feat(billing): renewals, coupons, VAT numbering, billing cycles and invoice payment tracking

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
baodev0
2026-10-19 16:37:56 +07:00
co-authored by Claude Sonnet 5.5
parent ea9a53f742
commit 25f23d541e
134 changed files with 4926 additions and 185 deletions
@@ -0,0 +1,41 @@
<?php
namespace App\Http\Controllers\Api\Admin\Setting;
use App\Http\Controllers\Controller;
use App\Models\Invoice;
use App\Support\VatSettings;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class VatNumberingController extends Controller
{
public function show(): JsonResponse
{
return response()->json(['error' => false, 'data' => VatSettings::numbering()]);
}
public function update(Request $request): JsonResponse
{
$data = $request->validate([
'serial' => 'required|string|max:20|regex:/^[A-Za-z0-9]+$/',
'next_number' => 'required|integer|min:1',
'padding' => 'required|integer|min:1|max:12',
'auto_issue' => 'required|boolean',
]);
$data['serial'] = strtoupper($data['serial']);
$lastIssued = Invoice::query()->where('vat_serial', $data['serial'])->whereNotNull('vat_number')->max('vat_number');
if ($lastIssued !== null && $data['next_number'] <= (int) $lastIssued) {
return response()->json([
'error' => true,
'message' => "Số tiếp theo phải lớn hơn số đã cấp gần nhất ({$lastIssued}) của ký hiệu {$data['serial']}",
], 422);
}
VatSettings::saveNumbering($data);
return response()->json(['error' => false, 'message' => 'Đã lưu cấu hình đánh số hóa đơn VAT', 'data' => VatSettings::numbering()]);
}
}