invoiceRepository->find($id); if (!$invoice) { return response()->json([ 'error' => true, 'message' => "Can't find invoice by ID #" . $id ], 404); } if ($disabled = $this->mailDisabledResponse()) { return $disabled; } if (!$reminders->isRemindable($invoice)) { return response()->json([ 'error' => true, 'message' => 'Chỉ nhắc được hoá đơn chưa thanh toán hoặc quá hạn.', ], 422); } try { AutoEmailGate::markManual(); $reminders->remind($invoice->load('customer'), force: true); } catch (\Throwable $e) { return response()->json([ 'error' => true, 'message' => 'Không gửi được email nhắc: ' . $e->getMessage(), ], 500); } return response()->json([ 'error' => false, 'message' => 'Đã gửi email nhắc thanh toán tới ' . $invoice->customer?->email, ]); } public function previewMail(Request $request, int $id): JsonResponse { $invoice = $this->invoiceForMail($request, $id); if ($invoice instanceof JsonResponse) { return $invoice; } $mail = InvoiceNotificationMail::forInvoice($invoice, $request->input('type') ?: 'invoice', $request->input('message')); return response()->json([ 'error' => false, 'data' => [ 'to' => $invoice->customer->email, 'subject' => $mail->envelope()->subject, 'html' => $mail->render(), 'attachment_filename' => $this->invoicePdfService->generateFileName($invoice), ], ]); } public function sendMail(Request $request, int $id): JsonResponse { if ($disabled = $this->mailDisabledResponse()) { return $disabled; } $invoice = $this->invoiceForMail($request, $id); if ($invoice instanceof JsonResponse) { return $invoice; } AutoEmailGate::markManual(); $jobId = Queue::push(new SendInvoiceMailJob( $invoice->id, $request->input('type') ?: 'invoice', $request->input('message'), $request->input('subject'), $request->filled('html') ? $request->input('html') : null, Auth::guard('admin')->id(), )); return response()->json([ 'error' => false, 'message' => "Đã đưa email vào hàng đợi gửi tới {$invoice->customer->email}", 'data' => ['job_id' => $jobId], ]); } private function mailDisabledResponse(): ?JsonResponse { return AutoEmailGate::mailEnabled() ? null : response()->json([ 'error' => true, 'message' => 'Chức năng gửi email đang tắt. Bật lại tại Cài đặt → Thông báo.', ], 422); } private function invoiceForMail(Request $request, int $id): Invoice|JsonResponse { $request->validate([ 'message' => 'nullable|string|max:1000', 'type' => 'nullable|string|in:invoice,renewal', 'subject' => 'nullable|required_with:html|string|max:255', 'html' => 'nullable|required_with:subject|string|max:500000', ]); $invoice = $this->invoiceRepository->find($id); if (!$invoice) { return response()->json(['error' => true, 'message' => "Can't find invoice #$id"], 404); } $invoice->load('customer'); if (!$invoice->customer?->email) { return response()->json(['error' => true, 'message' => 'Customer email not found'], 422); } return $invoice; } }