Files
portal-api/app/Repositories/Api/Invoice/InvoiceRepository.php
T
baodev0 3ed33ea7e4 Refactor VM creation and configuration process
- Updated VpsServiceResource to return product UUID instead of ID.
- Modified VirtualMachineService to utilize product data for CPU, RAM, and disk settings.
- Replaced AssignIpToGuestJob with UpdateVmConfigJob in CreateVirtualMachineJob to streamline VM configuration after cloning.
- Adjusted AssignIpToGuestJob to remove unnecessary UpdateVmConfigJob dispatch and focus on IP assignment.
- Enhanced UpdateVmConfigJob to handle CPU/RAM configuration and power cycling more effectively.
- Introduced ChangeIpVMJob for handling customer-initiated IP changes asynchronously.
- Updated InvoiceRepository to set invoice due date based on maximum months instead of a fixed 7 days.
- Improved web design quote PDF layout for better readability.
- Added Times-Roman font metrics for PDF generation.
2026-07-24 09:29:43 +07:00

108 lines
4.0 KiB
PHP

<?php
namespace App\Repositories\Api\Invoice;
use App\Enums\Invoice\InvoiceStatus;
use App\Helpers\OrderHelper;
use App\Models\Invoice;
use App\Models\InvoiceItem;
use App\Models\Order;
use App\Repositories\Api\BaseApiRepository;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
class InvoiceRepository extends BaseApiRepository implements InvoiceRepositoryInterface
{
public function getModel(): string
{
return Invoice::class;
}
// -------------------------------------------------------------------------
// getInvoice
// -------------------------------------------------------------------------
public function getInvoice(int $limit = 10, int $customerId = 0): LengthAwarePaginator
{
return $this->model
->where('customer_id', $customerId)
->orderByDesc('created_at')
->paginate($limit);
}
// -------------------------------------------------------------------------
// createFromOrder
// -------------------------------------------------------------------------
public function createFromOrder(Order $order): Invoice
{
$maxMonths = $order->orderItems->max(fn($item) => $this->cycleToMonths($item->billing_cycle)) ?? 1;
$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' => $order->total,
'discount_amount' => $order->discount_amount ?? 0,
'tax' => 0,
'total' => $order->total,
'status' => InvoiceStatus::UNPAID->value,
'due_date' => now()->addMonths($maxMonths)->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' => $this->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' => $this->cycleToMonths($item->billing_cycle),
'quantity' => $qty,
'unit_price' => $price,
'total_price' => $subtotal,
]);
}
}
return $invoice;
}
// -------------------------------------------------------------------------
// Helpers
// -------------------------------------------------------------------------
private function cycleToMonths(?string $cycle): int
{
return match ($cycle) {
'monthly' => 1,
'quarterly' => 3,
'semi_annually' => 6,
'annually' => 12,
'biennially' => 24,
'triennially' => 36,
default => 1,
};
}
}