|
|
@@ -0,0 +1,111 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Services;
|
|
|
+
|
|
|
+use App\Models\UnitAccountPayable;
|
|
|
+use Carbon\Carbon;
|
|
|
+use Illuminate\Database\Eloquent\Collection;
|
|
|
+use Illuminate\Validation\ValidationException;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Contas a Pagar da unidade.
|
|
|
+ *
|
|
|
+ * Registros com origin='tbr' são criados automaticamente quando a matriz gera a
|
|
|
+ * cobrança do TBR (espelho da dívida). Registros avulsos usam origin='manual'.
|
|
|
+ * A baixa é manual (Asaas não cobra a unidade de si mesma).
|
|
|
+ */
|
|
|
+class UnitAccountPayableService
|
|
|
+{
|
|
|
+ public function list(int $unitId, array $filters = []): Collection
|
|
|
+ {
|
|
|
+ return UnitAccountPayable::where('unit_id', $unitId)
|
|
|
+ ->when(
|
|
|
+ isset($filters['status']),
|
|
|
+ fn ($q) => $q->where('status', $filters['status']),
|
|
|
+ )
|
|
|
+ ->when(
|
|
|
+ isset($filters['origin']),
|
|
|
+ fn ($q) => $q->where('origin', $filters['origin']),
|
|
|
+ )
|
|
|
+ ->orderBy('due_date')
|
|
|
+ ->get();
|
|
|
+ }
|
|
|
+
|
|
|
+ public function findForUnit(int $id, int $unitId): ?UnitAccountPayable
|
|
|
+ {
|
|
|
+ return UnitAccountPayable::where('id', $id)
|
|
|
+ ->where('unit_id', $unitId)
|
|
|
+ ->first();
|
|
|
+ }
|
|
|
+
|
|
|
+ public function createManual(int $unitId, array $data): UnitAccountPayable
|
|
|
+ {
|
|
|
+ return UnitAccountPayable::create([
|
|
|
+ 'unit_id' => $unitId,
|
|
|
+ 'origin' => UnitAccountPayable::ORIGIN_MANUAL,
|
|
|
+ 'history' => $data['history'],
|
|
|
+ 'value' => $data['value'],
|
|
|
+ 'due_date' => $data['due_date'],
|
|
|
+ 'obs' => $data['obs'] ?? null,
|
|
|
+ 'paid_value' => 0,
|
|
|
+ 'discount' => 0,
|
|
|
+ 'fine' => 0,
|
|
|
+ 'status' => 'pending',
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Baixa manual: marca a conta como paga.
|
|
|
+ */
|
|
|
+ public function settle(UnitAccountPayable $payable, array $data): UnitAccountPayable
|
|
|
+ {
|
|
|
+ if ($payable->status === 'paid') {
|
|
|
+ throw ValidationException::withMessages([
|
|
|
+ 'status' => 'Esta conta já está paga.',
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($payable->status === 'cancelled') {
|
|
|
+ throw ValidationException::withMessages([
|
|
|
+ 'status' => 'Esta conta está cancelada e não pode receber baixa.',
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ $discount = isset($data['discount']) ? (float) $data['discount'] : (float) $payable->discount;
|
|
|
+ $fine = isset($data['fine']) ? (float) $data['fine'] : (float) $payable->fine;
|
|
|
+
|
|
|
+ $paidValue = isset($data['paid_value'])
|
|
|
+ ? (float) $data['paid_value']
|
|
|
+ : round((float) $payable->value - $discount + $fine, 2);
|
|
|
+
|
|
|
+ $payable->update([
|
|
|
+ 'status' => 'paid',
|
|
|
+ 'discount' => $discount,
|
|
|
+ 'fine' => $fine,
|
|
|
+ 'paid_value' => $paidValue,
|
|
|
+ 'payment_date' => $data['payment_date'] ?? Carbon::today()->format('Y-m-d'),
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return $payable->fresh();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Reabre uma conta paga (estorno da baixa manual).
|
|
|
+ */
|
|
|
+ public function reopen(UnitAccountPayable $payable): UnitAccountPayable
|
|
|
+ {
|
|
|
+ if ($payable->status !== 'paid') {
|
|
|
+ throw ValidationException::withMessages([
|
|
|
+ 'status' => 'Só é possível reabrir contas que estão pagas.',
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ $payable->update([
|
|
|
+ 'status' => 'pending',
|
|
|
+ 'paid_value' => 0,
|
|
|
+ 'payment_date' => null,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return $payable->fresh();
|
|
|
+ }
|
|
|
+}
|