|
|
@@ -4,6 +4,7 @@
|
|
|
|
|
|
use App\Enums\ReceivableStatus;
|
|
|
use App\Models\FranchiseeAccountReceive;
|
|
|
+use App\Models\StudentContractInstallment;
|
|
|
use Illuminate\Bus\Queueable;
|
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
|
use Illuminate\Foundation\Bus\Dispatchable;
|
|
|
@@ -51,17 +52,44 @@ public function handle(): void
|
|
|
$asaasId = $payment['id'] ?? null;
|
|
|
|
|
|
$receive = null;
|
|
|
+ $type = 'unknown';
|
|
|
|
|
|
if ($externalReference) {
|
|
|
- $receive = FranchiseeAccountReceive::find($externalReference);
|
|
|
+ // Se for um recebível de Franquia
|
|
|
+ if (str_starts_with($externalReference, 'TBR_')) {
|
|
|
+ $id = str_replace('TBR_', '', $externalReference);
|
|
|
+ $receive = FranchiseeAccountReceive::find($id);
|
|
|
+ $type = 'FranchiseeAccountReceive';
|
|
|
+ }
|
|
|
+ // Se for parcela de aluno
|
|
|
+ elseif (str_starts_with($externalReference, 'STU_')) {
|
|
|
+ $id = str_replace('STU_', '', $externalReference);
|
|
|
+ $receive = StudentContractInstallment::find($id);
|
|
|
+ $type = 'StudentContractInstallment';
|
|
|
+ }
|
|
|
+ // Backward compatibility para faturas de teste geradas antes do prefixo
|
|
|
+ elseif (is_numeric($externalReference)) {
|
|
|
+ $receive = FranchiseeAccountReceive::find($externalReference);
|
|
|
+ $type = 'FranchiseeAccountReceive (legacy)';
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ // Fallback por asaas_id caso externalReference venha nulo
|
|
|
if (!$receive && $asaasId) {
|
|
|
$receive = FranchiseeAccountReceive::where('asaas_id', $asaasId)->first();
|
|
|
+
|
|
|
+ if ($receive) {
|
|
|
+ $type = 'FranchiseeAccountReceive (by asaas_id)';
|
|
|
+ } else {
|
|
|
+ $receive = StudentContractInstallment::where('asaas_id', $asaasId)->first();
|
|
|
+ if ($receive) {
|
|
|
+ $type = 'StudentContractInstallment (by asaas_id)';
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (!$receive) {
|
|
|
- Log::warning("Asaas Webhook Job: recebível não encontrado", [
|
|
|
+ Log::warning("Asaas Webhook Job: registro não encontrado", [
|
|
|
'externalReference' => $externalReference,
|
|
|
'asaas_id' => $asaasId,
|
|
|
'event' => $event,
|
|
|
@@ -69,27 +97,31 @@ public function handle(): void
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // Se já está pago, não processa de novo
|
|
|
- if ($receive->status === ReceivableStatus::PAID && $newStatus === ReceivableStatus::PAID) {
|
|
|
- Log::info("Asaas Webhook Job: recebível #{$receive->id} já está pago. Ignorando duplicata.");
|
|
|
+ // Conversão de status: se a model usa string (como StudentContractInstallment)
|
|
|
+ // Precisamos comparar de forma segura
|
|
|
+ $currentStatus = $receive->status instanceof ReceivableStatus ? $receive->status->value : $receive->status;
|
|
|
+ $newStatusValue = $newStatus instanceof ReceivableStatus ? $newStatus->value : $newStatus;
|
|
|
+
|
|
|
+ // Idempotência
|
|
|
+ if ($currentStatus === ReceivableStatus::PAID->value && $newStatusValue === ReceivableStatus::PAID->value) {
|
|
|
+ Log::info("Asaas Webhook Job: registro {$type} #{$receive->id} já está pago. Ignorando duplicata.");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // Atualizar o status
|
|
|
$updateData = [
|
|
|
- 'status' => $newStatus,
|
|
|
+ 'status' => $newStatusValue,
|
|
|
'asaas_status' => $payment['status'] ?? $event,
|
|
|
];
|
|
|
|
|
|
- // Se foi pago, registrar a data de pagamento e o valor pago
|
|
|
- if ($newStatus === ReceivableStatus::PAID) {
|
|
|
+ if ($newStatusValue === ReceivableStatus::PAID->value) {
|
|
|
$updateData['payment_date'] = $payment['paymentDate'] ?? $payment['confirmedDate'] ?? now();
|
|
|
+ // A tabela do Aluno usa 'paid_value', a tabela da Franquia também.
|
|
|
$updateData['paid_value'] = $payment['value'] ?? $receive->value;
|
|
|
}
|
|
|
|
|
|
$receive->update($updateData);
|
|
|
|
|
|
- Log::info("Asaas Webhook Job: recebível #{$receive->id} atualizado para '{$newStatus->value}'", [
|
|
|
+ Log::info("Asaas Webhook Job: {$type} #{$receive->id} atualizado para '{$newStatusValue}'", [
|
|
|
'event' => $event,
|
|
|
'asaas_id' => $asaasId,
|
|
|
]);
|