174 lines
6.0 KiB
C#
174 lines
6.0 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using System.ComponentModel.DataAnnotations;
|
|
using System.Globalization;
|
|
|
|
namespace BankSampahApp.Controllers.Main;
|
|
|
|
[Route("Main/[controller]/[action]")]
|
|
public class LaporanKeuanganController : Controller
|
|
{
|
|
private static readonly List<MonthlyTransactionSnapshot> _monthlyTransactions =
|
|
[
|
|
new(2025, 1, 12_500_000m, 18_200_000m),
|
|
new(2025, 2, 10_350_000m, 16_750_000m),
|
|
new(2025, 3, 9_800_000m, 17_150_000m),
|
|
new(2025, 4, 11_200_000m, 15_600_000m),
|
|
new(2025, 5, 12_200_000m, 18_900_000m),
|
|
new(2025, 6, 10_450_000m, 14_800_000m),
|
|
new(2025, 7, 9_900_000m, 19_750_000m),
|
|
new(2025, 8, 11_650_000m, 17_500_000m),
|
|
new(2025, 9, 12_400_000m, 18_350_000m),
|
|
new(2024, 10, 10_050_000m, 15_500_000m),
|
|
new(2024, 11, 11_250_000m, 16_200_000m),
|
|
new(2024, 12, 12_800_000m, 18_600_000m)
|
|
];
|
|
|
|
private static readonly List<ManualExpense> _manualExpenses =
|
|
[
|
|
new() { Id = 1, ExpenseDate = new DateTime(2025, 1, 12), Title = "Transport & Operasional", Amount = 1_200_000m, Notes = "Pengiriman sampah ke offtaker" },
|
|
new() { Id = 2, ExpenseDate = new DateTime(2025, 3, 8), Title = "Perawatan Timbangan", Amount = 800_000m, Notes = "Kalibrasi timbangan BSU" },
|
|
new() { Id = 3, ExpenseDate = new DateTime(2025, 5, 20), Title = "Konsumsi Sosialisasi", Amount = 450_000m, Notes = "Kegiatan edukasi warga" },
|
|
new() { Id = 4, ExpenseDate = new DateTime(2024, 11, 14), Title = "Biaya Listrik Gudang", Amount = 600_000m, Notes = "Tagihan bulan berjalan" }
|
|
];
|
|
|
|
public IActionResult Index()
|
|
{
|
|
var years = _monthlyTransactions
|
|
.Select(t => t.Year)
|
|
.Concat(_manualExpenses.Select(e => e.ExpenseDate.Year))
|
|
.Distinct()
|
|
.OrderByDescending(y => y)
|
|
.ToList();
|
|
|
|
if (!years.Any())
|
|
{
|
|
years.Add(DateTime.UtcNow.Year);
|
|
}
|
|
|
|
ViewBag.AvailableYears = years;
|
|
ViewBag.DefaultYear = years.First();
|
|
return View("~/Views/Main/LaporanKeuangan/Index.cshtml");
|
|
}
|
|
|
|
[HttpGet]
|
|
public IActionResult Table(int? year)
|
|
{
|
|
var selectedYear = year ?? GetLatestYear();
|
|
var rows = BuildRows(selectedYear);
|
|
var totalSaldo = rows.LastOrDefault()?.SaldoAkumulatif ?? 0m;
|
|
|
|
var data = rows.Select((row, index) => new
|
|
{
|
|
no = index + 1,
|
|
bulan = row.Bulan,
|
|
pembelian = row.Pembelian,
|
|
penjualan = row.Penjualan,
|
|
pengeluaran = row.PengeluaranLain,
|
|
labaRugi = row.LabaRugiBulanan,
|
|
saldo = row.SaldoAkumulatif,
|
|
isProfit = row.LabaRugiBulanan >= 0
|
|
});
|
|
|
|
return Json(new { data, totalSaldo });
|
|
}
|
|
|
|
[HttpPost]
|
|
[ValidateAntiForgeryToken]
|
|
public IActionResult TambahPengeluaran([FromForm] PengeluaranInput input)
|
|
{
|
|
if (!ModelState.IsValid || input.Nominal <= 0)
|
|
{
|
|
return BadRequest(new { message = "Data pengeluaran tidak valid" });
|
|
}
|
|
|
|
var newExpense = new ManualExpense
|
|
{
|
|
Id = _manualExpenses.Any() ? _manualExpenses.Max(x => x.Id) + 1 : 1,
|
|
ExpenseDate = input.Tanggal,
|
|
Title = input.NamaPengeluaran,
|
|
Amount = input.Nominal,
|
|
Notes = input.Keterangan ?? string.Empty
|
|
};
|
|
|
|
_manualExpenses.Add(newExpense);
|
|
return Json(new { success = true });
|
|
}
|
|
|
|
private static List<FinancialRow> BuildRows(int year)
|
|
{
|
|
var rows = new List<FinancialRow>();
|
|
var culture = new CultureInfo("id-ID");
|
|
decimal saldoAkumulatif = 0m;
|
|
|
|
for (int month = 1; month <= 12; month++)
|
|
{
|
|
var baseData = _monthlyTransactions.FirstOrDefault(t => t.Year == year && t.Month == month);
|
|
var pembelian = baseData?.Pembelian ?? 0m;
|
|
var penjualan = baseData?.Penjualan ?? 0m;
|
|
var pengeluaranLain = _manualExpenses
|
|
.Where(e => e.ExpenseDate.Year == year && e.ExpenseDate.Month == month)
|
|
.Sum(e => e.Amount);
|
|
|
|
var labaRugi = penjualan - (pembelian + pengeluaranLain);
|
|
saldoAkumulatif += labaRugi;
|
|
|
|
rows.Add(new FinancialRow
|
|
{
|
|
Bulan = culture.DateTimeFormat.GetMonthName(month) + " " + year,
|
|
Pembelian = pembelian,
|
|
Penjualan = penjualan,
|
|
PengeluaranLain = pengeluaranLain,
|
|
LabaRugiBulanan = labaRugi,
|
|
SaldoAkumulatif = saldoAkumulatif
|
|
});
|
|
}
|
|
|
|
return rows;
|
|
}
|
|
|
|
private static int GetLatestYear()
|
|
{
|
|
return _monthlyTransactions.Select(t => t.Year)
|
|
.Concat(_manualExpenses.Select(e => e.ExpenseDate.Year))
|
|
.DefaultIfEmpty(DateTime.UtcNow.Year)
|
|
.Max();
|
|
}
|
|
|
|
private record MonthlyTransactionSnapshot(int Year, int Month, decimal Pembelian, decimal Penjualan);
|
|
|
|
private class ManualExpense
|
|
{
|
|
public int Id { get; set; }
|
|
public DateTime ExpenseDate { get; set; }
|
|
public string Title { get; set; } = string.Empty;
|
|
public decimal Amount { get; set; }
|
|
public string Notes { get; set; } = string.Empty;
|
|
}
|
|
|
|
public class PengeluaranInput
|
|
{
|
|
[Required]
|
|
public DateTime Tanggal { get; set; }
|
|
|
|
[Required]
|
|
[StringLength(150)]
|
|
public string NamaPengeluaran { get; set; } = string.Empty;
|
|
|
|
[Range(typeof(decimal), "0.01", "79228162514264337593543950335")]
|
|
public decimal Nominal { get; set; }
|
|
|
|
[StringLength(200)]
|
|
public string? Keterangan { get; set; }
|
|
}
|
|
|
|
private class FinancialRow
|
|
{
|
|
public string Bulan { get; set; } = string.Empty;
|
|
public decimal Pembelian { get; set; }
|
|
public decimal Penjualan { get; set; }
|
|
public decimal PengeluaranLain { get; set; }
|
|
public decimal LabaRugiBulanan { get; set; }
|
|
public decimal SaldoAkumulatif { get; set; }
|
|
}
|
|
}
|