Scope every FinancialReportService query by CompanyId (defense in depth)
Audit finding #7: most report queries relied on the global tenant query filter, which is bypassed for SuperAdmin users — so a SuperAdmin (or any multi-company account) running P&L / Balance Sheet / Trial Balance / aging / statements could pull data across companies. The cash-flow method was the only one doing it right (IgnoreQueryFilters + explicit CompanyId). Adds an explicit `CompanyId == companyId` predicate to every DB query across GetProfitAndLossAsync, GetBalanceSheetAsync, GetTrialBalanceAsync, GetArAgingAsync, GetSalesAndIncomeAsync, GetBalanceReconciliationAsync, and the customer/vendor statements (Sales Tax and AP aging already had it). The remaining in-memory filters operate on collections already loaded with the predicate. Matches the repo's standing rule (explicit CompanyId on every query, never the global filter alone). Build clean; 284 unit tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -89,7 +89,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
var isCash = accountingMethod == AccountingMethod.Cash;
|
||||
|
||||
var revenueAccounts = await _context.Accounts
|
||||
.Where(a => a.AccountType == AccountType.Revenue && a.IsActive)
|
||||
.Where(a => a.CompanyId == companyId && a.AccountType == AccountType.Revenue && a.IsActive)
|
||||
.ToDictionaryAsync(a => a.Id);
|
||||
|
||||
var revenueLines = new List<FinancialReportLine>();
|
||||
@@ -98,7 +98,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
{
|
||||
// Cash basis: total payments received in period (not split by revenue account)
|
||||
var cashRevenue = await _context.Payments
|
||||
.Where(p => p.PaymentDate >= from && p.PaymentDate <= toEnd
|
||||
.Where(p => p.CompanyId == companyId && p.PaymentDate >= from && p.PaymentDate <= toEnd
|
||||
&& p.Invoice.Status != InvoiceStatus.Voided)
|
||||
.SumAsync(p => (decimal?)p.Amount) ?? 0;
|
||||
if (cashRevenue > 0)
|
||||
@@ -106,7 +106,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// Cash refunds are cash paid back out — they reduce cash-basis revenue.
|
||||
var cashRefunds = await _context.Refunds
|
||||
.Where(r => !r.IsDeleted && r.RefundMethod != PaymentMethod.StoreCredit
|
||||
.Where(r => r.CompanyId == companyId && !r.IsDeleted && r.RefundMethod != PaymentMethod.StoreCredit
|
||||
&& r.RefundDate >= from && r.RefundDate <= toEnd)
|
||||
.SumAsync(r => (decimal?)r.Amount) ?? 0m;
|
||||
if (cashRefunds > 0)
|
||||
@@ -116,7 +116,8 @@ public class FinancialReportService : IFinancialReportService
|
||||
{
|
||||
// Accrual basis: revenue = invoice item amounts by invoice date
|
||||
var accrualRevenue = await _context.InvoiceItems
|
||||
.Where(ii => ii.RevenueAccountId != null
|
||||
.Where(ii => ii.CompanyId == companyId
|
||||
&& ii.RevenueAccountId != null
|
||||
&& ii.Invoice.Status != InvoiceStatus.Draft
|
||||
&& ii.Invoice.Status != InvoiceStatus.Voided
|
||||
&& ii.Invoice.InvoiceDate >= from && ii.Invoice.InvoiceDate <= toEnd)
|
||||
@@ -136,7 +137,8 @@ public class FinancialReportService : IFinancialReportService
|
||||
.OrderBy(l => l.AccountNumber));
|
||||
|
||||
var unlinkedRevenue = await _context.InvoiceItems
|
||||
.Where(ii => ii.RevenueAccountId == null
|
||||
.Where(ii => ii.CompanyId == companyId
|
||||
&& ii.RevenueAccountId == null
|
||||
&& ii.Invoice.Status != InvoiceStatus.Draft
|
||||
&& ii.Invoice.Status != InvoiceStatus.Voided
|
||||
&& ii.Invoice.InvoiceDate >= from && ii.Invoice.InvoiceDate <= toEnd)
|
||||
@@ -146,7 +148,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// Contra-revenue: discounts granted and credit memos applied reduce gross revenue.
|
||||
var periodDiscounts = await _context.Invoices
|
||||
.Where(i => i.Status != InvoiceStatus.Draft && i.Status != InvoiceStatus.Voided
|
||||
.Where(i => i.CompanyId == companyId && i.Status != InvoiceStatus.Draft && i.Status != InvoiceStatus.Voided
|
||||
&& i.DiscountAmount > 0 && i.InvoiceDate >= from && i.InvoiceDate <= toEnd)
|
||||
.SumAsync(i => (decimal?)i.DiscountAmount) ?? 0m;
|
||||
// Credit-memo contra-revenue is recognized at issue (DR Sales Discounts). Net for the period =
|
||||
@@ -171,7 +173,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
// Cash refunds reverse the sale — the revenue portion is contra-revenue (the tax portion
|
||||
// relieves Sales Tax Payable, not revenue). Store-credit refunds are excluded (no GL posting).
|
||||
var periodRefunds = await _context.Refunds
|
||||
.Where(r => !r.IsDeleted && r.Invoice != null && r.RefundMethod != PaymentMethod.StoreCredit
|
||||
.Where(r => r.CompanyId == companyId && !r.IsDeleted && r.Invoice != null && r.RefundMethod != PaymentMethod.StoreCredit
|
||||
&& r.RefundDate >= from && r.RefundDate <= toEnd)
|
||||
.Select(r => new { r.Amount, r.Invoice!.TaxAmount, r.Invoice.Total })
|
||||
.ToListAsync();
|
||||
@@ -186,7 +188,8 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// GC sales are deferred to GC Liability at issuance; revenue is recognized on redemption.
|
||||
var periodGcReclassified = await _context.InvoiceItems
|
||||
.Where(ii => ii.IsGiftCertificate
|
||||
.Where(ii => ii.CompanyId == companyId
|
||||
&& ii.IsGiftCertificate
|
||||
&& ii.Invoice.Status != InvoiceStatus.Draft
|
||||
&& ii.Invoice.Status != InvoiceStatus.Voided
|
||||
&& ii.Invoice.InvoiceDate >= from && ii.Invoice.InvoiceDate <= toEnd)
|
||||
@@ -201,7 +204,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// Voided GCs with remaining balance are breakage income (liability extinguished).
|
||||
var periodGcBreakage = await _context.GiftCertificates
|
||||
.Where(gc => !gc.IsDeleted && gc.Status == GiftCertificateStatus.Voided
|
||||
.Where(gc => gc.CompanyId == companyId && !gc.IsDeleted && gc.Status == GiftCertificateStatus.Voided
|
||||
&& gc.UpdatedAt >= from && gc.UpdatedAt <= toEnd
|
||||
&& gc.OriginalAmount > gc.RedeemedAmount)
|
||||
.SumAsync(gc => (decimal?)(gc.OriginalAmount - gc.RedeemedAmount)) ?? 0m;
|
||||
@@ -220,7 +223,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
if (isCash)
|
||||
{
|
||||
var cashExpenses = await _context.Expenses
|
||||
.Where(e => e.Date >= from && e.Date <= toEnd)
|
||||
.Where(e => e.CompanyId == companyId && e.Date >= from && e.Date <= toEnd)
|
||||
.GroupBy(e => e.ExpenseAccountId)
|
||||
.Select(g => new { AccountId = g.Key, Amount = g.Sum(e => e.Amount) })
|
||||
.ToListAsync();
|
||||
@@ -229,7 +232,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// Pro-rate paid bill line items by payment fraction (bill total may be partial)
|
||||
var paidBillLines = await _context.BillPayments
|
||||
.Where(bp => bp.PaymentDate >= from && bp.PaymentDate <= toEnd)
|
||||
.Where(bp => bp.CompanyId == companyId && bp.PaymentDate >= from && bp.PaymentDate <= toEnd)
|
||||
.Include(bp => bp.Bill).ThenInclude(b => b.LineItems)
|
||||
.ToListAsync();
|
||||
foreach (var bp in paidBillLines)
|
||||
@@ -242,7 +245,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
else
|
||||
{
|
||||
var accrualExpenses = await _context.Expenses
|
||||
.Where(e => e.Date >= from && e.Date <= toEnd)
|
||||
.Where(e => e.CompanyId == companyId && e.Date >= from && e.Date <= toEnd)
|
||||
.GroupBy(e => e.ExpenseAccountId)
|
||||
.Select(g => new { AccountId = g.Key, Amount = g.Sum(e => e.Amount) })
|
||||
.ToListAsync();
|
||||
@@ -250,7 +253,8 @@ public class FinancialReportService : IFinancialReportService
|
||||
expenseAmounts[e.AccountId] = expenseAmounts.GetValueOrDefault(e.AccountId) + e.Amount;
|
||||
|
||||
var accrualBillLines = await _context.BillLineItems
|
||||
.Where(bli => bli.AccountId != null
|
||||
.Where(bli => bli.CompanyId == companyId
|
||||
&& bli.AccountId != null
|
||||
&& bli.Bill.Status != BillStatus.Draft
|
||||
&& bli.Bill.Status != BillStatus.Voided
|
||||
&& bli.Bill.BillDate >= from && bli.Bill.BillDate <= toEnd)
|
||||
@@ -262,7 +266,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
}
|
||||
|
||||
var expAccounts = await _context.Accounts
|
||||
.Where(a => (a.AccountType == AccountType.Expense || a.AccountType == AccountType.CostOfGoods) && a.IsActive)
|
||||
.Where(a => a.CompanyId == companyId && (a.AccountType == AccountType.Expense || a.AccountType == AccountType.CostOfGoods) && a.IsActive)
|
||||
.ToDictionaryAsync(a => a.Id);
|
||||
|
||||
var cogsLines = new List<FinancialReportLine>();
|
||||
@@ -302,7 +306,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
// Pre-compute balance contributions per account (batch GROUP BY queries avoid N+1)
|
||||
|
||||
var depositsByAcct = await _context.Payments
|
||||
.Where(p => p.PaymentDate <= asOfEnd && p.DepositAccountId != null
|
||||
.Where(p => p.CompanyId == companyId && p.PaymentDate <= asOfEnd && p.DepositAccountId != null
|
||||
&& p.Invoice.Status != InvoiceStatus.Voided
|
||||
&& p.Invoice.Status != InvoiceStatus.WrittenOff)
|
||||
.GroupBy(p => p.DepositAccountId!.Value)
|
||||
@@ -310,38 +314,38 @@ public class FinancialReportService : IFinancialReportService
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amount);
|
||||
|
||||
var expFromByAcct = await _context.Expenses
|
||||
.Where(e => e.Date <= asOfEnd)
|
||||
.Where(e => e.CompanyId == companyId && e.Date <= asOfEnd)
|
||||
.GroupBy(e => e.PaymentAccountId)
|
||||
.Select(g => new { Id = g.Key, Amount = g.Sum(e => e.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amount);
|
||||
|
||||
var bpFromByAcct = await _context.BillPayments
|
||||
.Where(bp => bp.PaymentDate <= asOfEnd)
|
||||
.Where(bp => bp.CompanyId == companyId && bp.PaymentDate <= asOfEnd)
|
||||
.GroupBy(bp => bp.BankAccountId)
|
||||
.Select(g => new { Id = g.Key, Amount = g.Sum(bp => bp.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amount);
|
||||
|
||||
var billsByApAcct = await _context.Bills
|
||||
.Where(b => b.Status != BillStatus.Draft && b.Status != BillStatus.Voided && b.BillDate <= asOfEnd)
|
||||
.Where(b => b.CompanyId == companyId && b.Status != BillStatus.Draft && b.Status != BillStatus.Voided && b.BillDate <= asOfEnd)
|
||||
.GroupBy(b => b.APAccountId)
|
||||
.Select(g => new { Id = g.Key, Amount = g.Sum(b => b.Total) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amount);
|
||||
|
||||
var bpByApAcct = await _context.BillPayments
|
||||
.Where(bp => bp.PaymentDate <= asOfEnd)
|
||||
.Where(bp => bp.CompanyId == companyId && bp.PaymentDate <= asOfEnd)
|
||||
.GroupBy(bp => bp.Bill.APAccountId)
|
||||
.Select(g => new { Id = g.Key, Amount = g.Sum(bp => bp.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amount);
|
||||
|
||||
// AP: vendor credit applications reduce AP (DR side) when matched against specific bills.
|
||||
var vcByApAcctBs = await _context.VendorCreditApplications
|
||||
.Where(vca => vca.AppliedDate <= asOfEnd)
|
||||
.Where(vca => vca.CompanyId == companyId && vca.AppliedDate <= asOfEnd)
|
||||
.GroupBy(vca => vca.VendorCredit.APAccountId)
|
||||
.Select(g => new { Id = g.Key, Amount = g.Sum(vca => vca.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amount);
|
||||
|
||||
var taxByAcct = await _context.Invoices
|
||||
.Where(i => i.SalesTaxAccountId != null && i.TaxAmount > 0
|
||||
.Where(i => i.CompanyId == companyId && i.SalesTaxAccountId != null && i.TaxAmount > 0
|
||||
&& i.Status != InvoiceStatus.Draft && i.Status != InvoiceStatus.Voided
|
||||
&& i.InvoiceDate <= asOfEnd)
|
||||
.GroupBy(i => i.SalesTaxAccountId!.Value)
|
||||
@@ -349,16 +353,16 @@ public class FinancialReportService : IFinancialReportService
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amount);
|
||||
|
||||
var arDebits = await _context.Invoices
|
||||
.Where(i => i.Status != InvoiceStatus.Draft && i.Status != InvoiceStatus.Voided && i.InvoiceDate <= asOfEnd)
|
||||
.Where(i => i.CompanyId == companyId && i.Status != InvoiceStatus.Draft && i.Status != InvoiceStatus.Voided && i.InvoiceDate <= asOfEnd)
|
||||
.SumAsync(i => (decimal?)i.Total) ?? 0;
|
||||
var arCredits = await _context.Payments
|
||||
.Where(p => p.PaymentDate <= asOfEnd
|
||||
.Where(p => p.CompanyId == companyId && p.PaymentDate <= asOfEnd
|
||||
&& p.Invoice.Status != InvoiceStatus.Voided
|
||||
&& p.Invoice.Status != InvoiceStatus.WrittenOff)
|
||||
.SumAsync(p => (decimal?)p.Amount) ?? 0;
|
||||
// Credit memo applications reduce open AR (CR AR when a credit is applied to an invoice).
|
||||
var cmAppliedBs = await _context.CreditMemoApplications
|
||||
.Where(a => a.AppliedDate <= asOfEnd && a.Invoice.Status != InvoiceStatus.Voided)
|
||||
.Where(a => a.CompanyId == companyId && a.AppliedDate <= asOfEnd && a.Invoice.Status != InvoiceStatus.Voided)
|
||||
.SumAsync(a => (decimal?)a.AmountApplied) ?? 0;
|
||||
arCredits += cmAppliedBs;
|
||||
|
||||
@@ -369,7 +373,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
.Where(m => m.CompanyId == companyId && m.Status != CreditMemoStatus.Voided && m.IssueDate <= asOfEnd)
|
||||
.SumAsync(m => (decimal?)m.Amount) ?? 0m;
|
||||
var cmAppliedNonVoidedBs = await _context.CreditMemoApplications
|
||||
.Where(a => a.AppliedDate <= asOfEnd && a.Invoice.Status != InvoiceStatus.Voided
|
||||
.Where(a => a.CompanyId == companyId && a.AppliedDate <= asOfEnd && a.Invoice.Status != InvoiceStatus.Voided
|
||||
&& a.CreditMemo.Status != CreditMemoStatus.Voided)
|
||||
.SumAsync(a => (decimal?)a.AmountApplied) ?? 0m;
|
||||
var cmContraRevenueBs = cmIssuedNonVoidedBs + (cmAppliedBs - cmAppliedNonVoidedBs);
|
||||
@@ -380,7 +384,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
// tax portion relieves Sales Tax Payable, cash leaves the bank (refundsByAcctBs). AR is untouched.
|
||||
// Store-credit refunds post via CreditMemo, not the GL, so are excluded.
|
||||
var saleReversingRefundsBs = await _context.Refunds
|
||||
.Where(r => r.RefundDate <= asOfEnd && !r.IsDeleted && r.Invoice != null
|
||||
.Where(r => r.CompanyId == companyId && r.RefundDate <= asOfEnd && !r.IsDeleted && r.Invoice != null
|
||||
&& r.RefundMethod != PaymentMethod.StoreCredit)
|
||||
.Select(r => new { r.Amount, r.Invoice!.TaxAmount, r.Invoice.Total, r.Invoice.SalesTaxAccountId })
|
||||
.ToListAsync();
|
||||
@@ -396,14 +400,14 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// Refunds by bank account: money that left the account (CR to checking/bank).
|
||||
var refundsByAcctBs = await _context.Refunds
|
||||
.Where(r => r.RefundDate <= asOfEnd && !r.IsDeleted && r.DepositAccountId != null)
|
||||
.Where(r => r.CompanyId == companyId && r.RefundDate <= asOfEnd && !r.IsDeleted && r.DepositAccountId != null)
|
||||
.GroupBy(r => r.DepositAccountId!.Value)
|
||||
.Select(g => new { Id = g.Key, Amount = g.Sum(r => r.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amount);
|
||||
|
||||
// Deposits by bank account: cash received at deposit recording time (DR bank).
|
||||
var depositsByAcctDepBs = await _context.Deposits
|
||||
.Where(d => !d.IsDeleted && d.DepositAccountId != null && d.ReceivedDate <= asOfEnd)
|
||||
.Where(d => d.CompanyId == companyId && !d.IsDeleted && d.DepositAccountId != null && d.ReceivedDate <= asOfEnd)
|
||||
.GroupBy(d => d.DepositAccountId!.Value)
|
||||
.Select(g => new { Id = g.Key, Amount = g.Sum(d => d.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amount);
|
||||
@@ -414,11 +418,11 @@ public class FinancialReportService : IFinancialReportService
|
||||
.Select(a => (int?)a.Id).FirstOrDefaultAsync();
|
||||
var custDepositsCreditsBs = custDepositsAcctIdBs.HasValue
|
||||
? (await _context.Deposits
|
||||
.Where(d => !d.IsDeleted && d.ReceivedDate <= asOfEnd)
|
||||
.Where(d => d.CompanyId == companyId && !d.IsDeleted && d.ReceivedDate <= asOfEnd)
|
||||
.SumAsync(d => (decimal?)d.Amount) ?? 0m) : 0m;
|
||||
var custDepositsDebitsBs = custDepositsAcctIdBs.HasValue
|
||||
? (await _context.Deposits
|
||||
.Where(d => !d.IsDeleted && d.AppliedToInvoiceId != null && d.AppliedDate <= asOfEnd)
|
||||
.Where(d => d.CompanyId == companyId && !d.IsDeleted && d.AppliedToInvoiceId != null && d.AppliedDate <= asOfEnd)
|
||||
.SumAsync(d => (decimal?)d.Amount) ?? 0m) : 0m;
|
||||
|
||||
// Gift Certificate Liability (2500): balance driven by GC issuances, redemptions, and voids.
|
||||
@@ -427,14 +431,14 @@ public class FinancialReportService : IFinancialReportService
|
||||
.Select(a => (int?)a.Id).FirstOrDefaultAsync();
|
||||
var gcLiabilityCreditsBs = gcLiabilityAcctIdBs.HasValue
|
||||
? (await _context.GiftCertificates
|
||||
.Where(gc => !gc.IsDeleted && gc.IssueDate <= asOfEnd)
|
||||
.Where(gc => gc.CompanyId == companyId && !gc.IsDeleted && gc.IssueDate <= asOfEnd)
|
||||
.SumAsync(gc => (decimal?)gc.OriginalAmount) ?? 0m) : 0m;
|
||||
var gcLiabilityDebitsBs = gcLiabilityAcctIdBs.HasValue
|
||||
? ((await _context.GiftCertificateRedemptions
|
||||
.Where(r => !r.IsDeleted && r.RedeemedDate <= asOfEnd)
|
||||
.Where(r => r.CompanyId == companyId && !r.IsDeleted && r.RedeemedDate <= asOfEnd)
|
||||
.SumAsync(r => (decimal?)r.AmountRedeemed) ?? 0m)
|
||||
+ (await _context.GiftCertificates
|
||||
.Where(gc => !gc.IsDeleted && gc.Status == GiftCertificateStatus.Voided
|
||||
.Where(gc => gc.CompanyId == companyId && !gc.IsDeleted && gc.Status == GiftCertificateStatus.Voided
|
||||
&& gc.UpdatedAt <= asOfEnd && gc.OriginalAmount > gc.RedeemedAmount)
|
||||
.SumAsync(gc => (decimal?)(gc.OriginalAmount - gc.RedeemedAmount)) ?? 0m)) : 0m;
|
||||
|
||||
@@ -443,21 +447,21 @@ public class FinancialReportService : IFinancialReportService
|
||||
// plus (5) the net effect of any posted journal entries on revenue/expense/COGS accounts
|
||||
// (accruals, depreciation, year-end closes, and other adjustments not in the tables above).
|
||||
var lifetimeRevenue = await _context.InvoiceItems
|
||||
.Where(ii => ii.Invoice.Status != InvoiceStatus.Draft && ii.Invoice.Status != InvoiceStatus.Voided && ii.Invoice.InvoiceDate <= asOfEnd)
|
||||
.Where(ii => ii.CompanyId == companyId && ii.Invoice.Status != InvoiceStatus.Draft && ii.Invoice.Status != InvoiceStatus.Voided && ii.Invoice.InvoiceDate <= asOfEnd)
|
||||
.SumAsync(ii => (decimal?)ii.TotalPrice) ?? 0;
|
||||
var lifetimeDiscounts = isCash ? 0m
|
||||
: (await _context.Invoices
|
||||
.Where(i => i.Status != InvoiceStatus.Draft && i.Status != InvoiceStatus.Voided
|
||||
.Where(i => i.CompanyId == companyId && i.Status != InvoiceStatus.Draft && i.Status != InvoiceStatus.Voided
|
||||
&& i.DiscountAmount > 0 && i.InvoiceDate <= asOfEnd)
|
||||
.SumAsync(i => (decimal?)i.DiscountAmount) ?? 0m);
|
||||
// Credit memos are contra-revenue recognized at issue (DR Sales Discounts). Net revenue is
|
||||
// reduced by the issued amount (active memos in full + applied portion of voided memos).
|
||||
var lifetimeCreditMemos = isCash ? 0m : cmContraRevenueBs;
|
||||
var lifetimeDirectExp = await _context.Expenses
|
||||
.Where(e => e.Date <= asOfEnd)
|
||||
.Where(e => e.CompanyId == companyId && e.Date <= asOfEnd)
|
||||
.SumAsync(e => (decimal?)e.Amount) ?? 0;
|
||||
var lifetimeBillCosts = await _context.BillLineItems
|
||||
.Where(bli => bli.Bill.Status != BillStatus.Draft && bli.Bill.Status != BillStatus.Voided && bli.Bill.BillDate <= asOfEnd)
|
||||
.Where(bli => bli.CompanyId == companyId && bli.Bill.Status != BillStatus.Draft && bli.Bill.Status != BillStatus.Voided && bli.Bill.BillDate <= asOfEnd)
|
||||
.SumAsync(bli => (decimal?)bli.Amount) ?? 0;
|
||||
|
||||
// JE net effect on revenue accounts (positive = additional revenue recognised via manual JE)
|
||||
@@ -489,14 +493,14 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// GC items sold via invoices are reclassified to GC Liability and not yet earned income.
|
||||
var lifetimeGcReclassified = await _context.InvoiceItems
|
||||
.Where(ii => ii.IsGiftCertificate
|
||||
.Where(ii => ii.CompanyId == companyId && ii.IsGiftCertificate
|
||||
&& ii.Invoice.Status != InvoiceStatus.Draft
|
||||
&& ii.Invoice.Status != InvoiceStatus.Voided
|
||||
&& ii.Invoice.InvoiceDate <= asOfEnd)
|
||||
.SumAsync(ii => (decimal?)ii.TotalPrice) ?? 0m;
|
||||
// Voided GCs with remaining balance become breakage income (the liability is extinguished).
|
||||
var lifetimeGcBreakage = await _context.GiftCertificates
|
||||
.Where(gc => !gc.IsDeleted && gc.Status == GiftCertificateStatus.Voided
|
||||
.Where(gc => gc.CompanyId == companyId && !gc.IsDeleted && gc.Status == GiftCertificateStatus.Voided
|
||||
&& gc.UpdatedAt <= asOfEnd && gc.OriginalAmount > gc.RedeemedAmount)
|
||||
.SumAsync(gc => (decimal?)(gc.OriginalAmount - gc.RedeemedAmount)) ?? 0m;
|
||||
|
||||
@@ -511,7 +515,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
- jeExpNet;
|
||||
|
||||
var accounts = await _context.Accounts
|
||||
.Where(a => a.IsActive)
|
||||
.Where(a => a.CompanyId == companyId && a.IsActive)
|
||||
.OrderBy(a => a.AccountNumber)
|
||||
.ToListAsync();
|
||||
|
||||
@@ -619,7 +623,8 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
var openInvoices = await _context.Invoices
|
||||
.Include(i => i.Customer)
|
||||
.Where(i => i.Status != InvoiceStatus.Draft
|
||||
.Where(i => i.CompanyId == companyId
|
||||
&& i.Status != InvoiceStatus.Draft
|
||||
&& i.Status != InvoiceStatus.Voided
|
||||
&& i.Status != InvoiceStatus.Paid
|
||||
&& i.InvoiceDate <= asOfEnd
|
||||
@@ -699,14 +704,15 @@ public class FinancialReportService : IFinancialReportService
|
||||
var invoices = await _context.Invoices
|
||||
.Include(i => i.Customer)
|
||||
.Include(i => i.Payments)
|
||||
.Where(i => i.Status != InvoiceStatus.Draft
|
||||
.Where(i => i.CompanyId == companyId
|
||||
&& i.Status != InvoiceStatus.Draft
|
||||
&& i.Status != InvoiceStatus.Voided
|
||||
&& i.InvoiceDate >= from && i.InvoiceDate <= toEnd)
|
||||
.OrderBy(i => i.InvoiceDate)
|
||||
.ToListAsync();
|
||||
|
||||
var collectedInPeriod = await _context.Payments
|
||||
.Where(p => p.PaymentDate >= from && p.PaymentDate <= toEnd)
|
||||
.Where(p => p.CompanyId == companyId && p.PaymentDate >= from && p.PaymentDate <= toEnd)
|
||||
.SumAsync(p => (decimal?)p.Amount) ?? 0;
|
||||
|
||||
var byCustomer = invoices
|
||||
@@ -971,7 +977,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// Bank/cash: customer payments deposited here (DR)
|
||||
var depositsByAcct = await _context.Payments
|
||||
.Where(p => p.PaymentDate <= asOfEnd && p.DepositAccountId != null
|
||||
.Where(p => p.CompanyId == companyId && p.PaymentDate <= asOfEnd && p.DepositAccountId != null
|
||||
&& p.Invoice.Status != InvoiceStatus.Voided
|
||||
&& p.Invoice.Status != InvoiceStatus.WrittenOff)
|
||||
.GroupBy(p => p.DepositAccountId!.Value)
|
||||
@@ -981,42 +987,42 @@ public class FinancialReportService : IFinancialReportService
|
||||
// AP: vendor credit applications reduce AP (DR) — credits are applied when a vendor
|
||||
// issues a credit note and it is matched against a specific bill.
|
||||
var vcByApAcct = await _context.VendorCreditApplications
|
||||
.Where(vca => vca.AppliedDate <= asOfEnd)
|
||||
.Where(vca => vca.CompanyId == companyId && vca.AppliedDate <= asOfEnd)
|
||||
.GroupBy(vca => vca.VendorCredit.APAccountId)
|
||||
.Select(g => new { Id = g.Key, Amt = g.Sum(vca => vca.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amt);
|
||||
|
||||
// Bank/cash: expenses paid from here (CR)
|
||||
var expFromByAcct = await _context.Expenses
|
||||
.Where(e => e.Date <= asOfEnd)
|
||||
.Where(e => e.CompanyId == companyId && e.Date <= asOfEnd)
|
||||
.GroupBy(e => e.PaymentAccountId)
|
||||
.Select(g => new { Id = g.Key, Amt = g.Sum(e => e.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amt);
|
||||
|
||||
// Bank/cash: bill payments made from here (CR)
|
||||
var bpFromByAcct = await _context.BillPayments
|
||||
.Where(bp => bp.PaymentDate <= asOfEnd)
|
||||
.Where(bp => bp.CompanyId == companyId && bp.PaymentDate <= asOfEnd)
|
||||
.GroupBy(bp => bp.BankAccountId)
|
||||
.Select(g => new { Id = g.Key, Amt = g.Sum(bp => bp.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amt);
|
||||
|
||||
// AP: bills increase AP (CR)
|
||||
var billsByApAcct = await _context.Bills
|
||||
.Where(b => b.Status != BillStatus.Draft && b.Status != BillStatus.Voided && b.BillDate <= asOfEnd)
|
||||
.Where(b => b.CompanyId == companyId && b.Status != BillStatus.Draft && b.Status != BillStatus.Voided && b.BillDate <= asOfEnd)
|
||||
.GroupBy(b => b.APAccountId)
|
||||
.Select(g => new { Id = g.Key, Amt = g.Sum(b => b.Total) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amt);
|
||||
|
||||
// AP: bill payments reduce AP (DR)
|
||||
var bpByApAcct = await _context.BillPayments
|
||||
.Where(bp => bp.PaymentDate <= asOfEnd)
|
||||
.Where(bp => bp.CompanyId == companyId && bp.PaymentDate <= asOfEnd)
|
||||
.GroupBy(bp => bp.Bill.APAccountId)
|
||||
.Select(g => new { Id = g.Key, Amt = g.Sum(bp => bp.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amt);
|
||||
|
||||
// Tax liability: sales tax collected (CR)
|
||||
var taxByAcct = await _context.Invoices
|
||||
.Where(i => i.SalesTaxAccountId != null && i.TaxAmount > 0
|
||||
.Where(i => i.CompanyId == companyId && i.SalesTaxAccountId != null && i.TaxAmount > 0
|
||||
&& i.Status != InvoiceStatus.Draft && i.Status != InvoiceStatus.Voided
|
||||
&& i.InvoiceDate <= asOfEnd)
|
||||
.GroupBy(i => i.SalesTaxAccountId!.Value)
|
||||
@@ -1025,7 +1031,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// Revenue accounts: invoice line items (CR)
|
||||
var revenueByAcct = await _context.InvoiceItems
|
||||
.Where(ii => ii.RevenueAccountId != null
|
||||
.Where(ii => ii.CompanyId == companyId && ii.RevenueAccountId != null
|
||||
&& ii.Invoice.Status != InvoiceStatus.Draft
|
||||
&& ii.Invoice.Status != InvoiceStatus.Voided
|
||||
&& ii.Invoice.InvoiceDate <= asOfEnd)
|
||||
@@ -1035,14 +1041,14 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// Expense accounts: direct expenses (DR)
|
||||
var expenseByAcct = await _context.Expenses
|
||||
.Where(e => e.Date <= asOfEnd)
|
||||
.Where(e => e.CompanyId == companyId && e.Date <= asOfEnd)
|
||||
.GroupBy(e => e.ExpenseAccountId)
|
||||
.Select(g => new { Id = g.Key, Amt = g.Sum(e => e.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amt);
|
||||
|
||||
// Expense/COGS accounts: vendor bill line items (DR)
|
||||
var billLinesByAcct = await _context.BillLineItems
|
||||
.Where(bli => bli.AccountId != null
|
||||
.Where(bli => bli.CompanyId == companyId && bli.AccountId != null
|
||||
&& bli.Bill.Status != BillStatus.Draft
|
||||
&& bli.Bill.Status != BillStatus.Voided
|
||||
&& bli.Bill.BillDate <= asOfEnd)
|
||||
@@ -1064,7 +1070,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
var cmApplied = await _context.CreditMemoApplications
|
||||
.Where(a => a.AppliedDate <= asOfEnd
|
||||
.Where(a => a.CompanyId == companyId && a.AppliedDate <= asOfEnd
|
||||
&& a.Invoice.Status != InvoiceStatus.Voided)
|
||||
.SumAsync(a => (decimal?)a.AmountApplied) ?? 0m;
|
||||
|
||||
@@ -1076,7 +1082,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
.Where(m => m.CompanyId == companyId && m.Status != CreditMemoStatus.Voided && m.IssueDate <= asOfEnd)
|
||||
.SumAsync(m => (decimal?)m.Amount) ?? 0m;
|
||||
var cmAppliedNonVoided = await _context.CreditMemoApplications
|
||||
.Where(a => a.AppliedDate <= asOfEnd
|
||||
.Where(a => a.CompanyId == companyId && a.AppliedDate <= asOfEnd
|
||||
&& a.Invoice.Status != InvoiceStatus.Voided
|
||||
&& a.CreditMemo.Status != CreditMemoStatus.Voided)
|
||||
.SumAsync(a => (decimal?)a.AmountApplied) ?? 0m;
|
||||
@@ -1089,7 +1095,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
if (discountAcctId.HasValue)
|
||||
{
|
||||
var totalDiscounts = await _context.Invoices
|
||||
.Where(i => i.DiscountAmount > 0
|
||||
.Where(i => i.CompanyId == companyId && i.DiscountAmount > 0
|
||||
&& i.Status != InvoiceStatus.Draft
|
||||
&& i.Status != InvoiceStatus.Voided
|
||||
&& i.InvoiceDate <= asOfEnd)
|
||||
@@ -1100,14 +1106,14 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// JE lines: posted entries debit/credit all account types
|
||||
var jeDebitsByAcct = await _context.JournalEntryLines
|
||||
.Where(l => l.JournalEntry.Status == JournalEntryStatus.Posted
|
||||
.Where(l => l.CompanyId == companyId && l.JournalEntry.Status == JournalEntryStatus.Posted
|
||||
&& l.JournalEntry.EntryDate <= asOfEnd)
|
||||
.GroupBy(l => l.AccountId)
|
||||
.Select(g => new { Id = g.Key, Amt = g.Sum(l => l.DebitAmount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amt);
|
||||
|
||||
var jeCreditsByAcct = await _context.JournalEntryLines
|
||||
.Where(l => l.JournalEntry.Status == JournalEntryStatus.Posted
|
||||
.Where(l => l.CompanyId == companyId && l.JournalEntry.Status == JournalEntryStatus.Posted
|
||||
&& l.JournalEntry.EntryDate <= asOfEnd)
|
||||
.GroupBy(l => l.AccountId)
|
||||
.Select(g => new { Id = g.Key, Amt = g.Sum(l => l.CreditAmount) })
|
||||
@@ -1117,11 +1123,11 @@ public class FinancialReportService : IFinancialReportService
|
||||
// Credits include both cash payments and credit memo applications (which reduce open AR
|
||||
// when a customer credit is applied against a specific invoice).
|
||||
var arTotalDebits = await _context.Invoices
|
||||
.Where(i => i.Status != InvoiceStatus.Draft && i.Status != InvoiceStatus.Voided
|
||||
.Where(i => i.CompanyId == companyId && i.Status != InvoiceStatus.Draft && i.Status != InvoiceStatus.Voided
|
||||
&& i.InvoiceDate <= asOfEnd)
|
||||
.SumAsync(i => (decimal?)i.Total) ?? 0m;
|
||||
var arTotalCredits = await _context.Payments
|
||||
.Where(p => p.PaymentDate <= asOfEnd
|
||||
.Where(p => p.CompanyId == companyId && p.PaymentDate <= asOfEnd
|
||||
&& p.Invoice.Status != InvoiceStatus.Voided
|
||||
&& p.Invoice.Status != InvoiceStatus.WrittenOff)
|
||||
.SumAsync(p => (decimal?)p.Amount) ?? 0m;
|
||||
@@ -1131,7 +1137,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
// DR Sales Tax Payable (relieves the liability), cash → CR bank (refundsByAcct below). They no
|
||||
// longer touch AR. Store-credit refunds post via CreditMemo, not the GL, so are excluded.
|
||||
var saleReversingRefunds = await _context.Refunds
|
||||
.Where(r => r.RefundDate <= asOfEnd && !r.IsDeleted && r.Invoice != null
|
||||
.Where(r => r.CompanyId == companyId && r.RefundDate <= asOfEnd && !r.IsDeleted && r.Invoice != null
|
||||
&& r.RefundMethod != PaymentMethod.StoreCredit)
|
||||
.Select(r => new { r.Amount, r.Invoice!.TaxAmount, r.Invoice.Total, r.Invoice.SalesTaxAccountId })
|
||||
.ToListAsync();
|
||||
@@ -1152,7 +1158,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// Refunds by bank account: money leaving the account (CR to checking/bank).
|
||||
var refundsByAcct = await _context.Refunds
|
||||
.Where(r => r.RefundDate <= asOfEnd && !r.IsDeleted && r.DepositAccountId != null)
|
||||
.Where(r => r.CompanyId == companyId && r.RefundDate <= asOfEnd && !r.IsDeleted && r.DepositAccountId != null)
|
||||
.GroupBy(r => r.DepositAccountId!.Value)
|
||||
.Select(g => new { Id = g.Key, Amt = g.Sum(r => r.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amt);
|
||||
@@ -1160,7 +1166,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
// Deposits by bank account: cash received at deposit recording time (DR bank).
|
||||
// Deposit-sourced Payments have DepositAccountId = null, so there is no double-count with depositsByAcct.
|
||||
var depositsByAcctDep = await _context.Deposits
|
||||
.Where(d => !d.IsDeleted && d.DepositAccountId != null && d.ReceivedDate <= asOfEnd)
|
||||
.Where(d => d.CompanyId == companyId && !d.IsDeleted && d.DepositAccountId != null && d.ReceivedDate <= asOfEnd)
|
||||
.GroupBy(d => d.DepositAccountId!.Value)
|
||||
.Select(g => new { Id = g.Key, Amt = g.Sum(d => d.Amount) })
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Amt);
|
||||
@@ -1171,11 +1177,11 @@ public class FinancialReportService : IFinancialReportService
|
||||
.Select(a => (int?)a.Id).FirstOrDefaultAsync();
|
||||
var custDepositsCredits = custDepositsAcctId.HasValue
|
||||
? (await _context.Deposits
|
||||
.Where(d => !d.IsDeleted && d.ReceivedDate <= asOfEnd)
|
||||
.Where(d => d.CompanyId == companyId && !d.IsDeleted && d.ReceivedDate <= asOfEnd)
|
||||
.SumAsync(d => (decimal?)d.Amount) ?? 0m) : 0m;
|
||||
var custDepositsDebits = custDepositsAcctId.HasValue
|
||||
? (await _context.Deposits
|
||||
.Where(d => !d.IsDeleted && d.AppliedToInvoiceId != null && d.AppliedDate <= asOfEnd)
|
||||
.Where(d => d.CompanyId == companyId && !d.IsDeleted && d.AppliedToInvoiceId != null && d.AppliedDate <= asOfEnd)
|
||||
.SumAsync(d => (decimal?)d.Amount) ?? 0m) : 0m;
|
||||
|
||||
// Gift Certificate Liability (2500): balance driven by GC issuances, redemptions, and voids.
|
||||
@@ -1184,14 +1190,14 @@ public class FinancialReportService : IFinancialReportService
|
||||
.Select(a => (int?)a.Id).FirstOrDefaultAsync();
|
||||
var gcLiabilityCredits = gcLiabilityAcctId.HasValue
|
||||
? (await _context.GiftCertificates
|
||||
.Where(gc => !gc.IsDeleted && gc.IssueDate <= asOfEnd)
|
||||
.Where(gc => gc.CompanyId == companyId && !gc.IsDeleted && gc.IssueDate <= asOfEnd)
|
||||
.SumAsync(gc => (decimal?)gc.OriginalAmount) ?? 0m) : 0m;
|
||||
var gcLiabilityDebits = gcLiabilityAcctId.HasValue
|
||||
? ((await _context.GiftCertificateRedemptions
|
||||
.Where(r => !r.IsDeleted && r.RedeemedDate <= asOfEnd)
|
||||
.Where(r => r.CompanyId == companyId && !r.IsDeleted && r.RedeemedDate <= asOfEnd)
|
||||
.SumAsync(r => (decimal?)r.AmountRedeemed) ?? 0m)
|
||||
+ (await _context.GiftCertificates
|
||||
.Where(gc => !gc.IsDeleted && gc.Status == GiftCertificateStatus.Voided
|
||||
.Where(gc => gc.CompanyId == companyId && !gc.IsDeleted && gc.Status == GiftCertificateStatus.Voided
|
||||
&& gc.UpdatedAt <= asOfEnd && gc.OriginalAmount > gc.RedeemedAmount)
|
||||
.SumAsync(gc => (decimal?)(gc.OriginalAmount - gc.RedeemedAmount)) ?? 0m)) : 0m;
|
||||
|
||||
@@ -1337,17 +1343,17 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// Opening balance: invoiced − paid before period start
|
||||
var preInvoiced = await _context.Invoices
|
||||
.Where(i => i.CustomerId == customerId
|
||||
.Where(i => i.CompanyId == companyId && i.CustomerId == customerId
|
||||
&& i.Status != InvoiceStatus.Draft && i.Status != InvoiceStatus.Voided
|
||||
&& i.InvoiceDate < from)
|
||||
.SumAsync(i => (decimal?)i.Total) ?? 0;
|
||||
var prePaid = await _context.Payments
|
||||
.Where(p => p.Invoice.CustomerId == customerId
|
||||
.Where(p => p.CompanyId == companyId && p.Invoice.CustomerId == customerId
|
||||
&& p.Invoice.Status != InvoiceStatus.Voided
|
||||
&& p.PaymentDate < from)
|
||||
.SumAsync(p => (decimal?)p.Amount) ?? 0;
|
||||
var preCredits = await _context.CreditMemoApplications
|
||||
.Where(a => a.Invoice.CustomerId == customerId && a.AppliedDate < from)
|
||||
.Where(a => a.CompanyId == companyId && a.Invoice.CustomerId == customerId && a.AppliedDate < from)
|
||||
.SumAsync(a => (decimal?)a.AmountApplied) ?? 0;
|
||||
|
||||
var openingBalance = preInvoiced - prePaid - preCredits;
|
||||
@@ -1356,7 +1362,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
var lines = new List<StatementLineDto>();
|
||||
|
||||
var periodInvoices = await _context.Invoices
|
||||
.Where(i => i.CustomerId == customerId
|
||||
.Where(i => i.CompanyId == companyId && i.CustomerId == customerId
|
||||
&& i.Status != InvoiceStatus.Draft && i.Status != InvoiceStatus.Voided
|
||||
&& i.InvoiceDate >= from && i.InvoiceDate <= toEnd)
|
||||
.AsNoTracking().ToListAsync();
|
||||
@@ -1373,7 +1379,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
var periodPayments = await _context.Payments
|
||||
.Include(p => p.Invoice)
|
||||
.Where(p => p.Invoice.CustomerId == customerId
|
||||
.Where(p => p.CompanyId == companyId && p.Invoice.CustomerId == customerId
|
||||
&& p.Invoice.Status != InvoiceStatus.Voided
|
||||
&& p.PaymentDate >= from && p.PaymentDate <= toEnd)
|
||||
.AsNoTracking().ToListAsync();
|
||||
@@ -1391,7 +1397,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
var periodCredits = await _context.CreditMemoApplications
|
||||
.Include(a => a.Invoice)
|
||||
.Include(a => a.CreditMemo)
|
||||
.Where(a => a.Invoice.CustomerId == customerId
|
||||
.Where(a => a.CompanyId == companyId && a.Invoice.CustomerId == customerId
|
||||
&& a.AppliedDate >= from && a.AppliedDate <= toEnd)
|
||||
.AsNoTracking().ToListAsync();
|
||||
|
||||
@@ -1442,15 +1448,15 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
// Opening balance: bills − payments − credits before period start
|
||||
var preBills = await _context.Bills
|
||||
.Where(b => b.VendorId == vendorId
|
||||
.Where(b => b.CompanyId == companyId && b.VendorId == vendorId
|
||||
&& b.Status != BillStatus.Draft && b.Status != BillStatus.Voided
|
||||
&& b.BillDate < from)
|
||||
.SumAsync(b => (decimal?)b.Total) ?? 0;
|
||||
var prePayments = await _context.BillPayments
|
||||
.Where(bp => bp.Bill.VendorId == vendorId && bp.PaymentDate < from)
|
||||
.Where(bp => bp.CompanyId == companyId && bp.Bill.VendorId == vendorId && bp.PaymentDate < from)
|
||||
.SumAsync(bp => (decimal?)bp.Amount) ?? 0;
|
||||
var preVcApplied = await _context.VendorCreditApplications
|
||||
.Where(vca => vca.Bill.VendorId == vendorId && vca.AppliedDate < from)
|
||||
.Where(vca => vca.CompanyId == companyId && vca.Bill.VendorId == vendorId && vca.AppliedDate < from)
|
||||
.SumAsync(vca => (decimal?)vca.Amount) ?? 0;
|
||||
|
||||
var openingBalance = preBills - prePayments - preVcApplied;
|
||||
@@ -1458,7 +1464,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
var lines = new List<StatementLineDto>();
|
||||
|
||||
var periodBills = await _context.Bills
|
||||
.Where(b => b.VendorId == vendorId
|
||||
.Where(b => b.CompanyId == companyId && b.VendorId == vendorId
|
||||
&& b.Status != BillStatus.Draft && b.Status != BillStatus.Voided
|
||||
&& b.BillDate >= from && b.BillDate <= toEnd)
|
||||
.AsNoTracking().ToListAsync();
|
||||
@@ -1475,7 +1481,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
|
||||
var periodPayments = await _context.BillPayments
|
||||
.Include(bp => bp.Bill)
|
||||
.Where(bp => bp.Bill.VendorId == vendorId
|
||||
.Where(bp => bp.CompanyId == companyId && bp.Bill.VendorId == vendorId
|
||||
&& bp.PaymentDate >= from && bp.PaymentDate <= toEnd)
|
||||
.AsNoTracking().ToListAsync();
|
||||
|
||||
@@ -1492,7 +1498,7 @@ public class FinancialReportService : IFinancialReportService
|
||||
var periodVcApplied = await _context.VendorCreditApplications
|
||||
.Include(vca => vca.VendorCredit)
|
||||
.Include(vca => vca.Bill)
|
||||
.Where(vca => vca.Bill.VendorId == vendorId
|
||||
.Where(vca => vca.CompanyId == companyId && vca.Bill.VendorId == vendorId
|
||||
&& vca.AppliedDate >= from && vca.AppliedDate <= toEnd)
|
||||
.AsNoTracking().ToListAsync();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user