discount_amount ?? 0); // due_date là HẠN THANH TOÁN, không phải ngày hết hạn dịch vụ — mốc dịch vụ đã có // billing_period_end và services.expires_at lo. Cho phép truyền dueDays để admin gia hạn // hạn thanh toán riêng cho một số khách. $dueDays = $dueDays ?? (int) config('billing.invoice_due_days', 30); $invoice = $this->model->create([ 'invoice_number' => OrderHelper::generateOrderNumber('INV'), 'customer_id' => $order->customer_id, 'order_id' => $order->id, 'invoice_type' => 1, // new service // sub_total là tổng TRƯỚC giảm giá, để sub_total - discount_amount = total. 'sub_total' => (int) $order->total + $discount, 'discount_amount' => $discount, 'coupon_code' => $order->coupon_code, 'tax' => 0, 'total' => $order->total, 'status' => InvoiceStatus::UNPAID->value, 'due_date' => now()->addDays($dueDays)->toDateString(), ]); // Create one invoice_item per order_item line + addon sub-lines foreach ($order->orderItems as $item) { InvoiceItem::create([ 'invoice_id' => $invoice->id, 'product_id' => $item->product_id, 'type' => 'service', 'description' => $item->product?->name ?? 'Dịch vụ', 'months' => OrderHelper::cycleToMonths($item->billing_cycle), 'quantity' => $item->quantity ?? 1, 'unit_price' => $item->price, 'total_price' => $item->price * ($item->quantity ?? 1), ]); $addonsMeta = is_array($item->addons_meta) ? $item->addons_meta : []; foreach ($addonsMeta as $meta) { $qty = (int) ($meta['qty'] ?? 1); $price = (int) ($meta['price'] ?? 0); $subtotal = (int) ($meta['subtotal'] ?? $price * $qty); $name = $meta['name'] ?? ('Addon #' . ($meta['addon_id'] ?? '?')); $code = strtoupper($meta['code'] ?? ''); $label = $code ? "[{$code}] {$name}" : $name; InvoiceItem::create([ 'invoice_id' => $invoice->id, 'product_id' => $item->product_id, 'type' => 'addon', 'description' => $label, 'months' => OrderHelper::cycleToMonths($item->billing_cycle), 'quantity' => $qty, 'unit_price' => $price, 'total_price' => $subtotal, ]); } } return VatNumbering::settle($invoice); } // ------------------------------------------------------------------------- // Helpers // ------------------------------------------------------------------------- }