Kaynağa Gözat

feat(unit-receivable): endpoint de gerar cobrança sob demanda e campos Asaas no resource

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ebagabee 4 hafta önce
ebeveyn
işleme
f97bf8a29d

+ 22 - 0
app/Http/Controllers/UnitReceivableController.php

@@ -53,6 +53,28 @@ public function settleMe(SettleReceivableRequest $request, int $id): JsonRespons
         );
     }
 
+    public function chargeMe(int $id): JsonResponse
+    {
+        $unitId = $this->activeUnitId();
+
+        if (!$unitId) {
+            return $this->errorResponse(message: 'Unidade não encontrada', code: 404);
+        }
+
+        $installment = $this->service->findForUnit($id, $unitId);
+
+        if (!$installment) {
+            return $this->errorResponse(message: 'Recebível não encontrado', code: 404);
+        }
+
+        $item = $this->service->generateCharge($installment);
+
+        return $this->successResponse(
+            payload: new UnitReceivableResource($item),
+            message: 'Cobrança gerada no Asaas',
+        );
+    }
+
     public function reopenMe(int $id): JsonResponse
     {
         $unitId = $this->activeUnitId();

+ 3 - 0
app/Http/Resources/UnitReceivableResource.php

@@ -27,6 +27,9 @@ public function toArray(Request $request): array
             'payment_date'        => $this->payment_date?->format('Y-m-d'),
             'status'              => $this->status,
             'asaas_id'            => $this->asaas_id,
+            'invoice_url'         => $this->invoice_url,
+            'billing_type'        => $this->billing_type,
+            'asaas_status'        => $this->asaas_status,
         ];
     }
 }

+ 39 - 0
app/Services/UnitReceivableService.php

@@ -2,7 +2,10 @@
 
 namespace App\Services;
 
+use App\Exceptions\AsaasException;
+use App\Jobs\SyncStudentChargeJob;
 use App\Models\StudentContractInstallment;
+use App\Models\UnitPaymentAccount;
 use Carbon\Carbon;
 use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Validation\ValidationException;
@@ -80,6 +83,42 @@ public function settle(StudentContractInstallment $installment, array $data): St
         return $installment->fresh(['student']);
     }
 
+    /**
+     * Gera a cobrança da parcela na conta Asaas da unidade (sob demanda).
+     */
+    public function generateCharge(StudentContractInstallment $installment): StudentContractInstallment
+    {
+        if ($installment->status === 'cancelled') {
+            throw ValidationException::withMessages([
+                'status' => 'Parcela cancelada não pode ser cobrada.',
+            ]);
+        }
+
+        if ($installment->asaas_id) {
+            throw ValidationException::withMessages([
+                'asaas' => 'Esta parcela já possui cobrança gerada.',
+            ]);
+        }
+
+        $account = UnitPaymentAccount::where('unit_id', $installment->unit_id)->first();
+
+        if (!$account || empty($account->asaas_api_key)) {
+            throw ValidationException::withMessages([
+                'asaas' => 'A unidade não possui chave Asaas configurada.',
+            ]);
+        }
+
+        try {
+            SyncStudentChargeJob::dispatchSync($installment);
+        } catch (AsaasException $e) {
+            throw ValidationException::withMessages([
+                'asaas' => 'Não foi possível gerar a cobrança na Asaas. Tente novamente.',
+            ]);
+        }
+
+        return $installment->fresh(['student']);
+    }
+
     /**
      * Reabre uma parcela paga (estorno da baixa manual).
      */

+ 1 - 0
routes/authRoutes/unit_receivable.php

@@ -5,6 +5,7 @@
 
 Route::controller(UnitReceivableController::class)->prefix('unit-receivable')->group(function () {
     Route::get('/me', 'indexMe');
+    Route::post('/me/{id}/charge', 'chargeMe');
     Route::post('/me/{id}/settle', 'settleMe');
     Route::post('/me/{id}/reopen', 'reopenMe');
 });