Tax Reporting
This commit is contained in:
parent
392a7c7736
commit
226c881eef
|
|
@ -17,6 +17,7 @@ namespace App\DataMapper\TaxReport;
|
|||
*/
|
||||
class TaxSummary
|
||||
{
|
||||
public float $taxable_amount;
|
||||
public float $total_taxes; // Tax collected and confirmed (ie. Invoice Paid)
|
||||
public float $total_paid; // Tax pending collection (Outstanding tax of balance owing)
|
||||
public string $status; // updated, deleted, cancelled, adjustment
|
||||
|
|
@ -25,6 +26,7 @@ class TaxSummary
|
|||
|
||||
public function __construct(array $attributes = [])
|
||||
{
|
||||
$this->taxable_amount = $attributes['taxable_amount'] ?? 0.0;
|
||||
$this->total_taxes = $attributes['total_taxes'] ?? 0.0;
|
||||
$this->total_paid = $attributes['total_paid'] ?? 0.0;
|
||||
$this->status = $attributes['status'] ?? 'updated';
|
||||
|
|
@ -35,6 +37,7 @@ class TaxSummary
|
|||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'taxable_amount' => $this->taxable_amount,
|
||||
'total_taxes' => $this->total_taxes,
|
||||
'total_paid' => $this->total_paid,
|
||||
'status' => $this->status,
|
||||
|
|
|
|||
|
|
@ -129,6 +129,8 @@ class InvoiceTransactionEventEntry
|
|||
*/
|
||||
private function calculateDeltaMetaData($invoice)
|
||||
{
|
||||
$this->paid_ratio = 1;
|
||||
|
||||
$calc = $invoice->calc();
|
||||
|
||||
$details = [];
|
||||
|
|
@ -144,7 +146,7 @@ class InvoiceTransactionEventEntry
|
|||
$previous_tax_details = $previous_transaction_event->metadata->tax_report->tax_details;
|
||||
|
||||
foreach ($taxes as $tax) {
|
||||
$previousLine = $previous_tax_details[$tax['name']] ?? null;
|
||||
$previousLine = collect($previous_tax_details)->where('tax_name', $tax['name'])->first() ?? null;
|
||||
|
||||
$tax_detail = [
|
||||
'tax_name' => $tax['name'],
|
||||
|
|
@ -153,28 +155,32 @@ class InvoiceTransactionEventEntry
|
|||
'tax_amount' => $this->calculateRatio($tax['total']),
|
||||
'tax_amount_paid' => $this->calculateRatio($tax['total']),
|
||||
'tax_amount_remaining' => 0,
|
||||
'taxable_amount_adjustment' => ($tax['base_amount'] ?? $calc->getNetSubtotal()) - ($previousLine['taxable_amount'] ?? 0),
|
||||
'tax_amount_adjustment' => $this->calculateRatio($tax['total']) - ($previousLine['tax_amount'] ?? 0),
|
||||
'tax_amount_paid_adjustment' => $this->calculateRatio($tax['total']) - ($previousLine['tax_amount_paid'] ?? 0),
|
||||
'taxable_amount_adjustment' => ($tax['base_amount'] ?? $calc->getNetSubtotal()) - ($previousLine->taxable_amount ?? 0),
|
||||
'tax_amount_adjustment' => $tax['total'] - ($previousLine->tax_amount ?? 0),
|
||||
'tax_amount_paid_adjustment' => $this->calculateRatio($tax['total']) - ($previousLine->tax_amount_paid ?? 0),
|
||||
'tax_amount_remaining_adjustment' => 0,
|
||||
];
|
||||
|
||||
$details[] = $tax_detail;
|
||||
}
|
||||
|
||||
$this->setPaidRatio($invoice);
|
||||
|
||||
return new TransactionEventMetadata([
|
||||
'tax_report' => [
|
||||
'tax_details' => $details,
|
||||
'payment_history' => $this->payments->toArray() ?? [], //@phpstan-ignore-line
|
||||
'tax_summary' => [
|
||||
'total_taxes' => $invoice->total_taxes,
|
||||
'taxable_amount' => $calc->getNetSubtotal(),
|
||||
'total_taxes' => $calc->getTotalTaxes(),
|
||||
'total_paid' => $this->getTotalTaxPaid($invoice),
|
||||
'status' => 'delta',
|
||||
'adjustment' => round($invoice->amount - $previous_transaction_event->invoice_amount, 2),
|
||||
'tax_adjustment' => round($invoice->total_taxes - $previous_transaction_event->metadata->tax_report->tax_summary->total_taxes,2)
|
||||
'adjustment' => round($calc->getNetSubtotal() - $previous_transaction_event->metadata->tax_report->tax_summary->taxable_amount, 2),
|
||||
'tax_adjustment' => round($calc->getTotalTaxes() - $previous_transaction_event->metadata->tax_report->tax_summary->total_taxes,2)
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -203,14 +209,18 @@ class InvoiceTransactionEventEntry
|
|||
$details[] = $tax_detail;
|
||||
}
|
||||
|
||||
//@todo what happens if this is triggered in the "NEXT FINANCIAL PERIOD?
|
||||
return new TransactionEventMetadata([
|
||||
'tax_report' => [
|
||||
'tax_details' => $details,
|
||||
'payment_history' => $this->payments->toArray() ?? [], //@phpstan-ignore-line
|
||||
'tax_summary' => [
|
||||
'total_taxes' => $invoice->total_taxes,
|
||||
'taxable_amount' => $calc->getNetSubtotal(),
|
||||
'total_taxes' => $calc->getTotalTaxes(),
|
||||
'total_paid' => $this->getTotalTaxPaid($invoice),
|
||||
'status' => 'cancelled',
|
||||
// 'adjustment' => round($calc->getNetSubtotal() - $previous_transaction_event->metadata->tax_report->tax_summary->taxable_amount, 2),
|
||||
// 'tax_adjustment' => round($calc->getTotalTaxes() - $previous_transaction_event->metadata->tax_report->tax_summary->total_taxes,2)
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
|
@ -248,7 +258,8 @@ class InvoiceTransactionEventEntry
|
|||
'tax_details' => $details,
|
||||
'payment_history' => $this->payments->toArray(),
|
||||
'tax_summary' => [
|
||||
'total_taxes' => $invoice->total_taxes,
|
||||
'taxable_amount' => $calc->getNetSubtotal(),
|
||||
'total_taxes' => $calc->getTotalTaxes(),
|
||||
'total_paid' => $this->getTotalTaxPaid($invoice),
|
||||
'status' => 'deleted',
|
||||
],
|
||||
|
|
@ -291,7 +302,8 @@ class InvoiceTransactionEventEntry
|
|||
'tax_details' => $details,
|
||||
'payment_history' => $this->payments->toArray(),
|
||||
'tax_summary' => [
|
||||
'total_taxes' => $invoice->total_taxes,
|
||||
'taxable_amount' => $calc->getNetSubtotal(),
|
||||
'total_taxes' => $calc->getTotalTaxes(),
|
||||
'total_paid' => $this->getTotalTaxPaid($invoice),
|
||||
'status' => 'updated',
|
||||
],
|
||||
|
|
|
|||
|
|
@ -22,25 +22,25 @@ use App\DataMapper\TransactionEventMetadata;
|
|||
* @property int $invoice_id
|
||||
* @property int $payment_id
|
||||
* @property int $credit_id
|
||||
* @property string $client_balance
|
||||
* @property string $client_paid_to_date
|
||||
* @property string $client_credit_balance
|
||||
* @property string $invoice_balance
|
||||
* @property string $invoice_amount
|
||||
* @property string $invoice_partial
|
||||
* @property string $invoice_paid_to_date
|
||||
* @property float $client_balance
|
||||
* @property float $client_paid_to_date
|
||||
* @property float $client_credit_balance
|
||||
* @property float $invoice_balance
|
||||
* @property float $invoice_amount
|
||||
* @property float $invoice_partial
|
||||
* @property float $invoice_paid_to_date
|
||||
* @property int|null $invoice_status
|
||||
* @property string $payment_amount
|
||||
* @property string $payment_applied
|
||||
* @property string $payment_refunded
|
||||
* @property float $payment_amount
|
||||
* @property float $payment_applied
|
||||
* @property float $payment_refunded
|
||||
* @property int|null $payment_status
|
||||
* @property array|null $paymentables
|
||||
* @property int $event_id
|
||||
* @property int $timestamp
|
||||
* @property array|null $payment_request
|
||||
* @property TransactionEventMetadata|null $metadata
|
||||
* @property string $credit_balance
|
||||
* @property string $credit_amount
|
||||
* @property float $credit_balance
|
||||
* @property float $credit_amount
|
||||
* @property int|null $credit_status
|
||||
* @property Carbon|null $period
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel company()
|
||||
|
|
|
|||
|
|
@ -199,6 +199,7 @@ class TaxPeriodReportTest extends TestCase
|
|||
|
||||
$transaction_event = $invoice->transaction_events()->first();
|
||||
|
||||
nlog($transaction_event->metadata->toArray());
|
||||
$this->assertNotNull($transaction_event);
|
||||
$this->assertEquals(330, $transaction_event->invoice_amount);
|
||||
$this->assertEquals('2025-10-01', $invoice->date);
|
||||
|
|
@ -248,12 +249,113 @@ class TaxPeriodReportTest extends TestCase
|
|||
$pl = new TaxPeriodReport($this->company, $payload);
|
||||
$data = $pl->boot()->getData();
|
||||
|
||||
nlog($invoice->transaction_events->toArray());
|
||||
|
||||
$this->assertCount(2, $invoice->transaction_events);
|
||||
$this->assertCount(2, $data['invoices']);
|
||||
$this->assertCount(2, $data['invoice_items']);
|
||||
|
||||
$this->travelBack();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test that we adjust appropriately across reporting period where an invoice amount has been both
|
||||
* increased and decreased, and assess that the adjustments are correct.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInvoiceReportingOverMultiplePeriodsWithAccrualAccountingCheckAdjustments()
|
||||
{
|
||||
|
||||
$this->buildData();
|
||||
|
||||
$this->travelTo(\Carbon\Carbon::createFromDate(2025, 10, 1)->startOfDay());
|
||||
|
||||
$line_items = [];
|
||||
$item = InvoiceItemFactory::create();
|
||||
$item->quantity = 1;
|
||||
$item->cost = 300;
|
||||
$item->type_id = 1;
|
||||
$item->tax_name1 = 'GST';
|
||||
$item->tax_rate1 = 10;
|
||||
|
||||
$line_items[] = $item;
|
||||
|
||||
|
||||
$invoice = Invoice::factory()->create([
|
||||
'client_id' => $this->client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'line_items' => $line_items,
|
||||
'status_id' => Invoice::STATUS_DRAFT,
|
||||
'discount' => 0,
|
||||
'is_amount_discount' => false,
|
||||
'uses_inclusive_taxes' => false,
|
||||
'tax_name1' => '',
|
||||
'tax_rate1' => 0,
|
||||
'tax_name2' => '',
|
||||
'tax_rate2' => 0,
|
||||
'tax_name3' => '',
|
||||
'tax_rate3' => 0,
|
||||
'custom_surcharge1' => 0,
|
||||
'custom_surcharge2' => 0,
|
||||
'custom_surcharge3' => 0,
|
||||
'custom_surcharge4' => 0,
|
||||
'date' => now()->format('Y-m-d'),
|
||||
'due_date' => now()->addDays(30)->format('Y-m-d'),
|
||||
]);
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
|
||||
$invoice->service()->markSent()->createInvitations()->save();
|
||||
|
||||
$invoice->fresh();
|
||||
|
||||
(new InvoiceTransactionEventEntry())->run($invoice);
|
||||
|
||||
$invoice->fresh();
|
||||
|
||||
$transaction_event = $invoice->transaction_events()->first();
|
||||
|
||||
$this->assertEquals('2025-10-31', $transaction_event->period->format('Y-m-d'));
|
||||
$this->assertEquals(330, $transaction_event->invoice_amount);
|
||||
$this->assertEquals(30, $transaction_event->metadata->tax_report->tax_summary->total_taxes);
|
||||
$this->assertEquals(0, $transaction_event->invoice_paid_to_date);
|
||||
|
||||
|
||||
$this->travelTo(\Carbon\Carbon::createFromDate(2025, 11, 5)->startOfDay());
|
||||
|
||||
$line_items = [];
|
||||
$item = InvoiceItemFactory::create();
|
||||
$item->quantity = 1;
|
||||
$item->cost = 400;
|
||||
$item->type_id = 1;
|
||||
$item->tax_name1 = 'GST';
|
||||
$item->tax_rate1 = 10;
|
||||
|
||||
$line_items[] = $item;
|
||||
|
||||
$invoice->line_items = $line_items;
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
|
||||
$invoice->fresh();
|
||||
|
||||
(new InvoiceTransactionEventEntry())->run($invoice);
|
||||
|
||||
$transaction_event = $invoice->transaction_events()->orderBy('timestamp', 'desc')->first();
|
||||
|
||||
nlog($transaction_event->metadata);
|
||||
$this->assertEquals('2025-11-30', $transaction_event->period->format('Y-m-d'));
|
||||
$this->assertEquals(440, $transaction_event->invoice_amount);
|
||||
$this->assertEquals("delta", $transaction_event->metadata->tax_report->tax_summary->status);
|
||||
$this->assertEquals(40, $transaction_event->metadata->tax_report->tax_summary->total_taxes);
|
||||
$this->assertEquals(100, $transaction_event->metadata->tax_report->tax_summary->adjustment);
|
||||
$this->assertEquals(10, $transaction_event->metadata->tax_report->tax_summary->tax_adjustment);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function invoiceReportingOverMultiplePeriodsWithCashAccountingCheckAdjustments()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue