- Mail campaign: mẫu nhắc gia hạn thanh toán QR, chọn dịch vụ + chu kỳ từng dòng (renewal_services) - Hosting: nhiều server Plesk cho một gói (service_plan_servers), chuyển server khi server chết - Admin xem/sửa giấy tờ định danh khách, tuỳ chọn gia hạn cho khách, nhật ký cấp phát dịch vụ - Đánh dấu mẫu email dịch vụ là non-marketing Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
72 lines
2.5 KiB
PHP
72 lines
2.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Api\Admin\MailCampaign\Concerns;
|
|
|
|
use App\Models\Customer;
|
|
use App\Models\MailCampaign;
|
|
use App\Models\Service;
|
|
use App\Support\RenewalCampaign;
|
|
use App\Support\RenewalQuote;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
trait HandlesRenewalCampaigns
|
|
{
|
|
public function renewalServices(Request $request): JsonResponse
|
|
{
|
|
$data = $request->validate([
|
|
'uuids' => 'required|array|min:1|max:200',
|
|
'uuids.*' => 'string|exists:customers,uuid',
|
|
'days' => 'nullable|integer|min:1|max:365',
|
|
]);
|
|
|
|
$customerIds = Customer::whereIn('uuid', $data['uuids'])->pluck('id')->all();
|
|
$today = now()->startOfDay();
|
|
|
|
$rows = RenewalQuote::dueServices($customerIds, (int) ($data['days'] ?? 30))
|
|
->map(function (Service $service) use ($today) {
|
|
$quote = RenewalQuote::forService($service);
|
|
|
|
return $quote ? [
|
|
...$quote,
|
|
'customer_uuid' => $service->customer->uuid,
|
|
'customer_name' => $service->customer->fullname,
|
|
'customer_email' => $service->customer->email,
|
|
'days_left' => (int) $today->diffInDays($service->expires_at->copy()->startOfDay(), false),
|
|
] : null;
|
|
})
|
|
->filter()
|
|
->values();
|
|
|
|
return response()->json(['error' => false, 'data' => $rows]);
|
|
}
|
|
|
|
/**
|
|
* @param array<int, array{service_id: int, months: int}> $selected
|
|
* @return array<int, array{customer_id: int, email: string, service_id: int}>
|
|
*/
|
|
private function renewalJobs(MailCampaign $campaign, array $selected): array
|
|
{
|
|
if (! RenewalCampaign::isRenewalTemplate($campaign)) {
|
|
throw ValidationException::withMessages(['renewal_services' => 'Template đã chọn không phải mẫu nhắc gia hạn.']);
|
|
}
|
|
|
|
$services = Service::with('customer:id,email')
|
|
->whereIn('id', array_column($selected, 'service_id'))
|
|
->get();
|
|
|
|
return $services
|
|
->filter(fn (Service $service) => $service->customer && trim((string) $service->customer->email) !== '')
|
|
->map(fn (Service $service) => [
|
|
'customer_id' => $service->customer->id,
|
|
'email' => trim($service->customer->email),
|
|
'service_id' => $service->id,
|
|
])
|
|
->values()
|
|
->all();
|
|
}
|
|
}
|