commit5
tests / ci (push) Canceled after 0s

This commit is contained in:
2026-10-29 22:03:09 +02:00
parent 57f6b3cc36
commit 413c201d97
54 changed files with 2753 additions and 14 deletions
+22 -2
View File
@@ -30,6 +30,11 @@ class ExternalPaymentWorkflow
public function outstanding(Invoice $invoice): int
{
$canonical = app(SupplierPayables::class)->balance($invoice);
if ($canonical !== null) {
return $canonical;
}
return (int) $invoice->total_minor - (int) ExternalPayment::query()->where('invoice_id', $invoice->id)->where('status', 'confirmed')->sum('amount_minor');
}
@@ -59,6 +64,7 @@ class ExternalPaymentWorkflow
/** @param array<string,mixed> $data */
public function register(User $user, Invoice $invoice, array $data): ExternalPayment
{
abort_if(app(SupplierPayables::class)->principal($invoice) !== null, 403, 'Pagamento de obrigação do novo ensaio fora do âmbito.');
$this->actor($user, $invoice->tenant_id);
return DB::transaction(function () use ($user, $invoice, $data) {
@@ -66,6 +72,7 @@ class ExternalPaymentWorkflow
$user = User::query()->where('tenant_id', $user->tenant_id)->lockForUpdate()->findOrFail($user->id);
$this->actor($user, $invoice->tenant_id);
$invoice = Invoice::query()->lockForUpdate()->findOrFail($invoice->id);
abort_if(app(SupplierPayables::class)->principal($invoice) !== null, 403, 'Pagamento de obrigação do novo ensaio fora do âmbito.');
$reference = Str::upper(Str::squish($data['external_reference']));
$amount = BigDecimal::of((string) $data['amount'])->multipliedBy(100)->toScale(0)->toInt();
$canonical = ['invoice_id' => $invoice->id, 'bank_id' => (int) $data['supplier_bank_detail_id'], 'amount_minor' => $amount, 'paid_on' => $data['paid_on'], 'evidence_reference' => trim($data['evidence_reference'])];
@@ -102,7 +109,9 @@ class ExternalPaymentWorkflow
$user = User::query()->where('tenant_id', $user->tenant_id)->lockForUpdate()->findOrFail($user->id);
$this->actor($user, $payment->tenant_id);
$invoice = Invoice::query()->lockForUpdate()->findOrFail($payment->invoice_id);
$historical = app(SupplierPayables::class)->assertHistoricalReview($user, $invoice);
$payment = ExternalPayment::query()->lockForUpdate()->findOrFail($payment->id);
abort_if($payment->created_by === $user->id, 403);
if ($payment->status !== 'pending') {
if ($payment->status !== $decision) {
$this->invalid('Conferência já decidida; não pode ser reescrita.');
@@ -122,8 +131,19 @@ class ExternalPaymentWorkflow
$this->invalid('O autor do registo deixou de ser elegível.');
}
}
$payment->update(['status' => $decision, 'reviewed_by' => $user->id, 'review_reason' => $reason, 'reviewed_at' => now()]);
$this->audit($user, $invoice, $payment, 'payment.'.$decision);
$write = function () use ($payment, $decision, $user, $reason, $invoice) {
$payment->update(['status' => $decision, 'reviewed_by' => $user->id, 'review_reason' => $reason, 'reviewed_at' => now()]);
$this->audit($user, $invoice, $payment, 'payment.'.$decision);
};
if ($historical) {
try {
app(SupplierPayables::class)->engine($user)->decideImportedPayment($invoice->id, $payment->id, $write);
} catch (\DomainException $e) {
abort(409, $e->getMessage());
}
} else {
$write();
}
});
}