Improvements for tax reporting
This commit is contained in:
parent
694f1476de
commit
56b1abcf54
|
|
@ -26,7 +26,7 @@ class TaxDetail
|
|||
public string $tax_status; // "collected", "pending", "refundable", "partially_paid", "adjustment"
|
||||
|
||||
// Adjustment-specific fields (used when tax_status is "adjustment")
|
||||
public ?string $adjustment_reason; // "invoice_cancelled", "tax_rate_change", "exemption_applied", "correction"
|
||||
public ?string $postal_code; // "invoice_cancelled", "tax_rate_change", "exemption_applied", "correction"
|
||||
public float $line_total;
|
||||
public float $total_tax;
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ class TaxDetail
|
|||
$this->tax_amount = $attributes['tax_amount'] ?? 0.0;
|
||||
$this->tax_status = $attributes['tax_status'] ?? 'pending';
|
||||
// Adjustment fields
|
||||
$this->adjustment_reason = $attributes['adjustment_reason'] ?? null;
|
||||
$this->postal_code = $attributes['postal_code'] ?? null;
|
||||
|
||||
$this->line_total = $attributes['line_total'] ?? 0.0;
|
||||
$this->total_tax = $attributes['total_tax'] ?? 0.0;
|
||||
|
|
@ -57,7 +57,7 @@ class TaxDetail
|
|||
'taxable_amount' => $this->taxable_amount,
|
||||
'tax_amount' => $this->tax_amount,
|
||||
'tax_status' => $this->tax_status,
|
||||
'adjustment_reason' => $this->adjustment_reason,
|
||||
'postal_code' => $this->postal_code,
|
||||
'line_total' => $this->line_total,
|
||||
'total_tax' => $this->total_tax,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -171,10 +171,10 @@ class InvoiceTransactionEventEntry
|
|||
|
||||
$previous_tax_details = $previous_transaction_event->metadata->tax_report->tax_details;
|
||||
|
||||
$postal_code = $invoice->client->postal_code;
|
||||
|
||||
foreach ($taxes as $tax) {
|
||||
$previousLine = collect($previous_tax_details)->where('tax_name', $tax['name'])->first() ?? null;
|
||||
nlog($previousLine);
|
||||
nlog($tax);
|
||||
|
||||
$tax_detail = [
|
||||
'tax_name' => $tax['name'],
|
||||
|
|
@ -183,12 +183,9 @@ nlog($tax);
|
|||
'total_tax' => $tax['total'],
|
||||
'taxable_amount' => ($tax['base_amount'] ?? $calc->getNetSubtotal()) - ($previousLine->line_total ?? 0),
|
||||
'tax_amount' => $tax['total'] - ($previousLine->total_tax ?? 0),
|
||||
// 'taxable_amount_adjustment' => ($tax['base_amount'] ?? $calc->getNetSubtotal()) - ($previousLine->taxable_amount ?? 0),
|
||||
// 'tax_amount_adjustment' => $tax['total'] - ($previousLine->tax_amount ?? 0),
|
||||
'postal_code' => $postal_code,
|
||||
];
|
||||
|
||||
nlog($tax_detail);
|
||||
|
||||
$details[] = $tax_detail;
|
||||
}
|
||||
|
||||
|
|
@ -229,15 +226,7 @@ nlog($tax);
|
|||
|
||||
$taxes = array_merge($calc->getTaxMap()->merge($calc->getTotalTaxMap())->toArray());
|
||||
|
||||
//If there is a previous transaction event, we need to consider the taxable amount.
|
||||
// $previous_transaction_event = TransactionEvent::where('event_id', TransactionEvent::INVOICE_UPDATED)
|
||||
// ->where('invoice_id', $invoice->id)
|
||||
// ->orderBy('timestamp', 'desc')
|
||||
// ->first();
|
||||
|
||||
if($this->paid_ratio == 0){
|
||||
// setup a 0/0 recorded
|
||||
}
|
||||
$postal_code = $invoice->client->postal_code;
|
||||
|
||||
foreach ($taxes as $tax) {
|
||||
$tax_detail = [
|
||||
|
|
@ -247,6 +236,8 @@ nlog($tax);
|
|||
'tax_amount' => ($tax['total'] * $this->paid_ratio * -1),
|
||||
'line_total' => $tax['base_amount'] * $this->paid_ratio * -1,
|
||||
'total_tax' => $tax['total'] * $this->paid_ratio * -1,
|
||||
'postal_code' => $postal_code,
|
||||
|
||||
];
|
||||
$details[] = $tax_detail;
|
||||
}
|
||||
|
|
@ -280,15 +271,8 @@ nlog($tax);
|
|||
|
||||
$taxes = array_merge($calc->getTaxMap()->merge($calc->getTotalTaxMap())->toArray());
|
||||
|
||||
//If there is a previous transaction event, we need to consider the taxable amount.
|
||||
// $previous_transaction_event = TransactionEvent::where('event_id', TransactionEvent::INVOICE_UPDATED)
|
||||
// ->where('invoice_id', $invoice->id)
|
||||
// ->orderBy('timestamp', 'desc')
|
||||
// ->first();
|
||||
$postal_code = $invoice->client->postal_code;
|
||||
|
||||
if($this->paid_ratio == 0){
|
||||
// setup a 0/0 recorded
|
||||
}
|
||||
|
||||
foreach ($taxes as $tax) {
|
||||
$tax_detail = [
|
||||
|
|
@ -298,6 +282,7 @@ nlog($tax);
|
|||
'tax_amount' => ($tax['total'] * $this->paid_ratio),
|
||||
'line_total' => $tax['base_amount'] * $this->paid_ratio,
|
||||
'total_tax' => $tax['total'] * $this->paid_ratio,
|
||||
'postal_code' => $postal_code,
|
||||
];
|
||||
$details[] = $tax_detail;
|
||||
}
|
||||
|
|
@ -330,6 +315,7 @@ nlog($tax);
|
|||
$details = [];
|
||||
|
||||
$taxes = array_merge($calc->getTaxMap()->merge($calc->getTotalTaxMap())->toArray());
|
||||
$postal_code = $invoice->client->postal_code;
|
||||
|
||||
foreach ($taxes as $tax) {
|
||||
$tax_detail = [
|
||||
|
|
@ -339,6 +325,7 @@ nlog($tax);
|
|||
'tax_amount' => $tax['total'] * -1,
|
||||
'line_total' => $tax['base_amount'] * -1,
|
||||
'total_tax' => $tax['total'] * -1,
|
||||
'postal_code' => $postal_code,
|
||||
];
|
||||
$details[] = $tax_detail;
|
||||
}
|
||||
|
|
@ -375,6 +362,7 @@ nlog($tax);
|
|||
$details = [];
|
||||
|
||||
$taxes = array_merge($calc->getTaxMap()->merge($calc->getTotalTaxMap())->toArray());
|
||||
$postal_code = $invoice->client->postal_code;
|
||||
|
||||
foreach ($taxes as $tax) {
|
||||
$tax_detail = [
|
||||
|
|
@ -384,6 +372,7 @@ nlog($tax);
|
|||
'tax_amount' => $tax['total'],
|
||||
'line_total' => $tax['base_amount'] ?? $calc->getNetSubtotal(),
|
||||
'total_tax' => $tax['total'],
|
||||
'postal_code' => $postal_code,
|
||||
];
|
||||
$details[] = $tax_detail;
|
||||
}
|
||||
|
|
@ -401,18 +390,5 @@ nlog($tax);
|
|||
]);
|
||||
|
||||
}
|
||||
|
||||
private function getTotalTaxPaid($invoice)
|
||||
{
|
||||
if($invoice->amount == 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
$total_paid = $this->payments->sum('amount') - $this->payments->sum('refunded');
|
||||
|
||||
return round($invoice->total_taxes * ($total_paid / $invoice->amount), 2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,15 +84,9 @@ class InvoiceTransactionEventEntryCash
|
|||
|
||||
$this->paid_ratio = $invoice->paid_to_date / $invoice->amount;
|
||||
|
||||
nlog("paid ratio => {$this->paid_ratio}");
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function calculateRatio(float $amount): float
|
||||
{
|
||||
return round($amount * $this->paid_ratio, 2);
|
||||
}
|
||||
|
||||
private function getMetadata($invoice)
|
||||
{
|
||||
|
||||
|
|
@ -108,6 +102,9 @@ class InvoiceTransactionEventEntryCash
|
|||
'tax_rate' => $tax['tax_rate'],
|
||||
'taxable_amount' => ($tax['base_amount'] ?? $calc->getNetSubtotal()) * $this->paid_ratio,
|
||||
'tax_amount' => $tax['total'] * $this->paid_ratio,
|
||||
'line_total' => $tax['base_amount'],
|
||||
'total_tax' => $tax['total'],
|
||||
'postal_code' => $invoice->client->postal_code,
|
||||
];
|
||||
$details[] = $tax_detail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class PaymentTransactionEventEntry implements ShouldQueue
|
|||
|
||||
public function handle()
|
||||
{
|
||||
nlog("set invoice adjustment => {$this->invoice_adjustment}");
|
||||
|
||||
try{
|
||||
$this->runLog();
|
||||
}
|
||||
|
|
@ -99,12 +99,9 @@ class PaymentTransactionEventEntry implements ShouldQueue
|
|||
->get()
|
||||
->filter(function($invoice){
|
||||
//only insert adjustment entries if we are after the end of the month!!
|
||||
nlog(Carbon::parse($invoice->date)->endOfMonth()->isBefore(now()->addSeconds($this->payment->company->timezone_offset())));
|
||||
return Carbon::parse($invoice->date)->endOfMonth()->isBefore(now()->addSeconds($this->payment->company->timezone_offset()));
|
||||
})
|
||||
->each(function($invoice){
|
||||
|
||||
// nlog(" I am inserting!!! ");
|
||||
$this->setPaidRatio($invoice);
|
||||
|
||||
//delete any other payment mutations here if this is a delete event, the refunds are redundant in this time period
|
||||
|
|
@ -156,44 +153,6 @@ class PaymentTransactionEventEntry implements ShouldQueue
|
|||
return $this;
|
||||
}
|
||||
|
||||
private function getRefundRatio(Invoice $invoice): float
|
||||
{
|
||||
// For partial refunds, calculate ratio based on what was previously paid
|
||||
// Get the previous transaction event to find the historical paid_to_date
|
||||
if ($this->invoice_adjustment <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the most recent transaction event to see what was previously recorded
|
||||
$previous_event = $invoice->transaction_events()
|
||||
->orderBy('id', 'desc')
|
||||
->first();
|
||||
|
||||
if ($previous_event && $previous_event->invoice_paid_to_date > 0) {
|
||||
// Ratio: refund_amount / previous_paid_to_date
|
||||
// This gives us the portion of the previous payment being refunded
|
||||
nlog("Using previous event: refund {$this->invoice_adjustment} / {$previous_event->invoice_paid_to_date}");
|
||||
return $this->invoice_adjustment / $previous_event->invoice_paid_to_date;
|
||||
}
|
||||
|
||||
// Fallback: calculate what paid_to_date was BEFORE this refund
|
||||
// Since the refund has already been processed, paid_to_date is already reduced
|
||||
// So: paid_to_date_before_refund = current_paid_to_date + refund_amount
|
||||
$paid_to_date_before = $invoice->paid_to_date + $this->invoice_adjustment;
|
||||
|
||||
if ($paid_to_date_before > 0) {
|
||||
nlog("No previous event: refund {$this->invoice_adjustment} / {$paid_to_date_before}");
|
||||
return $this->invoice_adjustment / $paid_to_date_before;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function calculateRatio(float $amount): float
|
||||
{
|
||||
return round($amount * $this->paid_ratio, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Existing tax details are not deleted, but pending taxes are set to 0
|
||||
*
|
||||
|
|
@ -224,6 +183,9 @@ class PaymentTransactionEventEntry implements ShouldQueue
|
|||
'tax_rate' => $tax['tax_rate'],
|
||||
'taxable_amount' => round($base_amount * $refund_ratio, 2) * -1,
|
||||
'tax_amount' => round($tax['total'] * $refund_ratio, 2) * -1,
|
||||
'line_total' => $base_amount,
|
||||
'total_tax' => $tax['total'],
|
||||
'postal_code' => $invoice->client->postal_code,
|
||||
];
|
||||
$details[] = $tax_detail;
|
||||
}
|
||||
|
|
@ -266,6 +228,9 @@ class PaymentTransactionEventEntry implements ShouldQueue
|
|||
'taxable_amount' => $base_amount * -1,
|
||||
'tax_amount' => $tax['total'] * -1,
|
||||
'tax_status' => 'payment_deleted',
|
||||
'line_total' => $base_amount,
|
||||
'total_tax' => $tax['total'],
|
||||
'postal_code' => $invoice->client->postal_code,
|
||||
];
|
||||
|
||||
$details[] = $tax_detail;
|
||||
|
|
@ -304,7 +269,7 @@ class PaymentTransactionEventEntry implements ShouldQueue
|
|||
|
||||
$total_paid = $this->payments->sum('amount') - $this->payments->sum('refunded');
|
||||
|
||||
nlog("total paid => {$total_paid} - total taxes => {$invoice->total_taxes} - amount => {$invoice->amount}");
|
||||
// nlog("total paid => {$total_paid} - total taxes => {$invoice->total_taxes} - amount => {$invoice->amount}");
|
||||
|
||||
return round($invoice->total_taxes * ($total_paid / $invoice->amount), 2);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ class InvoiceItemReportRow
|
|||
ctrans('texts.tax_amount'),
|
||||
ctrans('texts.taxable_amount'),
|
||||
ctrans('texts.status'),
|
||||
ctrans('texts.postal_code'),
|
||||
];
|
||||
|
||||
if ($regional_calculator) {
|
||||
|
|
@ -62,6 +63,7 @@ class InvoiceItemReportRow
|
|||
$this->tax_detail->tax_amount,
|
||||
$this->tax_detail->taxable_amount,
|
||||
$this->status->label(),
|
||||
$this->tax_detail->postal_code,
|
||||
];
|
||||
|
||||
return $this->appendRegionalColumns($row, $this->tax_detail->tax_amount);
|
||||
|
|
@ -80,6 +82,7 @@ class InvoiceItemReportRow
|
|||
$this->tax_detail->tax_amount,
|
||||
$this->tax_detail->taxable_amount,
|
||||
$this->status->label(),
|
||||
$this->tax_detail->postal_code,
|
||||
];
|
||||
|
||||
return $this->appendRegionalColumns($row, $this->tax_detail->tax_amount);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class TaxDetail
|
|||
public float $tax_amount,
|
||||
public float $line_total = 0,
|
||||
public float $total_tax = 0,
|
||||
public string $postal_code = '',
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
|
@ -38,6 +39,7 @@ class TaxDetail
|
|||
tax_amount: $metadata->tax_amount ?? 0,
|
||||
line_total: $metadata->line_total ?? 0,
|
||||
total_tax: $metadata->total_tax ?? 0,
|
||||
postal_code: $metadata->postal_code ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -126,6 +128,7 @@ class TaxDetail
|
|||
'tax_amount' => $this->tax_amount,
|
||||
'line_total' => $this->line_total,
|
||||
'total_tax' => $this->total_tax,
|
||||
'postal_code' => $this->postal_code,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ class TaxPeriodReport extends BaseExport
|
|||
{
|
||||
$currency = $this->company->currency();
|
||||
|
||||
$formatted = number_format(9990.00, $currency->precision, $currency->decimal_separator, $currency->thousand_separator);
|
||||
$formatted = number_format(90.00, $currency->precision, $currency->decimal_separator, $currency->thousand_separator);
|
||||
$formatted = str_replace('9', '#', $formatted);
|
||||
$this->number_format = $formatted;
|
||||
|
||||
|
|
@ -356,8 +356,10 @@ class TaxPeriodReport extends BaseExport
|
|||
public function createInvoiceSummarySheet()
|
||||
{
|
||||
|
||||
$worksheet_title = $this->cash_accounting ? ctrans('texts.cash_accounting') : ctrans('texts.accrual_accounting');
|
||||
|
||||
$worksheet = $this->spreadsheet->createSheet();
|
||||
$worksheet->setTitle(ctrans('texts.invoice')." ".ctrans('texts.cash_vs_accrual'));
|
||||
$worksheet->setTitle(substr(ctrans('texts.invoice')." ".$worksheet_title, 0, 30));
|
||||
$worksheet->fromArray($this->data['invoices'], null, 'A1');
|
||||
|
||||
$worksheet->getStyle('B:B')->getNumberFormat()->setFormatCode($this->company->date_format());
|
||||
|
|
@ -374,13 +376,14 @@ class TaxPeriodReport extends BaseExport
|
|||
*/
|
||||
public function createInvoiceItemSummarySheet()
|
||||
{
|
||||
$worksheet_title = $this->cash_accounting ? ctrans('texts.cash_accounting') : ctrans('texts.accrual_accounting');
|
||||
|
||||
$worksheet = $this->spreadsheet->createSheet();
|
||||
$worksheet->setTitle(ctrans('texts.invoice_item')." ".ctrans('texts.cash_vs_accrual'));
|
||||
$worksheet->setTitle(substr(ctrans('texts.invoice_item')." ".$worksheet_title, 0, 30));
|
||||
$worksheet->fromArray($this->data['invoice_items'], null, 'A1');
|
||||
|
||||
$worksheet->getStyle('B:B')->getNumberFormat()->setFormatCode($this->company->date_format());
|
||||
$worksheet->getStyle('D:D')->getNumberFormat()->setFormatCode($this->number_format."%");
|
||||
$worksheet->getStyle('D:D')->getNumberFormat()->setFormatCode($this->number_format);
|
||||
$worksheet->getStyle('E:E')->getNumberFormat()->setFormatCode($this->currency_format);
|
||||
$worksheet->getStyle('F:F')->getNumberFormat()->setFormatCode($this->currency_format);
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_deleted' => 0,
|
||||
'postal_code' => rand(10000, 99999),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -255,8 +256,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true,
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testSingleInvoiceTaxReportStructure', $this->company, $payload);
|
||||
|
||||
$this->assertNotEmpty($data);
|
||||
|
||||
|
|
@ -305,8 +305,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false,
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testSingleInvoiceTaxReportStructure', $this->company, $payload);
|
||||
|
||||
$this->assertCount(2, $invoice->transaction_events);
|
||||
// Report should have data rows with proper structure
|
||||
|
|
@ -438,8 +437,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true,
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceReportingOverMultiplePeriodsWithAccrualAccountingCheckAdjustmentsForIncreases', $this->company, $payload);
|
||||
|
||||
$this->assertCount(2, $data['invoices']); // Header + 1 delta row
|
||||
$this->assertCount(2, $data['invoice_items']); // Header + 1 delta row
|
||||
|
|
@ -557,8 +555,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true,
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceReportingOverMultiplePeriodsWithAccrualAccountingCheckAdjustmentsForDecreases', $this->company, $payload);
|
||||
|
||||
$this->assertCount(2, $data['invoices']); // Header + 1 delta row
|
||||
$this->assertCount(2, $data['invoice_items']); // Header + 1 delta row
|
||||
|
|
@ -641,8 +638,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true, //accrual
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceReportingOverMultiplePeriodsWithCashAccountingCheckAdjustments', $this->company, $payload);
|
||||
|
||||
$transaction_event = $invoice->transaction_events()
|
||||
->where('event_id', '!=', TransactionEvent::INVOICE_UPDATED)
|
||||
|
|
@ -763,8 +759,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, //cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceWithRefundAndCashReportsAreCorrect', $this->company, $payload);
|
||||
|
||||
$invoice = $invoice->fresh();
|
||||
$payment = $invoice->payments()->first();
|
||||
|
|
@ -866,8 +861,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, //cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceWithRefundAndCashReportsAreCorrectAcrossReportingPeriods', $this->company, $payload);
|
||||
|
||||
// Verify October report data (payment in same period)
|
||||
$this->assertCount(2, $data['invoices']); // Header + 1 payment row
|
||||
|
|
@ -930,9 +924,8 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, //cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload);
|
||||
$data = $pl->boot()->getData();
|
||||
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceWithRefundAndCashReportsAreCorrectAcrossReportingPeriods', $this->company, $payload);
|
||||
|
||||
|
||||
// nlog($invoice->fresh()->transaction_events()->get()->toArray());
|
||||
// nlog($data);
|
||||
|
|
@ -962,8 +955,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, //cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceWithRefundAndCashReportsAreCorrectAcrossReportingPeriods', $this->company, $payload);
|
||||
|
||||
// Verify combined October-November report (payment + adjustment)
|
||||
$this->assertCount(3, $data['invoices']); // Header + payment row + adjustment row
|
||||
|
|
@ -1049,8 +1041,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true, // accrual
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testCancelledInvoiceInSamePeriodAccrual', $this->company, $payload, false);
|
||||
|
||||
// Should have cancelled status, but no tax liability for unpaid portion
|
||||
$this->assertCount(2, $data['invoices']); // Header + 1 invoice
|
||||
|
|
@ -1115,8 +1106,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
// Move to next period and cancel
|
||||
$this->travelTo(\Carbon\Carbon::createFromDate(2026, 1, 2)->startOfDay());
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testCancelledInvoiceInNextPeriodAccrual', $this->company, $payload, false);
|
||||
|
||||
// Verify December report shows the invoice created
|
||||
$this->assertCount(2, $data['invoices']); // Header + 1 invoice
|
||||
|
|
@ -1150,8 +1140,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true,
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testCancelledInvoiceInNextPeriodAccrual', $this->company, $payload, false);
|
||||
|
||||
// Verify January report shows the cancellation
|
||||
$this->assertGreaterThanOrEqual(2, count($data['invoices'])); // At least header + 1 invoice
|
||||
|
|
@ -1183,8 +1172,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
$payload['start_date'] = '2026-01-01';
|
||||
$payload['end_date'] = '2026-01-31';
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testCancelledInvoiceInNextPeriodAccrual', $this->company, $payload, false);
|
||||
|
||||
// Find our specific invoice in January report
|
||||
$found = false;
|
||||
|
|
@ -1270,8 +1258,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true,
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: true);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testCancelledInvoiceWithPartialPaymentAccrual', $this->company, $payload, true);
|
||||
|
||||
$this->assertCount(2, $data['invoices']);
|
||||
$invoice_report = $data['invoices'][1];
|
||||
|
|
@ -1343,8 +1330,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true,
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: true);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testDeletedInvoiceInSamePeriodAccrual', $this->company, $payload, true);
|
||||
|
||||
// Should only have header row, no invoice data
|
||||
$this->assertCount(1, $data['invoices']); // Just header
|
||||
|
|
@ -1413,8 +1399,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
|
||||
nlog("initial invoice");
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testDeletedPaidInvoiceInNextPeriodAccrual', $this->company, $payload, false);
|
||||
|
||||
// Verify October report shows the invoice before deletion
|
||||
$this->assertCount(2, $data['invoices']); // Header + 1 invoice
|
||||
|
|
@ -1452,8 +1437,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
|
||||
// nlog("post delete");
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testDeletedPaidInvoiceInNextPeriodAccrual', $this->company, $payload, false);
|
||||
|
||||
// nlog($invoice->fresh()->transaction_events()->get()->toArray());
|
||||
// (new InvoiceTransactionEventEntry())->run($invoice);
|
||||
|
|
@ -1463,8 +1447,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
$this->assertEquals(-30, $data['invoices'][1][4]); // +$30 GST
|
||||
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testDeletedPaidInvoiceInNextPeriodAccrual', $this->company, $payload, false);
|
||||
|
||||
$this->assertCount(2, $data['invoices']);
|
||||
$this->assertEquals(-30, $data['invoices'][1][4]); // +$30 GST
|
||||
|
|
@ -1473,8 +1456,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
$payload['start_date'] = '2025-11-01';
|
||||
$payload['end_date'] = '2025-11-30';
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testDeletedPaidInvoiceInNextPeriodAccrual', $this->company, $payload, false);
|
||||
|
||||
nlog($data);
|
||||
|
||||
|
|
@ -1551,9 +1533,8 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true,
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
|
||||
$data = $this->executeTaxPeriodReportAndSave('testDeletedPaidInvoiceInNextPeriodAccrual', $this->company, $payload, false);
|
||||
|
||||
$this->assertCount(2, $data['invoices']);
|
||||
|
||||
$repo = new InvoiceRepository();
|
||||
|
|
@ -1569,8 +1550,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true,
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testDeletedPaidInvoiceInNextPeriodAccrual', $this->company, $payload, false);
|
||||
|
||||
nlog($data);
|
||||
|
||||
|
|
@ -1655,8 +1635,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: true);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testPaymentDeletedInSamePeriodCash', $this->company, $payload, true);
|
||||
|
||||
// No payment, no cash report entry
|
||||
$this->assertCount(1, $data['invoices']); // Just header
|
||||
|
|
@ -1719,8 +1698,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testPaymentDeletedInNextPeriodCash', $this->company, $payload, false);
|
||||
|
||||
$this->assertCount(2, $data['invoices']); // Header + 1 payment row
|
||||
$this->assertCount(2, $data['invoice_items']); // Header + 1 payment row
|
||||
|
|
@ -1775,8 +1753,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testPaymentDeletedInNextPeriodCash', $this->company, $payload, false);
|
||||
|
||||
$this->assertCount(2, $data['invoices']); // Header + 1 deletion adjustment row
|
||||
$this->assertCount(2, $data['invoice_items']); // Header + 1 deletion adjustment row
|
||||
|
|
@ -1864,8 +1841,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true, // accrual
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testPaymentDeletedInNextPeriodAccrual', $this->company, $payload, false);
|
||||
|
||||
nlog($invoice->fresh()->transaction_events()->get()->toArray());
|
||||
|
||||
|
|
@ -1892,8 +1868,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
$payload['start_date'] = '2025-11-01';
|
||||
$payload['end_date'] = '2025-11-30';
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: true);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testPaymentDeletedInNextPeriodAccrual', $this->company, $payload, true);
|
||||
|
||||
$this->assertCount(1, $data['invoices']); // Just header, no invoice events in November for accrual
|
||||
|
||||
|
|
@ -1959,8 +1934,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: true);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testCancelledInvoiceInSamePeriodCash', $this->company, $payload, true);
|
||||
|
||||
// Cash accounting: unpaid cancelled invoice = no tax liability
|
||||
$this->assertCount(1, $data['invoices']); // Just header, no data
|
||||
|
|
@ -2024,8 +1998,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: true);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testCancelledPaidInvoiceInSamePeriodCash', $this->company, $payload, true);
|
||||
|
||||
// Should show the payment event but cancellation offsets it
|
||||
// The exact behavior depends on implementation
|
||||
|
|
@ -2089,8 +2062,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testCancelledPartiallyPaidInvoiceInNextPeriodCash', $this->company, $payload, false);
|
||||
|
||||
$this->assertCount(2, $data['invoices']);
|
||||
$this->assertEquals(10, $data['invoices'][1][4]); // +$30 GST from payment
|
||||
|
|
@ -2110,8 +2082,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testCancelledPartiallyPaidInvoiceInNextPeriodCash', $this->company, $payload, false);
|
||||
|
||||
// Should show cancelled status with negative adjustment
|
||||
$this->assertCount(1, $data['invoices']);
|
||||
|
|
@ -2179,8 +2150,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testCancelledInvoiceWithPartialPaymentCash', $this->company, $payload, false);
|
||||
|
||||
$this->assertCount(2, $data['invoices']);
|
||||
$this->assertEquals(10, $data['invoices'][1][4]); // +$15 GST (50% of $30)
|
||||
|
|
@ -2200,8 +2170,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testCancelledInvoiceWithPartialPaymentCash', $this->company, $payload, false);
|
||||
|
||||
// Should show reversal of the 50% that was paid
|
||||
$this->assertEquals(1, count($data['invoices']));
|
||||
|
|
@ -2270,8 +2239,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true, // accrual
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceReversedWithCreditNoteNextPeriodAccrual', $this->company, $payload, false);
|
||||
|
||||
$this->assertCount(2, $data['invoices']);
|
||||
$this->assertEquals(30, $data['invoices'][1][4]); // +$30 GST
|
||||
|
|
@ -2351,8 +2319,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceReversedWithCreditNoteNextPeriodCash', $this->company, $payload, false);
|
||||
|
||||
nlog($data);
|
||||
|
||||
|
|
@ -2404,8 +2371,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceReversedWithCreditNoteNextPeriodCash', $this->company, $payload, false);
|
||||
|
||||
$reversed_event = $invoice->fresh()->transaction_events()->where('metadata->tax_report->tax_summary->status', 'reversed')->first();
|
||||
$this->assertNotNull($reversed_event);
|
||||
|
|
@ -2487,8 +2453,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testPartialPaymentThenFullRefundAcrossPeriods', $this->company, $payload, false);
|
||||
|
||||
$this->assertCount(2, $data['invoices']); // Header + 1 partial payment row
|
||||
$this->assertCount(2, $data['invoice_items']); // Header + 1 partial payment row
|
||||
|
|
@ -2549,8 +2514,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => false, // cash
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testPartialPaymentThenFullRefundAcrossPeriods', $this->company, $payload, false);
|
||||
|
||||
// Should show negative adjustment
|
||||
$this->assertGreaterThanOrEqual(1, count($data['invoices']));
|
||||
|
|
@ -2631,11 +2595,8 @@ class TaxPeriodReportTest extends TestCase
|
|||
'date_range' => 'custom',
|
||||
'is_income_billed' => true,
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
|
||||
$pl = null;
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceIncreasedMultipleTimesAcrossPeriods', $this->company, $payload, false);
|
||||
|
||||
$invoice = $invoice->fresh();
|
||||
$this->assertEquals(1, $invoice->fresh()->transaction_events()->count());
|
||||
|
|
@ -2662,8 +2623,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true,
|
||||
];
|
||||
|
||||
$pb = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pb->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceIncreasedMultipleTimesAcrossPeriods', $this->company, $payload, false);
|
||||
|
||||
$this->assertEquals(2, $invoice->fresh()->transaction_events()->count());
|
||||
|
||||
|
|
@ -2683,8 +2643,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'date_range' => 'custom',
|
||||
'is_income_billed' => true,
|
||||
];
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceIncreasedMultipleTimesAcrossPeriods', $this->company, $payload, false);
|
||||
|
||||
$this->assertEquals(3, $invoice->fresh()->transaction_events()->count());
|
||||
|
||||
|
|
@ -2697,8 +2656,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
'is_income_billed' => true,
|
||||
];
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceIncreasedMultipleTimesAcrossPeriods', $this->company, $payload, false);
|
||||
|
||||
$this->assertCount(2, $data['invoices']); // Header + 1 invoice row
|
||||
$this->assertCount(2, $data['invoice_items']); // Header + 1 item row
|
||||
|
|
@ -2722,8 +2680,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
$payload['start_date'] = '2025-11-01';
|
||||
$payload['end_date'] = '2025-11-30';
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceIncreasedMultipleTimesAcrossPeriods', $this->company, $payload, false);
|
||||
|
||||
$this->assertCount(2, $data['invoices']); // Header + 1 delta row
|
||||
$this->assertCount(2, $data['invoice_items']); // Header + 1 delta row
|
||||
|
|
@ -2747,8 +2704,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
$payload['start_date'] = '2025-12-01';
|
||||
$payload['end_date'] = '2025-12-31';
|
||||
|
||||
$pl = new TaxPeriodReport($this->company, $payload, skip_initialization: false);
|
||||
$data = $pl->boot()->getData();
|
||||
$data = $this->executeTaxPeriodReportAndSave('testInvoiceIncreasedMultipleTimesAcrossPeriods', $this->company, $payload, false);
|
||||
|
||||
$this->assertCount(2, $data['invoices']); // Header + 1 delta row
|
||||
$this->assertCount(2, $data['invoice_items']); // Header + 1 delta row
|
||||
|
|
|
|||
Loading…
Reference in New Issue