- Create a new Blade view for domain registration (`registrant-tochuc.blade.php`) to capture organization and manager details. - Implement email templates for new domain orders for both admin (`domain-order-new.blade.php`) and customers (`domain-order-received.blade.php`). - Add CSV exports for client and domain data. - Introduce tests for customer mass assignment, password reset, login throttling, and permission gating. - Ensure service renewals use current pricing and validate ownership for virtual machines. - Validate mass assignment behavior in service model.
115 lines
4.6 KiB
PHP
115 lines
4.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Api\Client\Domain;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\Api\Client\Domain\StoreDomainOrderRequest;
|
|
use App\Mail\Admin\DomainOrderNewNotification;
|
|
use App\Mail\Customer\DomainOrderReceivedNotification;
|
|
use App\Models\Customer;
|
|
use App\Models\Notification;
|
|
use App\Models\Setting;
|
|
use App\Services\Api\Domain\DomainOrderService;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Mail;
|
|
|
|
class DomainOrderController extends Controller
|
|
{
|
|
public function __construct(
|
|
private readonly DomainOrderService $domainOrderService,
|
|
) {}
|
|
|
|
public function store(StoreDomainOrderRequest $request): JsonResponse
|
|
{
|
|
try {
|
|
$result = $this->domainOrderService->placeOrder($request->validated(), $request->user());
|
|
|
|
$this->notifyDomainOrderPlaced($request->user(), $result);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Đặt mua tên miền thành công.',
|
|
'notice' => 'Việc đặt mua không đồng nghĩa tên miền đã được đăng ký thành công. Đơn hàng sẽ được nhân viên kiểm tra và xử lý. Nếu tên miền không còn khả dụng, số dư đã thanh toán sẽ được hoàn lại vào tài khoản.',
|
|
'data' => [
|
|
'order_num' => $result['order']->order_num,
|
|
'domain_name' => $result['order']->orderItems->first()?->domain_name,
|
|
'status' => 'pending',
|
|
'total' => $result['invoice']->total,
|
|
'invoice_number' => $result['invoice']->invoice_number,
|
|
],
|
|
], 201);
|
|
} catch (\InvalidArgumentException $e) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => $e->getMessage(),
|
|
], 422);
|
|
} catch (\Throwable $e) {
|
|
Log::error('DomainOrderController@store', [
|
|
'error' => $e->getMessage(),
|
|
'customer_id' => $request->user()?->id,
|
|
'data' => $request->validated(),
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Đặt mua tên miền thất bại. Vui lòng thử lại.',
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
private function notifyDomainOrderPlaced(Customer $customer, array $result): void
|
|
{
|
|
$domainName = $result['order']->orderItems->first()?->domain_name ?? '';
|
|
$orderNum = $result['order']->order_num;
|
|
$total = number_format((int) $result['invoice']->total) . ' VNĐ';
|
|
$createdAt = now()->format('d/m/Y H:i:s');
|
|
|
|
Notification::notifyAdmins([
|
|
'type' => 'domain_order_new',
|
|
'title' => 'Đơn đăng ký tên miền mới',
|
|
'body' => "Khách hàng {$customer->fullname} vừa đặt mua tên miền {$domainName} (#{$orderNum})",
|
|
'link' => '/domain-orders',
|
|
]);
|
|
|
|
$setting = Setting::where('key', 'setting')->first();
|
|
$settingValue = $setting ? json_decode((string) $setting->value, true) : [];
|
|
$companyName = $settingValue['company'] ?? config('app.name');
|
|
$adminEmail = $settingValue['admin_email'] ?? null;
|
|
|
|
$mailData = [
|
|
'company_name' => $companyName,
|
|
'domain_name' => $domainName,
|
|
'customer_name' => $customer->fullname,
|
|
'customer_email' => $customer->email,
|
|
'order_num' => $orderNum,
|
|
'order_total' => $total,
|
|
'created_at' => $createdAt,
|
|
];
|
|
|
|
if (!empty($adminEmail)) {
|
|
try {
|
|
$adminUrl = rtrim(env('ADMIN_URL', config('app.url')), '/') . '/domain-orders';
|
|
|
|
Mail::to($adminEmail)->send(
|
|
new DomainOrderNewNotification([...$mailData, 'admin_url' => $adminUrl])
|
|
);
|
|
} catch (\Throwable $e) {
|
|
Log::error('DomainOrderController: không thể gửi email admin: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
try {
|
|
$orderUrl = rtrim(config('app.frontend_url', ''), '/') . '/don-hang';
|
|
|
|
Mail::to($customer->email)->send(
|
|
new DomainOrderReceivedNotification([...$mailData, 'order_url' => $orderUrl])
|
|
);
|
|
} catch (\Throwable $e) {
|
|
Log::error('DomainOrderController: không thể gửi email khách hàng: ' . $e->getMessage());
|
|
}
|
|
}
|
|
}
|