resolveCustomer($uuid); $invoices = $this->invoiceRepository->filter(['customer_id' => $customer->id], ['payment']); // Frontend đọc ngày thanh toán qua `date_paid` — alias từ cột paid_at. $invoices->each(fn($invoice) => $invoice->date_paid = $invoice->paid_at); return $invoices; } /** * Sửa hóa đơn của khách hàng, kể cả số tiền (sub_total/tax/total). Không * tự đồng bộ lại invoice_items hay customer.total. */ public function updateInvoice(string $uuid, int $invoiceId, array $data): Invoice { $customer = $this->resolveCustomer($uuid); $invoice = Invoice::where('customer_id', $customer->id)->where('id', $invoiceId)->first(); abort_if(!$invoice, 404, 'Không tìm thấy hóa đơn'); // `date_paid` là tên field phía frontend — cột thật trong DB là paid_at. if (array_key_exists('date_paid', $data)) { $data['paid_at'] = $data['date_paid']; unset($data['date_paid']); } if (array_key_exists('amount_paid', $data) && $data['amount_paid'] === null) { unset($data['amount_paid']); } if (isset($data['amount_paid']) && $data['amount_paid'] > (int) ($data['total'] ?? $invoice->total)) { abort(422, 'Số tiền đã thu không được lớn hơn tổng hóa đơn'); } // Đi qua repository (không gọi $invoice->update() trực tiếp) để cache // của invoiceRepository->filter() (dùng ở getInvoices) được xoá theo, // nếu không danh sách hóa đơn sẽ hiển thị dữ liệu cũ cho tới khi cache hết hạn. $this->invoiceRepository->update($invoiceId, $data); $invoice = $invoice->refresh(); $invoice->date_paid = $invoice->paid_at; return $invoice->load('payment'); } public function getTransactions(string $uuid): Collection { $customer = $this->resolveCustomer($uuid); return $this->transactionRepository->filter(['customer_id' => $customer->id], ['user']); } /** * Sửa thông tin giao dịch, kể cả amount (để sửa số tiền nhập/hiển thị sai). * Không tự động cộng/trừ lại customer.total khi sửa amount — chiều +/- của * amount phụ thuộc vào type (balance trừ tiền, transfer/admin_add_total * cộng tiền,...) và không có field nào lưu lại chiều đó, nên tự suy luận * dễ làm sai số dư hơn là sửa đúng. Nếu cần đồng bộ lại số dư, dùng * "Cộng tiền" ở tab Tổng quan sau khi sửa xong. */ public function updateTransaction(string $uuid, int $transactionId, array $data): Transaction { $customer = $this->resolveCustomer($uuid); $transaction = Transaction::where('customer_id', $customer->id)->where('id', $transactionId)->first(); abort_if(!$transaction, 404, 'Không tìm thấy giao dịch'); // Đi qua repository để cache của transactionRepository->filter() // (dùng ở getTransactions) được xoá theo — xem ghi chú ở updateInvoice. $this->transactionRepository->update($transactionId, $data); return $transaction->refresh()->load('user'); } public function createTransaction(string $uuid, array $data, ?int $adminId): Transaction { $customer = $this->resolveCustomer($uuid); $transaction = $this->transactionRepository->create([ 'uuid' => (string) Str::uuid(), 'public_code' => Transaction::newPublicCode('ADM'), 'trans' => $data['trans'] ?? null, 'amount' => $data['amount'], 'received_amount' => $data['amount'], 'customer_id' => $customer->id, 'user_id' => $adminId, 'status' => $data['status'] ?? TransactionStatus::COMPLETED->value, 'type' => 'admin_record', 'note' => $data['note'] ?? null, ]); return $transaction->load('user'); } public function deleteTransaction(string $uuid, int $transactionId): void { $customer = $this->resolveCustomer($uuid); $exists = Transaction::where('customer_id', $customer->id)->where('id', $transactionId)->exists(); abort_if(!$exists, 404, 'Không tìm thấy giao dịch'); $this->transactionRepository->delete($transactionId); } public function getOrders(string $uuid): Collection { $customer = $this->resolveCustomer($uuid); $orders = $this->orderRepository->filter(['client' => $customer->id], [ 'customer', 'user:id,username', 'payment', 'invoices', ...OrderItemServiceResource::relationsFor('orderItems'), ]); $orders->each(fn ($order) => $order->invoices->each(fn ($invoice) => $invoice->date_paid = $invoice->paid_at)); return $orders; } /** * Sửa đơn hàng của khách hàng, kể cả số tiền (sub_total/discount_amount/ * total). Không tự đồng bộ lại invoice/invoice_item hay customer.total — * nếu số tiền hóa đơn liên kết cũng cần sửa, sửa riêng ở updateInvoice. */ public function updateOrder(string $uuid, int $orderId, array $data): Order { $customer = $this->resolveCustomer($uuid); $order = Order::where('customer_id', $customer->id)->where('id', $orderId)->first(); abort_if(!$order, 404, 'Không tìm thấy đơn hàng'); // Đi qua repository để cache của orderRepository->filter() // (dùng ở getOrders) được xoá theo — xem ghi chú ở updateInvoice. $this->orderRepository->update($orderId, $data); return $order->refresh()->load(['payment', 'invoices']); } }