Add feature tests for domain order management

- Implement AdminDomainOrderTest to cover admin functionalities for domain orders including listing, confirming registration, KYC updates, activation, rejection, and refunds.
- Implement ClientDomainOrderTest to cover client functionalities for placing domain orders, including validation for balance, duplicate orders, and domain normalization.
- Ensure proper handling of domain pricing and service statuses throughout the tests.
This commit is contained in:
baodev0
2026-07-10 14:16:35 +07:00
parent 61c0e026c8
commit dfb926055d
81 changed files with 35743 additions and 481 deletions
@@ -5,10 +5,11 @@ namespace App\Http\Controllers\Api\Admin\Customer;
use App\Http\Controllers\Controller;
use App\Http\Requests\CreateCustomerRequest;
use App\Http\Resources\Api\Admin\CustomerResource;
use App\Jobs\Mail\PasswordRecoverJob;
use App\Mail\Customer\ManualCustomerEmail;
use App\Models\Customer;
use App\Models\Invoice;
use App\Models\Order;
use App\Models\Template;
use App\Models\Transaction;
use App\Models\Log;
use App\Repositories\Customer\CustomerRepositoryInterface;
@@ -25,6 +26,7 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use App\Enums\Invoice\InvoiceStatus;
use App\Enums\Order\OrderStatus;
@@ -233,11 +235,31 @@ class CustomerController extends Controller
public function trash(Request $request): JsonResponse
{
$query = $this->customerRepository->onlyTrashed([], ['hosting', 'vps', 'domain']);
$perPage = min((int) $request->get('per_page', 15), 500);
$query = Customer::onlyTrashed()
->with(['hosting', 'vps', 'domain']);
if ($filter = $request->get('filter')) {
$query->where(function ($q) use ($filter) {
$filter = trim($filter);
$q->where('fullname', 'LIKE', "%{$filter}%")
->orWhere('email', 'LIKE', "%{$filter}%")
->orWhere('phone', 'LIKE', "%{$filter}%");
});
}
$paginator = $query->paginate($perPage);
return response()->json([
'error' => false,
'data' => CustomerResource::collection($query->get())
'data' => [
'items' => CustomerResource::collection($paginator),
'total' => $paginator->total(),
'per_page' => $paginator->perPage(),
'current_page' => $paginator->currentPage(),
'last_page' => $paginator->lastPage(),
],
]);
}
@@ -462,6 +484,105 @@ class CustomerController extends Controller
}
}
public function sendEmail(Request $request, string $uuid): JsonResponse
{
$data = $request->validate([
'template_id' => 'nullable|integer|exists:template,id',
'subject' => 'required_without:template_id|nullable|string|max:255',
'message' => 'required_without:template_id|nullable|string',
'to' => 'nullable|string|max:1000',
'cc' => 'nullable|string|max:1000',
'bcc' => 'nullable|string|max:1000',
]);
$customer = $this->customerRepository->findBy('uuid', $uuid);
if (!$customer) {
return response()->json([
'error' => true,
'message' => "Can't find customer by UUID #" . $uuid,
], 404);
}
$template = null;
$subject = trim((string) ($data['subject'] ?? ''));
$message = trim((string) ($data['message'] ?? ''));
if (!empty($data['template_id'])) {
$template = Template::query()
->whereKey($data['template_id'])
->where('status', 1)
->first();
if (!$template) {
return response()->json([
'error' => true,
'message' => 'Template không tồn tại hoặc đang bị tắt.',
], 422);
}
$subject = trim((string) $template->subject);
$message = trim((string) $template->message);
}
if ($subject === '' || $message === '') {
return response()->json([
'error' => true,
'message' => 'Subject và content không được để trống.',
], 422);
}
$to = $this->parseEmailRecipients($data['to'] ?? null);
if ($to === []) {
$to = [$customer->email];
}
$cc = $this->parseEmailRecipients($data['cc'] ?? null);
$bcc = $this->parseEmailRecipients($data['bcc'] ?? null);
if ($to === []) {
return response()->json([
'error' => true,
'message' => 'Không có địa chỉ email nhận hợp lệ.',
], 422);
}
try {
$mailer = Mail::to($to);
if ($cc !== []) {
$mailer->cc($cc);
}
if ($bcc !== []) {
$mailer->bcc($bcc);
}
$mailer->send(new ManualCustomerEmail($subject, $message));
$admin = Auth::guard('admin')->user();
Log::create([
'agent' => 'admin',
'client_ip' => $request->ip(),
'description' => sprintf(
'%s gửi email cho customer %s%s',
$admin->username ?? $admin->email ?? 'Admin',
$customer->email,
$template ? sprintf(' bằng template #%s', $template->id) : '',
),
'customer_id' => $customer->id,
]);
return response()->json([
'error' => false,
'message' => 'Đã gửi email cho khách hàng.',
]);
} catch (\Throwable $e) {
return response()->json([
'error' => true,
'message' => $e->getMessage(),
], 500);
}
}
public function addCredit(Request $request, string $uuid): JsonResponse
{
$request->validate([
@@ -510,6 +631,20 @@ class CustomerController extends Controller
}
}
private function parseEmailRecipients(?string $value): array
{
if (!$value) {
return [];
}
return collect(preg_split('/[,;]+/', $value) ?: [])
->map(fn($email) => trim((string) $email))
->filter(fn($email) => $email !== '' && filter_var($email, FILTER_VALIDATE_EMAIL))
->unique()
->values()
->all();
}
public function addTotal(Request $request, string $uuid): JsonResponse
{
$request->validate([