feat(129): order user notes module
CRUD notatek autorskich operatora per zamowienie z badge [N] na liscie
zamowien. Reuse istniejacej tabeli `order_notes` przez nowy
`note_type='user'` z `user_id` (FK->users SET NULL) i `author_name`
(snapshot). Sekcja `#notes` w "Wiadomosci i zalaczniki" w
`/orders/{id}` z inline edit form + delete przez
`OrderProAlerts.confirm`. Autoryzacja DB-level
(`WHERE user_id = :user_id`, rowCount=0 ⇒ 403) — bez admin override
(brak systemu rol w aplikacji).
- Migracja `20260514_000116_*.sql` (ADD COLUMN user_id + author_name +
FK + indeks `idx_order_notes_type_order`); idempotentne z DDL
no-op fallback.
- `OrderNotesService` (CRUD + walidacja body ≤ 2000 znakow); subquery
`user_notes_count` w paginate; badge HTML w `toTableRow()`.
- 3 routy POST /orders/{id}/notes(/update|/delete).
- SCSS module `_order-notes.scss` + vanilla JS `order-notes.js`
(inline edit toggle + delete confirm; idempotent guard).
- 9 kluczy i18n PL; PROJECT.md + ROADMAP.md + tech_changelog.md +
db_schema.md zaktualizowane.
Follow-up: `php bin/migrate.php` + manualny smoke test (autor vs inny
user + badge na /orders/list).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ use App\Modules\Cron\CronHandlerFactory;
|
||||
use App\Modules\Cron\CronRepository;
|
||||
use App\Modules\Orders\OrdersController;
|
||||
use App\Modules\Orders\OrderImportRepository;
|
||||
use App\Modules\Orders\OrderNotesService;
|
||||
use App\Modules\Orders\OrdersRepository;
|
||||
use App\Modules\Statistics\OrdersStatisticsController;
|
||||
use App\Modules\Statistics\OrdersStatisticsRepository;
|
||||
@@ -414,7 +415,8 @@ 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, $smsTemplateRepository, $smsVariableResolver, $companySettingsRepository);
|
||||
$orderNotesService = new OrderNotesService($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, $smsTemplateRepository, $smsVariableResolver, $companySettingsRepository, $orderNotesService);
|
||||
$ordersStatisticsController = new OrdersStatisticsController(
|
||||
$template,
|
||||
$translator,
|
||||
@@ -595,6 +597,9 @@ return static function (Application $app): void {
|
||||
$router->post('/orders/{id}/email-preview', [$ordersController, 'emailPreview'], [$authMiddleware]);
|
||||
$router->get('/api/orders/search', [$ordersController, 'quickSearch'], [$authMiddleware]);
|
||||
$router->get('/api/orders/{id}/preview', [$ordersController, 'preview'], [$authMiddleware]);
|
||||
$router->post('/orders/{id}/notes', [$ordersController, 'storeNote'], [$authMiddleware]);
|
||||
$router->post('/orders/{id}/notes/{noteId}/update', [$ordersController, 'updateNote'], [$authMiddleware]);
|
||||
$router->post('/orders/{id}/notes/{noteId}/delete', [$ordersController, 'deleteNote'], [$authMiddleware]);
|
||||
$router->post('/users', [$usersController, 'store'], [$authMiddleware]);
|
||||
$router->get('/settings/users', [$usersController, 'index'], [$authMiddleware]);
|
||||
$router->post('/settings/users', [$usersController, 'store'], [$authMiddleware]);
|
||||
|
||||
Reference in New Issue
Block a user