feat: nhắc gia hạn QR theo dịch vụ, failover server hosting, CCCD admin, log cấp phát dịch vụ
- 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>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
047c23beff
commit
55a834a2f8
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\Http\Controllers\Api\Admin\MailCampaign;
|
||||
|
||||
use App\Http\Controllers\Api\Admin\MailCampaign\Concerns\HandlesCampaignBulkActions;
|
||||
use App\Http\Controllers\Api\Admin\MailCampaign\Concerns\HandlesRenewalCampaigns;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Jobs\Mail\SendMailCampaignRecipient;
|
||||
use App\Models\Customer;
|
||||
@@ -16,6 +17,7 @@ use App\Support\AutoEmailGate;
|
||||
use App\Support\MailAttachments;
|
||||
use App\Support\MailPlaceholders;
|
||||
use App\Support\MailSettings;
|
||||
use App\Support\RenewalCampaign;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -28,6 +30,7 @@ use Illuminate\Validation\ValidationException;
|
||||
final class MailCampaignController extends Controller
|
||||
{
|
||||
use HandlesCampaignBulkActions;
|
||||
use HandlesRenewalCampaigns;
|
||||
|
||||
private const MAX_EMAILS = 1000;
|
||||
|
||||
@@ -253,6 +256,9 @@ final class MailCampaignController extends Controller
|
||||
'emails' => 'nullable|array|max:' . self::MAX_EMAILS,
|
||||
'emails.*' => self::EMAIL_RULE,
|
||||
'name' => 'nullable|string|max:255',
|
||||
'renewal_services' => 'nullable|array|max:500',
|
||||
'renewal_services.*.service_id' => 'required|integer|exists:services,id',
|
||||
'renewal_services.*.months' => 'required|integer|min:1|max:600',
|
||||
'cc' => 'nullable|string|max:1000',
|
||||
'bcc' => 'nullable|string|max:1000',
|
||||
...MailAttachments::rules(),
|
||||
@@ -263,12 +269,25 @@ final class MailCampaignController extends Controller
|
||||
|
||||
$campaign = $this->draftCampaign($data);
|
||||
|
||||
$marketingOnly = $campaign->isMarketing();
|
||||
$recipients = $data['recipient_type'] === 'all'
|
||||
? $this->allCustomerRecipients($marketingOnly)
|
||||
: $this->selectedRecipients($data['uuids'] ?? [], $data['emails'] ?? [], $marketingOnly);
|
||||
$optedOut = $recipients['opted_out'];
|
||||
$recipients = $recipients['recipients'];
|
||||
$renewalJobs = [];
|
||||
$optedOut = 0;
|
||||
if (!empty($data['renewal_services'])) {
|
||||
$renewalJobs = $this->renewalJobs($campaign, $data['renewal_services']);
|
||||
$campaign->renewal_services = array_values(array_filter(
|
||||
$data['renewal_services'],
|
||||
fn (array $item) => in_array((int) $item['service_id'], array_column($renewalJobs, 'service_id'), true),
|
||||
));
|
||||
$campaign->variables = RenewalCampaign::withoutServiceValues($campaign->variables);
|
||||
$data['recipient_type'] = 'selected';
|
||||
$recipients = $renewalJobs;
|
||||
} else {
|
||||
$marketingOnly = $campaign->isMarketing();
|
||||
$resolved = $data['recipient_type'] === 'all'
|
||||
? $this->allCustomerRecipients($marketingOnly)
|
||||
: $this->selectedRecipients($data['uuids'] ?? [], $data['emails'] ?? [], $marketingOnly);
|
||||
$optedOut = $resolved['opted_out'];
|
||||
$recipients = $resolved['recipients'];
|
||||
}
|
||||
|
||||
if ($recipients === []) {
|
||||
return response()->json([
|
||||
@@ -299,8 +318,14 @@ final class MailCampaignController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($recipients as $email => $customerId) {
|
||||
SendMailCampaignRecipient::dispatch($campaign->id, $customerId, $email);
|
||||
if ($renewalJobs !== []) {
|
||||
foreach ($renewalJobs as $job) {
|
||||
SendMailCampaignRecipient::dispatch($campaign->id, $job['customer_id'], $job['email'], $job['service_id']);
|
||||
}
|
||||
} else {
|
||||
foreach ($recipients as $email => $customerId) {
|
||||
SendMailCampaignRecipient::dispatch($campaign->id, $customerId, $email);
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
|
||||
Reference in New Issue
Block a user