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:
co-authored by
Claude Sonnet 5.5
parent
ea9a53f742
commit
25f23d541e
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Resources\Api\Admin;
|
||||
|
||||
use App\Support\Billing\BillingDuplicateDetector;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
@@ -12,6 +13,7 @@ class InvoiceResource extends JsonResource
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'invoice_number' => $this->invoice_number,
|
||||
'duplicate' => BillingDuplicateDetector::forInvoice($this->id),
|
||||
'order_num' => $this->whenLoaded('order', fn() => $this->order?->order_num),
|
||||
'order_items' => $this->when(
|
||||
$this->relationLoaded('order') && $this->order?->relationLoaded('orderItems'),
|
||||
@@ -25,6 +27,7 @@ class InvoiceResource extends JsonResource
|
||||
]),
|
||||
'sub_total' => $this->sub_total,
|
||||
'discount_amount' => $this->discount_amount,
|
||||
'coupon_code' => $this->coupon_code,
|
||||
'tax' => $this->tax,
|
||||
'total' => $this->total,
|
||||
// Công nợ: đã thu bao nhiêu / còn thiếu bao nhiêu. Kế toán cần thấy ngay trên
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Resources\Api\Admin;
|
||||
|
||||
use App\Support\Billing\BillingDuplicateDetector;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
@@ -12,6 +13,7 @@ class OrderResource extends JsonResource
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'order_num' => $this->order_num,
|
||||
'duplicate' => BillingDuplicateDetector::forOrder($this->id),
|
||||
'customer' => $this->whenLoaded('customer', fn() => [
|
||||
'id' => $this->customer->id,
|
||||
'uuid' => $this->customer->uuid,
|
||||
@@ -95,6 +97,7 @@ class OrderResource extends JsonResource
|
||||
])),
|
||||
'sub_total' => $this->sub_total,
|
||||
'discount_amount' => $this->discount_amount,
|
||||
'coupon_code' => $this->coupon_code,
|
||||
'total' => $this->total,
|
||||
// Order has no payment_id FK — `payment` relation is always null. Fall back to
|
||||
// the raw payment_method string instead of letting whenLoaded() mask it with null.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Resources\Api\Admin;
|
||||
|
||||
use App\Support\BillingCycleCatalog;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
@@ -37,6 +38,8 @@ class ProductResource extends JsonResource
|
||||
'bandwidth' => $this->bandwidth,
|
||||
'domain_count' => $this->domain_count,
|
||||
'features' => $this->features,
|
||||
'short_description' => $this->short_description,
|
||||
'description' => $this->description,
|
||||
'setup_fee' => $this->setup_fee,
|
||||
'min_price' => $minPrice,
|
||||
'billing_type' => $this->whenLoaded('pricings', function () {
|
||||
@@ -52,6 +55,9 @@ class ProductResource extends JsonResource
|
||||
'price_annually' => $this->whenLoaded('pricings', fn () => optional($this->pricings->firstWhere('billing_cycle', 'annually'))->price),
|
||||
'price_biennially' => $this->whenLoaded('pricings', fn () => optional($this->pricings->firstWhere('billing_cycle', 'biennially'))->price),
|
||||
'price_triennially' => $this->whenLoaded('pricings', fn () => optional($this->pricings->firstWhere('billing_cycle', 'triennially'))->price),
|
||||
'custom_prices' => $this->whenLoaded('pricings', fn () => $this->pricings
|
||||
->filter(fn ($pricing) => str_starts_with((string) $pricing->billing_cycle, BillingCycleCatalog::CODE_PREFIX))
|
||||
->mapWithKeys(fn ($pricing) => [$pricing->billing_cycle => $pricing->price])),
|
||||
'price_onetime' => $this->whenLoaded('pricings', fn () => optional($this->pricings->first(fn ($pricing) => in_array($pricing->billing_cycle, ['onetime', 'one_time'], true)))->price),
|
||||
'is_active' => $this->is_active,
|
||||
'created_at' => $this->created_at,
|
||||
|
||||
Reference in New Issue
Block a user