feat(124): sms templates CRUD + order picker

- Nowa tabela sms_templates (name + body + is_active) + minimalny CRUD.
- /settings/sms-templates: lista + formularz z paleta zmiennych (pill chips).
- Wydzielono Sms\SmsVariableResolver ze wspolna logika placeholderow;
  Email\VariableResolver staje sie cienka fasada — EmailSendingService bez zmian.
- Dropdown "Wybierz szablon" w zakladce SMS na /orders/{id} z fetch
  GET /orders/{id}/sms/template + OrderProAlerts.confirm przy nadpisaniu.
- Stopka SMSPLANET dalej doklejana wylacznie przez SmsConversationService
  (Phase 122 contract preserved).
- Sidebar Ustawien: nowy link "Szablony SMS".

Migration: 20260512_000112_create_sms_templates.sql (CREATE TABLE).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-12 21:37:51 +02:00
parent 0227f2d072
commit 522c94a434
25 changed files with 1641 additions and 105 deletions

View File

@@ -56,6 +56,7 @@ use App\Modules\Settings\EmailMailboxController;
use App\Modules\Settings\EmailMailboxRepository;
use App\Modules\Settings\EmailTemplateController;
use App\Modules\Settings\EmailTemplateRepository;
use App\Modules\Settings\SmsTemplateController;
use App\Modules\Settings\IntegrationSecretCipher;
use App\Modules\Email\AttachmentGenerator;
use App\Modules\Email\EmailSendingService;
@@ -100,6 +101,8 @@ use App\Modules\Notifications\NotificationController;
use App\Modules\Notifications\NotificationRepository;
use App\Modules\Sms\SmsConversationService;
use App\Modules\Sms\SmsMessageRepository;
use App\Modules\Sms\SmsTemplateRepository;
use App\Modules\Sms\SmsVariableResolver;
use App\Modules\Sms\SmsplanetWebhookController;
use App\Modules\Users\UsersController;
@@ -315,6 +318,13 @@ return static function (Application $app): void {
$emailTemplateRepository,
$emailMailboxRepository
);
$smsTemplateRepository = new SmsTemplateRepository($app->db());
$smsTemplateController = new SmsTemplateController(
$template,
$translator,
$auth,
$smsTemplateRepository
);
$automationRepository = new AutomationRepository($app->db());
$automationExecutionLogRepository = new AutomationExecutionLogRepository($app->db());
$automationController = new AutomationController(
@@ -325,7 +335,8 @@ return static function (Application $app): void {
$automationExecutionLogRepository,
$receiptConfigRepository
);
$variableResolver = new VariableResolver($shipmentPackageRepositoryForOrders);
$smsVariableResolver = new SmsVariableResolver($shipmentPackageRepositoryForOrders);
$variableResolver = new VariableResolver($shipmentPackageRepositoryForOrders, $smsVariableResolver);
$attachmentGenerator = new AttachmentGenerator($receiptRepository, $receiptConfigRepository, $template);
$emailSendingService = new EmailSendingService(
$app->db(),
@@ -386,7 +397,7 @@ return static function (Application $app): void {
$allegroDeliveryMappingController
);
$printJobRepository = new PrintJobRepository($app->db());
$ordersController = new OrdersController($template, $translator, $auth, $app->orders(), $shipmentPackageRepositoryForOrders, $receiptRepository, $receiptConfigRepository, $emailSendingService, $emailTemplateRepository, $emailMailboxRepository, $app->basePath('storage'), $printJobRepository, $shopproIntegrationsRepository, $automationService, $invoiceRepository, $invoiceConfigRepository, $smsMessageRepository, $smsConversationService);
$ordersController = new OrdersController($template, $translator, $auth, $app->orders(), $shipmentPackageRepositoryForOrders, $receiptRepository, $receiptConfigRepository, $emailSendingService, $emailTemplateRepository, $emailMailboxRepository, $app->basePath('storage'), $printJobRepository, $shopproIntegrationsRepository, $automationService, $invoiceRepository, $invoiceConfigRepository, $smsMessageRepository, $smsConversationService, $smsTemplateRepository, $smsVariableResolver, $companySettingsRepository);
$ordersStatisticsController = new OrdersStatisticsController(
$template,
$translator,
@@ -554,6 +565,7 @@ return static function (Application $app): void {
$router->post('/orders/{id}/status', [$ordersController, 'updateStatus'], [$authMiddleware]);
$router->post('/orders/{id}/details/update', [$ordersController, 'updateDetails'], [$authMiddleware]);
$router->post('/orders/{id}/sms/send', [$ordersController, 'sendSms'], [$authMiddleware]);
$router->get('/orders/{id}/sms/template', [$ordersController, 'smsTemplate'], [$authMiddleware]);
$router->post('/orders/{id}/send-email', [$ordersController, 'sendEmail'], [$authMiddleware]);
$router->post('/orders/{id}/email-preview', [$ordersController, 'emailPreview'], [$authMiddleware]);
$router->get('/api/orders/search', [$ordersController, 'quickSearch'], [$authMiddleware]);
@@ -645,6 +657,13 @@ return static function (Application $app): void {
$router->post('/settings/email-templates/toggle', [$emailTemplateController, 'toggleStatus'], [$authMiddleware]);
$router->post('/settings/email-templates/preview', [$emailTemplateController, 'preview'], [$authMiddleware]);
$router->get('/settings/email-templates/variables', [$emailTemplateController, 'getVariables'], [$authMiddleware]);
$router->get('/settings/sms-templates', [$smsTemplateController, 'index'], [$authMiddleware]);
$router->get('/settings/sms-templates/create', [$smsTemplateController, 'create'], [$authMiddleware]);
$router->get('/settings/sms-templates/edit', [$smsTemplateController, 'edit'], [$authMiddleware]);
$router->post('/settings/sms-templates/save', [$smsTemplateController, 'save'], [$authMiddleware]);
$router->post('/settings/sms-templates/delete', [$smsTemplateController, 'delete'], [$authMiddleware]);
$router->post('/settings/sms-templates/toggle', [$smsTemplateController, 'toggleStatus'], [$authMiddleware]);
$router->get('/settings/sms-templates/variables', [$smsTemplateController, 'getVariables'], [$authMiddleware]);
$router->get('/settings/automation', [$automationController, 'index'], [$authMiddleware]);
$router->get('/settings/automation/create', [$automationController, 'create'], [$authMiddleware]);
$router->post('/settings/automation/store', [$automationController, 'store'], [$authMiddleware]);