diff --git a/app/Casts/TransactionEventMetadataCast.php b/app/Casts/TransactionEventMetadataCast.php new file mode 100644 index 0000000000..e9759a9edb --- /dev/null +++ b/app/Casts/TransactionEventMetadataCast.php @@ -0,0 +1,45 @@ + null]; + } + + return [ + $key => json_encode($value->toArray()) + ]; + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 6a9adbabdd..93cbfa986c 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -34,6 +34,7 @@ use App\Jobs\Ninja\BankTransactionSync; use App\Jobs\Cron\RecurringExpensesCron; use App\Jobs\Cron\RecurringInvoicesCron; use App\Jobs\EDocument\EInvoicePullDocs; +use App\Jobs\Cron\InvoiceTaxSummary; use Illuminate\Console\Scheduling\Schedule; use App\Jobs\Invoice\InvoiceCheckLateWebhook; use App\Jobs\Subscription\CleanStaleInvoiceOrder; @@ -72,6 +73,32 @@ class Kernel extends ConsoleKernel /* Checks for scheduled tasks */ $schedule->job(new TaskScheduler())->hourlyAt(10)->withoutOverlapping()->name('task-scheduler-job')->onOneServer(); + /* Generates the tax summary for invoices */ + $schedule->job(new InvoiceTaxSummary())->monthly('23:30')->withoutOverlapping()->name('invoice-tax-summary-job')->onOneServer(); + + // Run hourly over 26-hour period for complete timezone coverage + $schedule->job(new InvoiceTaxSummary()) + ->hourly() + ->when(function () { + $now = now(); + $hour = $now->hour; + + // Run for 26 hours starting from UTC 10:00 on last day of month + // This covers the transition period when timezones move to next month + if ($now->isLastOfMonth()) { + // Start at UTC 10:00 (when UTC+14 moves to next day) + return $hour >= 10; + } elseif ($now->isFirstOfMonth()) { + // Continue until UTC 12:00 (when UTC-12 moves to next day) + return $hour <= 12; + } + + return false; + }) + ->withoutOverlapping() + ->name('invoice-tax-summary-26hour-coverage') + ->onOneServer(); + /* Checks Rotessa Transactions */ $schedule->job(new TransactionReport())->dailyAt('01:48')->withoutOverlapping()->name('rotessa-transaction-report')->onOneServer(); diff --git a/app/DataMapper/TaxReport/PaymentHistory.php b/app/DataMapper/TaxReport/PaymentHistory.php new file mode 100644 index 0000000000..5de340e458 --- /dev/null +++ b/app/DataMapper/TaxReport/PaymentHistory.php @@ -0,0 +1,42 @@ +number = $attributes['number'] ?? ''; + $this->date = $attributes['date'] ?? ''; + $this->amount = $attributes['amount'] ?? 0.0; + $this->refunded = $attributes['refunded'] ?? 0.0; + } + + public function toArray(): array + { + return [ + 'number' => $this->number, + 'date' => $this->date, + 'amount' => $this->amount, + 'refunded' => $this->refunded, + ]; + } +} diff --git a/app/DataMapper/TaxReport/TaxDetail.php b/app/DataMapper/TaxReport/TaxDetail.php new file mode 100644 index 0000000000..d8b368e519 --- /dev/null +++ b/app/DataMapper/TaxReport/TaxDetail.php @@ -0,0 +1,67 @@ +tax_name = $attributes['tax_name'] ?? ''; + $this->tax_rate = $attributes['tax_rate'] ?? 0; + $this->nexus = $attributes['nexus'] ?? ''; + $this->country_nexus = $attributes['country_nexus'] ?? ''; + $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'; + + // Adjustment fields + $this->adjustment_reason = $attributes['adjustment_reason'] ?? null; + + } + + public function toArray(): array + { + $data = [ + 'tax_name' => $this->tax_name, + 'tax_rate' => $this->tax_rate, + 'nexus' => $this->nexus, + 'country_nexus' => $this->country_nexus, + '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, + 'adjustment_reason' => $this->adjustment_reason, + ]; + + return $data; + } +} diff --git a/app/DataMapper/TaxReport/TaxReport.php b/app/DataMapper/TaxReport/TaxReport.php new file mode 100644 index 0000000000..81cbcb39f9 --- /dev/null +++ b/app/DataMapper/TaxReport/TaxReport.php @@ -0,0 +1,49 @@ +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->payment_history = isset($attributes['payment_history']) + ? array_map(fn ($payment) => new PaymentHistory($payment), $attributes['payment_history']) + : null; + } + + public function toArray(): array + { + return [ + 'tax_summary' => $this->tax_summary?->toArray(), + 'tax_details' => $this->tax_details ? array_map(fn ($detail) => $detail->toArray(), $this->tax_details) : null, + 'payment_history' => $this->payment_history ? array_map(fn ($payment) => $payment->toArray(), $this->payment_history) : null, + ]; + } +} diff --git a/app/DataMapper/TaxReport/TaxSummary.php b/app/DataMapper/TaxReport/TaxSummary.php new file mode 100644 index 0000000000..f8a360e96a --- /dev/null +++ b/app/DataMapper/TaxReport/TaxSummary.php @@ -0,0 +1,39 @@ +total_taxes = $attributes['total_taxes'] ?? 0.0; + $this->total_paid = $attributes['total_paid'] ?? 0.0; + $this->status = $attributes['status'] ?? 'updated'; + } + + public function toArray(): array + { + return [ + 'total_taxes' => $this->total_taxes, + 'total_paid' => $this->total_paid, + 'status' => $this->status, + ]; + } +} diff --git a/app/DataMapper/TransactionEventMetadata.php b/app/DataMapper/TransactionEventMetadata.php new file mode 100644 index 0000000000..b88bd0cb50 --- /dev/null +++ b/app/DataMapper/TransactionEventMetadata.php @@ -0,0 +1,54 @@ +tax_report = isset($attributes['tax_report']) + ? new TaxReport($attributes['tax_report']) + : new TaxReport([]); + } + + /** + * Get the name of the caster class to use when casting from / to this cast target. + * + * @param array $arguments + */ + public static function castUsing(array $arguments): string + { + return TransactionEventMetadataCast::class; + } + + public static function fromArray(array $data): self + { + return new self($data); + } + + public function toArray(): array + { + return [ + 'tax_report' => $this->tax_report->toArray(), + ]; + } +} diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 9c2089cb46..12492da88c 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -241,14 +241,6 @@ class InvoiceController extends BaseController event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars($user ? $user->id : null))); - $transaction = [ - 'invoice' => $invoice->transaction_event(), - 'payment' => [], - 'client' => $invoice->client->transaction_event(), - 'credit' => [], - 'metadata' => [], - ]; - return $this->itemResponse($invoice); } diff --git a/app/Jobs/Cron/InvoiceTaxSummary.php b/app/Jobs/Cron/InvoiceTaxSummary.php new file mode 100644 index 0000000000..5b2e7e5bf2 --- /dev/null +++ b/app/Jobs/Cron/InvoiceTaxSummary.php @@ -0,0 +1,162 @@ +hour; + $transitioningTimezones = $this->getTransitioningTimezones($currentUtcHour); + + foreach(MultiDB::$dbs as $db) { + MultiDB::setDB($db); + // Only process companies in timezones that just transitioned + $companies = $this->getCompaniesInTimezones($transitioningTimezones); + + foreach ($companies as $company) { + + $this->processCompanyTaxSummary($company); + } + } + } + + private function getTransitioningTimezones($utcHour) + { + $transitioningTimezones = []; + + // Get all timezones from the database + $timezones = app('timezones'); + + foreach ($timezones as $timezone) { + // Calculate the current UTC offset for this timezone (accounting for DST) + $currentOffset = $this->getCurrentUtcOffset($timezone->name); + + // Calculate when this timezone transitions to the next day + $transitionHour = $this->getTimezoneTransitionHour($currentOffset); + + // If this timezone transitions at the current UTC hour, include it + if ($transitionHour === $utcHour) { + $transitioningTimezones[] = $timezone->id; + } + } + + return $transitioningTimezones; + } + + private function getCurrentUtcOffset($timezoneName) + { + try { + $dateTime = new \DateTime('now', new \DateTimeZone($timezoneName)); + return $dateTime->getOffset(); + } catch (\Exception $e) { + // Fallback to UTC if timezone is invalid + return 0; + } + } + + private function getTimezoneTransitionHour($utcOffset) + { + // Calculate which UTC hour this timezone transitions to the next day + // A timezone with UTC offset +X transitions at UTC hour (24 - X) + // For example: UTC+14 transitions at UTC 10:00 (24 - 14 = 10) + // UTC-12 transitions at UTC 12:00 (24 - (-12) = 36, but we use modulo 24) + + $transitionHour = (24 - ($utcOffset / 3600)) % 24; + + // Handle negative offsets properly + if ($transitionHour < 0) { + $transitionHour += 24; + } + + return (int) $transitionHour; + } + + private function getCompaniesInTimezones($timezoneIds) + { + if (empty($timezoneIds)) { + return collect(); // No companies to process + } + + // Get companies that have timezone_id in their JSON settings matching the transitioning timezones + return Company::whereRaw("JSON_EXTRACT(settings, '$.timezone_id') IN (" . implode(',', $timezoneIds) . ")")->get(); + } + + private function processCompanyTaxSummary($company) + { + // Your existing tax summary logic here + // This will only run for companies in timezones that just transitioned + + $startDate = now()->subMonth()->startOfMonth()->format('Y-m-d'); + $endDate = now()->subMonth()->endOfMonth()->format('Y-m-d'); + + // Process tax summary for the company + $this->generateTaxSummary($company, $startDate, $endDate); + } + + private function generateTaxSummary($company, $startDate, $endDate) + { + $todayStart = now()->subHours(15)->timestamp; + $todayEnd = now()->endOfDay()->timestamp; + + Invoice::withTrashed() + ->with('payments') + ->where('company_id', $company->id) + ->whereIn('status_id', [2,3,4,5]) + ->where('is_deleted', 0) + ->whereHas('client', function ($query) { + $query->where('is_deleted', false); + }) + ->whereHas('company', function ($query) { + $query->where('is_disabled', 0) + ->whereHas('account', function ($q) { + $q->where('is_flagged', false); + }); + }) + ->whereBetween('date', [$startDate, $endDate]) + ->whereDoesntHave('transaction_events', function ($query) use ($todayStart, $todayEnd) { + $query->where('timestamp', '>=', $todayStart) + ->where('timestamp', '<=', $todayEnd); + }) + ->cursor() + ->each(function (Invoice $invoice) { + (new InvoiceTransactionEventEntry())->run($invoice); + }); + } +} \ No newline at end of file diff --git a/app/Listeners/Invoice/InvoiceTransactionEventEntry.php b/app/Listeners/Invoice/InvoiceTransactionEventEntry.php new file mode 100644 index 0000000000..0a9f1a1f00 --- /dev/null +++ b/app/Listeners/Invoice/InvoiceTransactionEventEntry.php @@ -0,0 +1,224 @@ +setPaidRatio($invoice); + + $this->payments = $invoice->payments->flatMap(function ($payment) { + return $payment->invoices()->get()->map(function ($invoice) use ($payment) { + return [ + 'number' => $payment->number, + 'amount' => $invoice->pivot->amount, + 'refunded' => $invoice->pivot->refunded, + 'date' => $invoice->pivot->created_at->format('Y-m-d'), + ]; + }); + }); + + TransactionEvent::create([ + 'invoice_id' => $invoice->id, + 'client_id' => $invoice->client_id, + 'client_balance' => $invoice->client->balance, + 'client_paid_to_date' => $invoice->client->paid_to_date, + 'client_credit_balance' => $invoice->client->credit_balance, + 'invoice_balance' => $invoice->balance ?? 0, + 'invoice_amount' => $invoice->amount ?? 0 , + 'invoice_partial' => $invoice->partial ?? 0, + 'invoice_paid_to_date' => $invoice->paid_to_date ?? 0, + 'invoice_status' => $invoice->is_deleted ? 7 : $invoice->status_id, + 'event_id' => $invoice->is_deleted ? TransactionEvent::INVOICE_DELETED : TransactionEvent::INVOICE_UPDATED, + 'timestamp' => now()->timestamp, + 'metadata' => $this->getMetadata($invoice), + ]); + } + + private function setPaidRatio(Invoice $invoice): self + { + if($invoice->amount == 0){ + $this->paid_ratio = 0; + return $this; + } + + $this->paid_ratio = $invoice->paid_to_date / $invoice->amount; + + return $this; + } + + 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 + * + * @param mixed $invoice + */ + private function getCancelledMetaData($invoice) + { + + $calc = $invoice->calc(); + + $details = []; + + $taxes = array_merge($calc->getTaxMap()->merge($calc->getTotalTaxMap())->toArray()); + + foreach ($taxes as $tax) { + $tax_detail = [ + 'tax_name' => $tax['name'], + 'tax_rate' => $tax['tax_rate'], + 'taxable_amount' => $tax['base_amount'] ?? $calc->getNetSubtotal(), + 'tax_amount' => $this->calculateRatio($tax['total']), + 'tax_amount_paid' => $this->calculateRatio($tax['total']), + 'tax_amount_remaining' => 0, + ]; + $details[] = $tax_detail; + } + + return new TransactionEventMetadata([ + 'tax_report' => [ + 'tax_details' => $details, + 'payment_history' => $this->payments->toArray(), + 'tax_summary' => [ + 'total_taxes' => $invoice->total_taxes, + 'total_paid' => $this->getTotalTaxPaid($invoice), + 'status' => 'cancelled', + ], + ], + ]); + + } + + /** + * Set all tax details to 0 + * + * @param mixed $invoice + */ + private function getDeletedMetaData($invoice) + { + + $calc = $invoice->calc(); + + $details = []; + + $taxes = array_merge($calc->getTaxMap()->merge($calc->getTotalTaxMap())->toArray()); + + foreach ($taxes as $tax) { + $tax_detail = [ + 'tax_name' => $tax['name'], + 'tax_rate' => $tax['tax_rate'], + 'taxable_amount' => $tax['base_amount'] ?? $calc->getNetSubtotal(), + 'tax_amount' => $tax['total'], + 'tax_amount_paid' => $this->calculateRatio($tax['total']), + 'tax_amount_remaining' => 0, + ]; + $details[] = $tax_detail; + } + + return new TransactionEventMetadata([ + 'tax_report' => [ + 'tax_details' => $details, + 'payment_history' => $this->payments->toArray(), + 'tax_summary' => [ + 'total_taxes' => $invoice->total_taxes, + 'total_paid' => $this->getTotalTaxPaid($invoice),0, + 'status' => 'deleted', + ], + ], + ]); + + } + + private function getMetadata($invoice) + { + + if ($invoice->status_id == Invoice::STATUS_CANCELLED) { + return $this->getCancelledMetaData($invoice); + } elseif ($invoice->is_deleted) { + return $this->getDeletedMetaData($invoice); + } + + $calc = $invoice->calc(); + + $details = []; + + $taxes = array_merge($calc->getTaxMap()->merge($calc->getTotalTaxMap())->toArray()); + + foreach ($taxes as $tax) { + $tax_detail = [ + 'tax_name' => $tax['name'], + 'tax_rate' => $tax['tax_rate'], + 'taxable_amount' => $tax['base_amount'] ?? $calc->getNetSubtotal(), + 'tax_amount' => $tax['total'], + 'tax_amount_paid' => $this->calculateRatio($tax['total']), + 'tax_amount_remaining' => $tax['total'] - $this->calculateRatio($tax['total']), + ]; + $details[] = $tax_detail; + } + + return new TransactionEventMetadata([ + 'tax_report' => [ + 'tax_details' => $details, + 'payment_history' => $this->payments->toArray(), + 'tax_summary' => [ + 'total_taxes' => $invoice->total_taxes, + 'total_paid' => $this->getTotalTaxPaid($invoice), + 'status' => 'updated', + ], + ], + ]); + + } + + 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); + + } + + +} diff --git a/app/Models/Client.php b/app/Models/Client.php index ff4f0f4801..2c6e962902 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -982,19 +982,7 @@ class Client extends BaseModel implements HasLocalePreference return $offset; } - - public function transaction_event() - { - $client = $this->fresh(); - - return [ - 'client_id' => $client->id, - 'client_balance' => $client->balance ?: 0, - 'client_paid_to_date' => $client->paid_to_date ?: 0, - 'client_credit_balance' => $client->credit_balance ?: 0, - ]; - } - + public function translate_entity(): string { return ctrans('texts.client'); diff --git a/app/Models/Credit.php b/app/Models/Credit.php index 67a32de32b..1121ae1fb3 100644 --- a/app/Models/Credit.php +++ b/app/Models/Credit.php @@ -407,18 +407,6 @@ class Credit extends BaseModel }); } - public function transaction_event() - { - $credit = $this->fresh(); - - return [ - 'credit_id' => $credit->id, - 'credit_amount' => $credit->amount ?: 0, - 'credit_balance' => $credit->balance ?: 0, - 'credit_status' => $credit->status_id ?: 1, - ]; - } - public function translate_entity(): string { return ctrans('texts.credit'); diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 303e805bf2..c21d3b4039 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -127,6 +127,7 @@ use App\Utils\Number; * @property-read int|null $tasks_count * @property-read \App\Models\User $user * @property-read \App\Models\Vendor|null $vendor + * @property-read \Illuminate\Database\Eloquent\Collection $transaction_events * @property-read \Illuminate\Database\Eloquent\Collection $activities * @property-read \Illuminate\Database\Eloquent\Collection $company_ledger * @property-read \Illuminate\Database\Eloquent\Collection $credits @@ -349,6 +350,11 @@ class Invoice extends BaseModel return $this->hasMany(InvoiceInvitation::class); } + public function transaction_events(): \Illuminate\Database\Eloquent\Relations\HasMany + { + return $this->hasMany(TransactionEvent::class); + } + public function client(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(Client::class)->withTrashed(); @@ -684,21 +690,7 @@ class Invoice extends BaseModel break; } } - - public function transaction_event() - { - $invoice = $this->fresh(); - - return [ - 'invoice_id' => $invoice->id, - 'invoice_amount' => $invoice->amount ?: 0, - 'invoice_partial' => $invoice->partial ?: 0, - 'invoice_balance' => $invoice->balance ?: 0, - 'invoice_paid_to_date' => $invoice->paid_to_date ?: 0, - 'invoice_status' => $invoice->status_id ?: 1, - ]; - } - + public function expense_documents() { $line_items = $this->line_items; diff --git a/app/Models/Payment.php b/app/Models/Payment.php index 09f39c8dea..e507617b8a 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -481,21 +481,6 @@ class Payment extends BaseModel return $domain.'/client/payment/'.$this->client->contacts()->first()->contact_key.'/'.$this->hashed_id.'?next=/client/payments/'.$this->hashed_id; } - public function transaction_event() - { - $payment = $this->fresh(); - - return [ - 'payment_id' => $payment->id, - 'payment_amount' => $payment->amount ?: 0, - 'payment_applied' => $payment->applied ?: 0, - 'payment_refunded' => $payment->refunded ?: 0, - 'payment_status' => $payment->status_id ?: 1, - 'paymentables' => $payment->paymentables->toArray(), - 'payment_request' => [], - ]; - } - public function translate_entity(): string { return ctrans('texts.payment'); diff --git a/app/Models/TransactionEvent.php b/app/Models/TransactionEvent.php index a87b2780db..cccf52e904 100644 --- a/app/Models/TransactionEvent.php +++ b/app/Models/TransactionEvent.php @@ -12,6 +12,8 @@ namespace App\Models; +use App\DataMapper\TransactionEventMetadata; + /** * Class Bank. * @@ -42,34 +44,6 @@ namespace App\Models; * @property int|null $credit_status * @method static \Illuminate\Database\Eloquent\Builder|StaticModel company() * @method static \Illuminate\Database\Eloquent\Builder|StaticModel exclude($columns) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent newModelQuery() - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent newQuery() - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent query() - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereClientBalance($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereClientCreditBalance($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereClientId($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereClientPaidToDate($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereCreditAmount($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereCreditBalance($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereCreditId($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereCreditStatus($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereEventId($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereId($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereInvoiceAmount($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereInvoiceBalance($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereInvoiceId($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereInvoicePaidToDate($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereInvoicePartial($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereInvoiceStatus($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereMetadata($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent wherePaymentAmount($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent wherePaymentApplied($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent wherePaymentId($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent wherePaymentRefunded($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent wherePaymentRequest($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent wherePaymentStatus($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent wherePaymentables($value) - * @method static \Illuminate\Database\Eloquent\Builder|TransactionEvent whereTimestamp($value) * @mixin \Eloquent */ class TransactionEvent extends StaticModel @@ -79,36 +53,14 @@ class TransactionEvent extends StaticModel public $guarded = ['id']; public $casts = [ - 'metadata' => 'array', + 'metadata' => TransactionEventMetadata::class, 'payment_request' => 'array', 'paymentables' => 'array', ]; - public const INVOICE_MARK_PAID = 1; + public const INVOICE_UPDATED = 1; - public const INVOICE_UPDATED = 2; + public const INVOICE_DELETED = 2; - public const INVOICE_DELETED = 3; - - public const INVOICE_PAYMENT_APPLIED = 4; - - public const INVOICE_CANCELLED = 5; - - public const INVOICE_FEE_APPLIED = 6; - - public const INVOICE_REVERSED = 7; - - public const PAYMENT_MADE = 100; - - public const PAYMENT_APPLIED = 101; - - public const PAYMENT_REFUND = 102; - - public const PAYMENT_FAILED = 103; - - public const GATEWAY_PAYMENT_MADE = 104; - - public const PAYMENT_DELETED = 105; - - public const CLIENT_STATUS = 200; + public const PAYMENT_DELETED = 3; } diff --git a/app/Services/Invoice/ApplyPayment.php b/app/Services/Invoice/ApplyPayment.php index c355520f2d..61dbc70ad3 100644 --- a/app/Services/Invoice/ApplyPayment.php +++ b/app/Services/Invoice/ApplyPayment.php @@ -88,7 +88,7 @@ class ApplyPayment extends AbstractService ->workFlow() ->unlockDocuments() ->save(); - + return $this->invoice; } } diff --git a/app/Services/Payment/DeletePayment.php b/app/Services/Payment/DeletePayment.php index 982def5b46..df679a8bf3 100644 --- a/app/Services/Payment/DeletePayment.php +++ b/app/Services/Payment/DeletePayment.php @@ -156,6 +156,8 @@ class DeletePayment $paymentable_invoice->delete(); } + + }); } diff --git a/app/Services/Payment/PaymentService.php b/app/Services/Payment/PaymentService.php index b1384df4af..a1ac776ea4 100644 --- a/app/Services/Payment/PaymentService.php +++ b/app/Services/Payment/PaymentService.php @@ -65,6 +65,7 @@ class PaymentService ->updatePaidToDate($invoice->pivot->amount * -1) ->setStatus(Invoice::STATUS_SENT) ->save(); + } }); diff --git a/app/Services/Payment/RefundPayment.php b/app/Services/Payment/RefundPayment.php index 9c82113c31..701ed5f79b 100644 --- a/app/Services/Payment/RefundPayment.php +++ b/app/Services/Payment/RefundPayment.php @@ -309,6 +309,7 @@ class RefundPayment if ($invoice->is_deleted) { $invoice->delete(); } + } } else { diff --git a/app/Services/Payment/UpdateInvoicePayment.php b/app/Services/Payment/UpdateInvoicePayment.php index 5631727b9b..ab99e0fdd1 100644 --- a/app/Services/Payment/UpdateInvoicePayment.php +++ b/app/Services/Payment/UpdateInvoicePayment.php @@ -163,6 +163,8 @@ class UpdateInvoicePayment $invoice->service() ->applyNumber() ->save(); + + } /* Updates the company ledger */ diff --git a/app/Services/Report/TaxSummaryReport.php b/app/Services/Report/TaxSummaryReport.php index 342778d122..99c896a720 100644 --- a/app/Services/Report/TaxSummaryReport.php +++ b/app/Services/Report/TaxSummaryReport.php @@ -24,7 +24,6 @@ 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 06fdbde33e..0e58d0aef7 100644 --- a/app/Services/Report/XLS/TaxReport.php +++ b/app/Services/Report/XLS/TaxReport.php @@ -36,49 +36,20 @@ class TaxReport $t->replace(Ninja::transformTranslations($this->company->settings)); $this->spreadsheet = new Spreadsheet(); - - $this->updateTaxData(); - - // ->createGroupedTaxSummarySheetAccrual() - // ->createGroupedTaxSummarySheetCash(); + $this->buildData() + ->setCurrencyFormat() + ->createSummarySheet() + ->createInvoiceSummarySheetAccrual() + ->createInvoiceSummarySheetCash() + ->createInvoiceItemSummarySheetAccrual() + ->createInvoiceItemSummarySheetCash(); + return $this; } - private function postUpdateContinuation() - { - $this->buildData() - ->setCurrencyFormat() - ->createSummarySheet() - ->createInvoiceSummarySheetAccrual() - ->createInvoiceSummarySheetCash() - ->createInvoiceItemSummarySheetAccrual() - ->createInvoiceItemSummarySheetCash(); - } - - 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(); - - } - public function setCurrencyFormat() { $currency = $this->company->currency();