From 0d1625644fda63dae9fa70fd4cdcfba3bd7abd67 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 5 Aug 2025 07:35:46 +1000 Subject: [PATCH] Refactor for TransactionEvents --- app/Casts/InvoiceSyncCast.php | 10 +- app/DataMapper/InvoiceSync.php | 258 +----------------- .../Transactions/BaseTransaction.php | 99 ------- .../Transactions/ClientStatusTransaction.php | 23 -- .../GatewayPaymentMadeTransaction.php | 23 -- .../InvoiceCancelledTransaction.php | 23 -- .../InvoiceDeletedTransaction.php | 23 -- .../InvoiceFeeAppliedTransaction.php | 23 -- .../InvoicePaymentTransaction.php | 23 -- .../InvoiceReversalTransaction.php | 23 -- .../InvoiceUpdatedTransaction.php | 23 -- .../Transactions/MarkPaidTransaction.php | 23 -- .../PaymentAppliedTransaction.php | 23 -- .../PaymentDeletedTransaction.php | 23 -- .../Transactions/PaymentFailedTransaction.php | 23 -- .../Transactions/PaymentMadeTransaction.php | 23 -- .../PaymentRefundedTransaction.php | 23 -- .../Transactions/TransactionInterface.php | 18 -- app/Http/Controllers/InvoiceController.php | 2 - app/Jobs/Ninja/TransactionLog.php | 116 -------- app/Services/Report/TaxSummaryReport.php | 1 + app/Services/Report/XLS/TaxReport.php | 36 ++- 22 files changed, 37 insertions(+), 825 deletions(-) delete mode 100644 app/DataMapper/Transactions/BaseTransaction.php delete mode 100644 app/DataMapper/Transactions/ClientStatusTransaction.php delete mode 100644 app/DataMapper/Transactions/GatewayPaymentMadeTransaction.php delete mode 100644 app/DataMapper/Transactions/InvoiceCancelledTransaction.php delete mode 100644 app/DataMapper/Transactions/InvoiceDeletedTransaction.php delete mode 100644 app/DataMapper/Transactions/InvoiceFeeAppliedTransaction.php delete mode 100644 app/DataMapper/Transactions/InvoicePaymentTransaction.php delete mode 100644 app/DataMapper/Transactions/InvoiceReversalTransaction.php delete mode 100644 app/DataMapper/Transactions/InvoiceUpdatedTransaction.php delete mode 100644 app/DataMapper/Transactions/MarkPaidTransaction.php delete mode 100644 app/DataMapper/Transactions/PaymentAppliedTransaction.php delete mode 100644 app/DataMapper/Transactions/PaymentDeletedTransaction.php delete mode 100644 app/DataMapper/Transactions/PaymentFailedTransaction.php delete mode 100644 app/DataMapper/Transactions/PaymentMadeTransaction.php delete mode 100644 app/DataMapper/Transactions/PaymentRefundedTransaction.php delete mode 100644 app/DataMapper/Transactions/TransactionInterface.php delete mode 100644 app/Jobs/Ninja/TransactionLog.php diff --git a/app/Casts/InvoiceSyncCast.php b/app/Casts/InvoiceSyncCast.php index bc5f6cfcc6..626a16029b 100644 --- a/app/Casts/InvoiceSyncCast.php +++ b/app/Casts/InvoiceSyncCast.php @@ -29,8 +29,9 @@ class InvoiceSyncCast implements CastsAttributes return null; } - $is = new InvoiceSync($data); - + $is = new InvoiceSync(); + $is->qb_id = $data['qb_id']; + return $is; } @@ -44,11 +45,6 @@ class InvoiceSyncCast implements CastsAttributes 'qb_id' => $value->qb_id, ]; - // Handle structured nested object - if ($value->tax_report !== null) { - $data['tax_report'] = $value->tax_report->toArray(); - } - return [ $key => json_encode($data) ]; diff --git a/app/DataMapper/InvoiceSync.php b/app/DataMapper/InvoiceSync.php index c4111d5ed0..f2a532c544 100644 --- a/app/DataMapper/InvoiceSync.php +++ b/app/DataMapper/InvoiceSync.php @@ -13,6 +13,7 @@ namespace App\DataMapper; use App\Casts\InvoiceSyncCast; +use App\DataMapper\TaxReport\TaxReport; use Illuminate\Contracts\Database\Eloquent\Castable; /** @@ -21,14 +22,10 @@ use Illuminate\Contracts\Database\Eloquent\Castable; class InvoiceSync implements Castable { public string $qb_id; - public ?TaxReport $tax_report; // Structured nested object public function __construct(array $attributes = []) { $this->qb_id = $attributes['qb_id'] ?? ''; - $this->tax_report = isset($attributes['tax_report']) - ? new TaxReport($attributes['tax_report']) - : null; // Handle structured nested object } /** @@ -46,256 +43,3 @@ class InvoiceSync implements Castable return new self($data); } } - -/** - * Tax report object for InvoiceSync - tracks incremental tax history - */ -class TaxReport -{ - public string $nexus; - public string $country_nexus; - public string $report_period; // e.g., "2024-Q1", "2024-01" - public string $last_updated; - public ?array $tax_summary; // Summary totals - public ?array $tax_details; // Array of TaxDetail objects - public ?array $tax_adjustments; // Array of TaxAdjustment objects - - public function __construct(array $attributes = []) - { - $this->nexus = $attributes['nexus'] ?? ''; - $this->country_nexus = $attributes['country_nexus'] ?? ''; - $this->report_period = $attributes['report_period'] ?? ''; - $this->last_updated = $attributes['last_updated'] ?? ''; - $this->tax_summary = isset($attributes['tax_summary']) - ? new TaxSummary($attributes['tax_summary']) - : null; - $this->tax_details = isset($attributes['tax_details']) - ? array_map(fn($detail) => new TaxDetail($detail), $attributes['tax_details']) - : null; - $this->tax_adjustments = isset($attributes['tax_adjustments']) - ? array_map(fn($adjustment) => new TaxAdjustment($adjustment), $attributes['tax_adjustments']) - : null; - } - - public function toArray(): array - { - return [ - 'nexus' => $this->nexus, - 'country_nexus' => $this->country_nexus, - 'report_period' => $this->report_period, - 'last_updated' => $this->last_updated, - 'tax_summary' => $this->tax_summary?->toArray(), - 'tax_details' => $this->tax_details ? array_map(fn($detail) => $detail->toArray(), $this->tax_details) : null, - 'tax_adjustments' => $this->tax_adjustments ? array_map(fn($adjustment) => $adjustment->toArray(), $this->tax_adjustments) : null, - ]; - } -} - -/** - * Tax summary with totals for different tax states - */ -class TaxSummary -{ - public float $total_collected; // Tax collected and confirmed - public float $total_pending; // Tax pending collection - public float $total_refundable; // Tax that needs to be claimed back - public float $total_partially_paid; // Tax partially paid - public float $total_adjustments; // Net adjustments - public float $net_tax_liability; // Final tax liability - public ?array $period_totals; // Totals by report period - - public function __construct(array $attributes = []) - { - $this->total_collected = $attributes['total_collected'] ?? 0.0; - $this->total_pending = $attributes['total_pending'] ?? 0.0; - $this->total_refundable = $attributes['total_refundable'] ?? 0.0; - $this->total_partially_paid = $attributes['total_partially_paid'] ?? 0.0; - $this->total_adjustments = $attributes['total_adjustments'] ?? 0.0; - $this->net_tax_liability = $attributes['net_tax_liability'] ?? 0.0; - $this->period_totals = isset($attributes['period_totals']) - ? array_map(fn($period) => new PeriodTotal($period), $attributes['period_totals']) - : null; - } - - public function toArray(): array - { - return [ - 'total_collected' => $this->total_collected, - 'total_pending' => $this->total_pending, - 'total_refundable' => $this->total_refundable, - 'total_partially_paid' => $this->total_partially_paid, - 'total_adjustments' => $this->total_adjustments, - 'net_tax_liability' => $this->net_tax_liability, - 'period_totals' => $this->period_totals ? array_map(fn($period) => $period->toArray(), $this->period_totals) : null, - ]; - } -} - -/** - * Period-specific tax totals - */ -class PeriodTotal -{ - public string $report_period; - public float $collected_in_period; - public float $pending_in_period; - public float $refundable_in_period; - public float $adjustments_in_period; - - public function __construct(array $attributes = []) - { - $this->report_period = $attributes['report_period'] ?? ''; - $this->collected_in_period = $attributes['collected_in_period'] ?? 0.0; - $this->pending_in_period = $attributes['pending_in_period'] ?? 0.0; - $this->refundable_in_period = $attributes['refundable_in_period'] ?? 0.0; - $this->adjustments_in_period = $attributes['adjustments_in_period'] ?? 0.0; - } - - public function toArray(): array - { - return [ - 'report_period' => $this->report_period, - 'collected_in_period' => $this->collected_in_period, - 'pending_in_period' => $this->pending_in_period, - 'refundable_in_period' => $this->refundable_in_period, - 'adjustments_in_period' => $this->adjustments_in_period, - ]; - } -} - -/** - * Individual tax detail object with status tracking - */ -class TaxDetail -{ - public string $invoice_id; - public string $tax_type; // e.g., "state_tax", "city_tax", "county_tax" - public float $tax_rate; - public float $taxable_amount; - public float $tax_amount; - public float $tax_amount_paid; // Amount actually paid - public float $tax_amount_remaining; // Amount still pending - public string $tax_status; // "collected", "pending", "refundable", "partially_paid" - public string $collection_date; // When tax was collected - public string $due_date; // When tax is due - public ?array $payment_history; // Array of PaymentHistory objects - public ?array $metadata; // Additional tax-specific data - - public function __construct(array $attributes = []) - { - $this->invoice_id = $attributes['invoice_id'] ?? ''; - $this->tax_type = $attributes['tax_type'] ?? ''; - $this->tax_rate = $attributes['tax_rate'] ?? 0.0; - $this->taxable_amount = $attributes['taxable_amount'] ?? 0.0; - $this->tax_amount = $attributes['tax_amount'] ?? 0.0; - $this->tax_amount_paid = $attributes['tax_amount_paid'] ?? 0.0; - $this->tax_amount_remaining = $attributes['tax_amount_remaining'] ?? 0.0; - $this->tax_status = $attributes['tax_status'] ?? 'pending'; - $this->collection_date = $attributes['collection_date'] ?? ''; - $this->due_date = $attributes['due_date'] ?? ''; - $this->payment_history = isset($attributes['payment_history']) - ? array_map(fn($payment) => new PaymentHistory($payment), $attributes['payment_history']) - : null; - $this->metadata = $attributes['metadata'] ?? null; - } - - public function toArray(): array - { - return [ - 'invoice_id' => $this->invoice_id, - 'tax_type' => $this->tax_type, - 'tax_rate' => $this->tax_rate, - 'taxable_amount' => $this->taxable_amount, - 'tax_amount' => $this->tax_amount, - 'tax_amount_paid' => $this->tax_amount_paid, - 'tax_amount_remaining' => $this->tax_amount_remaining, - 'tax_status' => $this->tax_status, - 'collection_date' => $this->collection_date, - 'due_date' => $this->due_date, - 'payment_history' => $this->payment_history ? array_map(fn($payment) => $payment->toArray(), $this->payment_history) : null, - 'metadata' => $this->metadata, - ]; - } -} - -/** - * Payment history for tracking partial payments across periods - */ -class PaymentHistory -{ - public string $payment_id; - public string $payment_date; - public string $report_period; // Which period this payment belongs to - public float $payment_amount; - public float $tax_amount_paid; // Tax portion of this payment - public string $payment_method; - public string $status; // "processed", "pending", "failed" - public ?array $allocation_details; // How the payment was allocated - - public function __construct(array $attributes = []) - { - $this->payment_id = $attributes['payment_id'] ?? ''; - $this->payment_date = $attributes['payment_date'] ?? ''; - $this->report_period = $attributes['report_period'] ?? ''; - $this->payment_amount = $attributes['payment_amount'] ?? 0.0; - $this->tax_amount_paid = $attributes['tax_amount_paid'] ?? 0.0; - $this->payment_method = $attributes['payment_method'] ?? ''; - $this->status = $attributes['status'] ?? 'processed'; - $this->allocation_details = $attributes['allocation_details'] ?? null; - } - - public function toArray(): array - { - return [ - 'payment_id' => $this->payment_id, - 'payment_date' => $this->payment_date, - 'report_period' => $this->report_period, - 'payment_amount' => $this->payment_amount, - 'tax_amount_paid' => $this->tax_amount_paid, - 'payment_method' => $this->payment_method, - 'status' => $this->status, - 'allocation_details' => $this->allocation_details, - ]; - } -} - -/** - * Tax adjustment for status changes and corrections - */ -class TaxAdjustment -{ - public string $adjustment_id; - public string $original_invoice_id; - public string $adjustment_type; // "refund", "correction", "status_change" - public string $adjustment_reason; // "invoice_cancelled", "tax_rate_change", "exemption_applied" - public float $adjustment_amount; - public string $adjustment_date; - public string $status; // "pending", "approved", "processed" - public ?array $supporting_documents; // References to supporting docs - - public function __construct(array $attributes = []) - { - $this->adjustment_id = $attributes['adjustment_id'] ?? ''; - $this->original_invoice_id = $attributes['original_invoice_id'] ?? ''; - $this->adjustment_type = $attributes['adjustment_type'] ?? ''; - $this->adjustment_reason = $attributes['adjustment_reason'] ?? ''; - $this->adjustment_amount = $attributes['adjustment_amount'] ?? 0.0; - $this->adjustment_date = $attributes['adjustment_date'] ?? ''; - $this->status = $attributes['status'] ?? 'pending'; - $this->supporting_documents = $attributes['supporting_documents'] ?? null; - } - - public function toArray(): array - { - return [ - 'adjustment_id' => $this->adjustment_id, - 'original_invoice_id' => $this->original_invoice_id, - 'adjustment_type' => $this->adjustment_type, - 'adjustment_reason' => $this->adjustment_reason, - 'adjustment_amount' => $this->adjustment_amount, - 'adjustment_date' => $this->adjustment_date, - 'status' => $this->status, - 'supporting_documents' => $this->supporting_documents, - ]; - } -} diff --git a/app/DataMapper/Transactions/BaseTransaction.php b/app/DataMapper/Transactions/BaseTransaction.php deleted file mode 100644 index 235f902502..0000000000 --- a/app/DataMapper/Transactions/BaseTransaction.php +++ /dev/null @@ -1,99 +0,0 @@ - $data['metadata']], - ['event_id' => $this->event_id, 'timestamp' => time()], - ); - // return [ - // 'event_id' => $this->event_id, - // 'client_id' => $client?->id, - // 'invoice_id' => $invoice?->id, - // 'payment_id' => $payment?->id, - // 'credit_id' => $credit?->creditid, - // 'client_balance' => $client?->balance, - // 'client_paid_to_date' => $client?->paid_to_date, - // 'client_credit_balance' => $client?->credit_balance, - // 'invoice_balance' => $invoice?->balance, - // 'invoice_amount' => $invoice?->amount, - // 'invoice_partial' => $invoice?->partial, - // 'invoice_paid_to_date' => $invoice?->paid_to_date, - // 'invoice_status' => $invoice?->status_id, - // 'payment_amount' => $payment?->amount, - // 'payment_applied' => $payment?->applied, - // 'payment_refunded' => $payment?->refunded, - // 'payment_status' => $payment?->status_id, - // 'paymentables' => $payment?->paymentables, - // 'payment_request' => $payment_request, - // 'metadata' => $metadata, - // 'credit_balance' => $credit?->balance, - // 'credit_amount' => $credit?->amount, - // 'credit_status' => $credit?->status_id, - // 'timestamp' => time(), - // ]; - } -} diff --git a/app/DataMapper/Transactions/ClientStatusTransaction.php b/app/DataMapper/Transactions/ClientStatusTransaction.php deleted file mode 100644 index a7950b31dd..0000000000 --- a/app/DataMapper/Transactions/ClientStatusTransaction.php +++ /dev/null @@ -1,23 +0,0 @@ - [], ]; - // TransactionLog::dispatch(TransactionEvent::INVOICE_UPDATED, $transaction, $invoice->company->db); - return $this->itemResponse($invoice); } diff --git a/app/Jobs/Ninja/TransactionLog.php b/app/Jobs/Ninja/TransactionLog.php deleted file mode 100644 index 2f1054d1de..0000000000 --- a/app/Jobs/Ninja/TransactionLog.php +++ /dev/null @@ -1,116 +0,0 @@ - MarkPaidTransaction::class, // - TransactionEvent::INVOICE_UPDATED => InvoiceUpdatedTransaction::class, // - TransactionEvent::INVOICE_DELETED => InvoiceDeletedTransaction::class, // - TransactionEvent::INVOICE_PAYMENT_APPLIED => InvoicePaymentTransaction::class, - TransactionEvent::INVOICE_CANCELLED => InvoiceCancelledTransaction::class, - TransactionEvent::INVOICE_REVERSED => InvoiceReversalTransaction::class, // - TransactionEvent::INVOICE_FEE_APPLIED => InvoiceFeeAppliedTransaction::class, // - TransactionEvent::PAYMENT_MADE => PaymentMadeTransaction::class, // - TransactionEvent::GATEWAY_PAYMENT_MADE => GatewayPaymentMadeTransaction::class, // - TransactionEvent::PAYMENT_APPLIED => PaymentAppliedTransaction::class, - TransactionEvent::PAYMENT_REFUND => PaymentRefundedTransaction::class, // - TransactionEvent::PAYMENT_FAILED => PaymentFailedTransaction::class, - TransactionEvent::PAYMENT_DELETED => PaymentDeletedTransaction::class, // - TransactionEvent::CLIENT_STATUS => ClientStatusTransaction::class, // - ]; - - /** - * Create a new job instance. - * - * @return void - */ - public function __construct($event, $data, $db) - { - $this->db = $db; - $this->event = $event; - $this->data = $data; - } - - /** - * Execute the job. - * - * @return void - */ - public function handle() - { - // if(!Ninja::isHosted()) - // return; - - $this->setTransformer(); - - $this->payload = $this->event_transformer->transform($this->data); - - $this->persist(); - } - - private function setTransformer() - { - $class = $this->transformer_array[$this->event]; - - $this->event_transformer = new $class(); - - return $this; - } - - private function persist() - { - MultiDB::setDB($this->db); - - TransactionEvent::create($this->payload); - } -} diff --git a/app/Services/Report/TaxSummaryReport.php b/app/Services/Report/TaxSummaryReport.php index 99c896a720..342778d122 100644 --- a/app/Services/Report/TaxSummaryReport.php +++ b/app/Services/Report/TaxSummaryReport.php @@ -24,6 +24,7 @@ use App\Export\CSV\BaseExport; use App\Utils\Traits\MakesDates; use Illuminate\Support\Facades\App; use App\Services\Template\TemplateService; +use App\Jobs\Invoice\InvoiceTaxReportUpdate; class TaxSummaryReport extends BaseExport { diff --git a/app/Services/Report/XLS/TaxReport.php b/app/Services/Report/XLS/TaxReport.php index 4c46041b14..06fdbde33e 100644 --- a/app/Services/Report/XLS/TaxReport.php +++ b/app/Services/Report/XLS/TaxReport.php @@ -37,17 +37,45 @@ class TaxReport $this->spreadsheet = new Spreadsheet(); + $this->updateTaxData(); + + + // ->createGroupedTaxSummarySheetAccrual() + // ->createGroupedTaxSummarySheetCash(); + + return $this; + + } + + private function postUpdateContinuation() + { $this->buildData() - ->setCurrencyFormat() + ->setCurrencyFormat() ->createSummarySheet() ->createInvoiceSummarySheetAccrual() ->createInvoiceSummarySheetCash() ->createInvoiceItemSummarySheetAccrual() ->createInvoiceItemSummarySheetCash(); - // ->createGroupedTaxSummarySheetAccrual() - // ->createGroupedTaxSummarySheetCash(); + } - return $this; + private function updateTaxData() + { + + $batch_key = Str::uuid(); + + $updates = Invoice::withTrashed() + ->whereIn('id', $this->ids) + ->get() + ->map(function ($invoice) use ($batch_key) { + return new InvoiceTaxReportUpdate($invoice, $this->company->db); + })->toArray(); + + + $batch = Bus::batch($updates) + ->then(function (Batch $batch) { + $this->postUpdateContinuation(); + }) + ->name($batch_key)->dispatch(); }