Commit Graph

221 Commits

Author SHA1 Message Date
root fbfcb71d61 fix: driver delivery UX — remove Загружено status, fix checkbox reset, fix confirmed label
1. Remove "Загружено" status from driver workflow — driver goes directly
   Назначен водитель → Доставлено (or Проблема)
2. Driver can undo "Доставлено" → "Вернуть в работу" (back to Назначен водитель)
3. Fix checkbox reset: shippedItems only resets when order ID changes,
   not on every order data refetch — driver can toggle items freely
4. Fix "confirmed" showing in SMS status card — add Russian label
5. onResetStatus resets to driver_assigned, not loaded
6. ShipmentPanel "Сбросить" works for all active statuses
2026-07-13 11:51:56 +00:00
root 1766ccb897 fix: driver planner uses fs-zone-table not fs-zone-card
User changes "Таблицы" slider in Settings → expects table text to scale.
DriverDeliveryPlanner was wrapped in fs-zone-card (responds to "Карточки"),
not fs-zone-table (responds to "Таблицы").
2026-07-13 11:35:52 +00:00
root edb6784c16 fix: remove duplicate fmtTime declaration in OrderDetailPanel 2026-07-13 11:26:31 +00:00
root 0821bcc747 merge: dev → main — driver table layout, filters, status reset, SMS campaigns, font zones
Merges dev branch into main:
- Driver delivery list: table layout (№, Client, Phone, City, Half-day)
- Driver filters: search, half-day filter, problem sorting
- DriverShipmentPanel: reset status with confirmation
- SmsCampaignPanel: campaigns refactor
- LogisticsReadinessBoard: unified table view
- Font zone classes (fs-zone-card) on all driver components
- SMS campaign scripts updates
2026-07-13 11:24:56 +00:00
root 6c7d83c2be fix: add fs-zone-card to driver components so font size settings apply
Driver components (DriverDeliveryPlanner, DriverShipmentPanel,
DriverDeliveryDetail) were missing fs-zone-card class wrappers.
Font size settings from SettingsPage saved to localStorage correctly
but never applied to driver UI because fontSettings.css only
overrides Tailwind text-* classes inside .fs-zone-* wrappers.
2026-07-13 06:58:49 +00:00
root 112147cb0a fix: driver delivery list — table layout with columns: № | Client | Phone | City | Half-day
Replaced card-style delivery items with proper table:
- № счёта (order numbers, accent color)
- Клиент (customer name)
- Телефон (tel: link, clickable)
- Город (extracted from address)
- Часть дня (delivery half-day)
Problem rows highlighted with red tint + ⚠ icon
2026-07-10 15:15:16 +00:00
root ced5958eac feat: driver filters + status fixes + logistics problem indicator
DriverDeliveryPlanner:
- Text search (name, address, phone, order numbers)
- Half-day filter (morning/afternoon/unknown)
- 'Reset all filters' button
- tel: link on phone in delivery cards
- Order numbers badges in cards
- Partial delivery warning badge
- Problems-first sorting

saveShipmentData fix:
- Partial shipment with problems → status 'problem' (not 'delivered')
- Full shipment → 'delivered' (unchanged)

DriverShipmentPanel:
- Reset button: confirmation dialog when status is final
- Calls onResetStatus to revert delivery status to 'loaded'

OrderDetailPanel (driver status section):
- 'Return to work' button for delivered/problem/picked_up statuses
- Passes onResetStatus + isSavingStatusChange to DriverShipmentPanel

LogisticsReadinessBoard:
- Warning badge for has_delivery_problem groups in table rows
- Shows delivery_problem_note as tooltip
2026-07-10 14:50:15 +00:00
root e7365b6c0c fix(analytics): remove 1С import category, bypassed_completed covers all no-date completions 2026-07-06 15:00:41 +00:00
root 14a3006918 fix(analytics): funnel shows real order path with bypass detection 2026-07-06 13:47:02 +00:00
root a695a73af7 fix(analytics): rewrite funnel as real order path
- SQL admin_automation_economics: new columns based on actual order lifecycle
  - sms_sent: got at least 1 SMS
  - completed_auto: delivered/picked_up without manual_confirmation_at
  - completed_manual: delivered/picked_up with manual_confirmation_at
  - stuck_in_manual: manual_required + still waiting
  - no_sms_completed: imported as already delivered
- Funnel steps: Всего → SMS → Авто-завершено → Завершено вручную → Застряло → Без SMS → Хранение → Отменено
- Footer: Автоматизация % / Ручное вмешательство % / Завершено всего
- Fixes: old funnel counted manual_confirmation_required as "согласовано"
  and missed 31 completed orders (notification_status=completed vs confirmed)
2026-07-06 13:16:44 +00:00
root b0bc056090 fix(analytics): separate Вывезено (status) from Самовывоз (type) in KPI
- KPI: Вывезено = picked_up (all types), Самовывоз = pickup type only
- SQL admin_delivery_stats: + picked_up_delivery, picked_up_pickup columns
- Fixes confusion: 17 picked_up vs 5 pickup type were different metrics
2026-07-06 10:20:55 +00:00
root eba1769078 redesign(analytics): dashboard desktop layout + pickup period label
- 12-col responsive grid: pie 4/8 trend, table 4/8 drivers
- KPI cards: 7 metrics with uppercase labels, larger values
- Period label in every section subtitle (за 7 дней, etc)
- PickupStatsPanel: period label, status breakdown (завершено/ожидает/ручное)
- PickupStatsPanel: hide empty schedule bars when no planned pickups
- SQL admin_pickup_stats: + picked_up, pending, manual columns
- Colors: delivered #22c55e, picked_up #14b8a6 (distinct)
- Desktop: 3-col grid inside pickup panel
2026-07-06 10:09:11 +00:00
root 1b9fea7f1d fix(analytics): picked_up as separate status in dashboard
- KPI: separate Доставлено and Вывезено cards
- Trend: separate line for Вывезено (#14b8a6)
- Driver chart: separate bar for Вывезено
- SQL: admin_delivery_stats returns picked_up column
- SQL: admin_daily_trend returns picked_up column
- SQL: admin_driver_stats returns picked_up column
- delivery_rate = (delivered + picked_up) / total
- Colors: delivered #22c55e, picked_up #14b8a6 (distinct)
2026-07-06 06:42:31 +00:00
root 6786779f2c fix(analytics): recognize picked_up status in dashboard and stats
- Add picked_up to STATUS_COLORS and STATUS_LABELS in AdminDashboard
- SQL: admin_delivery_stats counts picked_up as delivered
- SQL: admin_daily_trend counts picked_up as delivered
- SQL: admin_driver_stats counts picked_up as delivered
- Fixes: picked_up showed as Unknown, delivered count was 17 short
2026-07-06 06:17:32 +00:00
root eabf30bceb fix: stop SMS UI for terminal delivery statuses (picked_up/delivered/cancelled)
- SmsStatusCard: show "SMS не отправляется" when delivery is terminal, hide countdown + restart buttons
- SmsCampaignPanel fmtAgreement: check terminal status FIRST → " Самовывоз завершён" instead of "Самовывоз (неполно)"
- update_delivery_status RPC: reset notification_status→completed on terminal transition
- Add completed to notification_status check constraint
- SW v60→v61
2026-07-04 11:27:03 +00:00
root 43d9116c51 fix: restore localStorage filter persistence in LogisticsReadinessBoard, SW v60 2026-07-03 15:04:05 +00:00
root 468c3c4097 fix: sessionStorage→localStorage for filter persistence, SW v59 2026-07-03 14:14:00 +00:00
root 1d288279c0 fix: extractCity word boundary + filter persistence in sessionStorage 2026-07-03 14:07:13 +00:00
root 8ade6a6ff3 fix: fallback fresh slots when all availableSlots passed + SW v57 2026-07-03 13:37:42 +00:00
root a74a5242b8 fix: use current date for slot availability + SW v56 2026-07-03 13:32:24 +00:00
root e93215f837 feat: SMS filter no_sms in queue + SW v55 2026-07-03 13:26:13 +00:00
root 6a34f36621 SW v54 — business schedule 2026-07-03 12:45:26 +00:00
root d397d0cb24 feat: configurable business schedule (delivery/pickup/SMS days)
- New table business_schedule_settings (delivery_days, pickup_days, sms_days)
- RPC get_business_schedule() (public) + update_business_schedule() (admin)
- Admin UI: BusinessSchedulePanel with day pills for each category
- ClientDeliveryPage: fetches schedule, replaces hardcoded Sunday/weekend checks
- PickupSlotsPicker: uses pickupDays prop instead of hardcoded isWeekend
- Edge function confirm-delivery-choice: reads delivery_days from DB
- delivery-invitations.ts: buildDefaultDatedAvailableSlots reads delivery_days
- RPC confirm_delivery_choice_by_token: checks delivery_days instead of extract(dow)=0
- SMS scripts: get_sms_days() reads sms_days from business_schedule_settings
  and overrides per-campaign work_days setting
- Nav item Расписание for mega_admin and admin roles
- Default: Mon-Fri (1,2,3,4,5) for all three categories
2026-07-03 12:45:02 +00:00
root d4d85bc767 fix: normalize_phone handles +7, 8, text, and multi-number fields
- Two numbers in one field (XXX / YYY) → take first 10 digits
- Text in field (Екатерина +7978...) → extract digits only
- 8 prefix → 7 (Russian landline style)
- 10 digits (no country code) → prepend 7
- All 4 SMS scripts patched (first, second, paid_storage)
2026-07-03 12:33:53 +00:00
root e55a4cafcc fix: manual_campaign EXISTS check — no manual_required without SMS sent
Scenario 3 (link_ready + next_check expired) now requires EXISTS
in sms_campaign_log. Prevents groups from being moved to
manual_required before first SMS is ever sent.
2026-07-03 12:18:28 +00:00
root c1e5f109be docs: SMS campaigns architecture + font settings + stale highlight 2026-07-02 14:37:58 +00:00
root 20873bdc5f fix: font zones + stale highlight + fmtTime + SW v49
- FontSettingsContext: body zone first in CSS (specific zones win)
- Arbitrary px sizes (10-14px) overrides in table/card zones
- fs-zone-table on OrdersTable + LogisticsReadinessBoard
- fs-zone-body/heading/nav in AppShell + const navigate = useNavigate()
- Stale delivery highlight: isStale() 24h + bg tint, isLinkOpened 👁
- fmtTime defined in OrderDetailPanel (was used but never declared)
- SmsStatusCard synced from prod
- SW v49 (fixed: addEventListener was broken by sed)
2026-07-02 14:25:40 +00:00
root f69a52779f fix: font zone classes on tables + body/heading/nav zones in AppShell
- fs-zone-table on OrdersTable + LogisticsReadinessBoard (was missing)
- fs-zone-body on main content area
- fs-zone-heading on mobile + desktop headers
- fs-zone-nav on mobile tab nav
- CSS: added arbitrary px size overrides (10px/11px/12px/13px/14px)
- CSS: reordered body zone last so table/card/nav/heading win at equal specificity
2026-07-02 13:19:10 +00:00
root db57624626 merge: resolve conflicts (our SmsCampaignPanel + SW v43) 2026-07-01 16:20:12 +00:00
root b78bdc48bb feat: drag-n-drop status sections + localStorage filters/collapsed + pickup date in logistics board
- Drag-n-drop reordering of status sections (desktop + touch)
- Section order saved in localStorage (logistics-section-order)
- Collapsed/expanded state saved in localStorage (logistics-collapsed)
- Filters (city, status, search) saved in localStorage (logistics-filters)
- Pickup date shown in delivery date column for self-pickup orders
- SMS campaign scripts (manual, second, paid_storage, timer manager)
- SmsCampaignStats + SmsStatusCard components
- DashboardPage: unified LogisticsReadinessBoard for all roles
- OrdersTable cleanup, StatusActionPanel updates
- SW v42
2026-07-01 16:16:22 +00:00
root 5e02f61567 feat: manual campaign tab shows order_groups instead of empty sms_campaign_log
- Manual campaign doesn't write to sms_campaign_log, so the tab was always empty
- Now loads order_groups with notification_status='manual_required'
- Shows: customer name, phone, first/second SMS timestamps, last update
- Red 'не отправлена' badge for groups where second SMS was never sent
- Also shows manual count on the campaign card
2026-06-30 15:48:52 +00:00
root 94f534ded3 fix: manual campaign no longer moves first_sms_sent groups to manual before second SMS is sent
Bug: sms_manual_campaign.py condition 2 caught first_sms_sent groups after 3h
WITHOUT checking if second SMS was already sent. This caused manual campaign
(5min timer) to move groups to manual_required before second campaign (10min timer)
could send the second SMS.

Fix: added second_sms_sent_at IS NOT NULL check to condition 2.
Now manual only moves groups where second SMS was already sent AND client
still didn't agree after 3 more hours.

Also restored 17 groups that were incorrectly moved to manual_required back
to first_sms_sent so second campaign can send their second SMS.
2026-06-30 15:27:56 +00:00
root 55d42bfdc8 feat: persist collapsed sections in localStorage
- Collapsed/expanded state survives page refresh
- Key: logistics-section-collapsed
- Each toggle saves to localStorage immediately
2026-06-30 13:12:50 +00:00
root 70ec6ec7a8 feat: unified LogisticsReadinessBoard for all roles — single table view
- Removed OrdersTable from dashboard, all roles now use LogisticsReadinessBoard
- Logistician, admin, mega_admin, manager — same grouped board with drag-and-drop
- Driver still uses DriverDeliveryPlanner (card view)
- Bundle size reduced (OrdersTable no longer imported)
2026-06-30 12:44:40 +00:00
root 5c957c3c05 fix: make drag handle more visible in LogisticsReadinessBoard 2026-06-30 12:39:10 +00:00
root 23c0ed78ef feat: drag-and-drop section ordering in LogisticsReadinessBoard + unified table visuals
- LogisticsReadinessBoard: @dnd-kit/sortable for drag-and-drop section reordering
  - Drag handle (6-dot grip icon) on left of each section header
  - Custom order persists in localStorage (key: logistics-section-order)
  - Default: agreed → manual_required → funnel order
  - Flat rows (no Button/rounded), matches OrdersTable style
  - 7 columns: Клиент | Город | Тип | Дата | Водитель | Статус | Обновлён
  - Horizontal scroll: overflow-x-auto + min-w-[1080px]
  - Type column wide enough for Самовывоз/Доставка in one line

- OrdersTable: widened Type column (minmax 70px→100px), min-w 920→1080px
  for consistent horizontal scroll across tables
2026-06-30 12:21:54 +00:00
root 581239cc73 fix: unify table styles — no rounded rows, wider type col, horizontal scroll, pagination by filtered groups 2026-06-30 11:43:15 +00:00
root c0c549adca feat: show delivery type (pickup/delivery) in logistics board + driver planner 2026-06-30 09:04:27 +00:00
root 858d36e5b0 feat: manual SMS campaign shows groups in manual mode + pagination on all delivery pages 2026-06-30 07:30:12 +00:00
root 93d3ce4ca8 fix: manage-users — remove manual public.users insert, trigger handle_new_user does it via user_metadata 2026-06-30 07:04:24 +00:00
root cadcceef7e feat: manage-users edge function — admin user CRUD (create/delete) 2026-06-30 06:55:55 +00:00
root d2ac10d849 feat: SMS campaign sub-tabs + recheck button + dual send protection
- SmsCampaignPanel: 4 sub-tabs (first_sms/second_sms/manual/paid_storage)
- 'Проверить снова' button sets needs_check=true in sms_campaign_log
- Auto-refresh every 30s with toggle
- Elapsed time display per row
- Script: after send, notification_status='sms_sending' (not 'link_ready')
  → double protection against re-sending to same group
- Script: get_sms_to_check includes needs_check=true records regardless of age
- Script: checked_at timestamp on each status check
- DB: needs_check boolean + checked_at timestamptz columns added
2026-06-23 10:35:52 +00:00
root 4215001ab7 feat: test_mode toggle in admin + cache bump v10
- test_mode + test_phone columns in sms_campaign_settings (DB)
- Script reads test_mode from DB settings, not env vars
- Admin panel: toggle Test/Production mode with visual indicator
- test_mode=true (default): SMS only to test_phone
- test_mode=false: SMS to real customers
- Service worker cache v9 → v10 (fixes white screen)
2026-06-23 08:58:59 +00:00
root f264a53c0a feat: SmsCampaignPanel — SMS log + settings in mega_admin dashboard
- sms_campaign_log table: full audit trail (phone, sms_id, status, code, attempts)
- sms_campaign_settings: editable by megaadmin (wait times, max attempts, delays)
- New tab 'SMS-кампании' in mega_admin navigation
- State machine: no blocking sleeps, fast cron runs
- Protection: no duplicate SMS within 24h, code 231/132 = limit, not retry
2026-06-23 08:39:24 +00:00
root 174c74ec0b fix: DB host 10.0.4.5 (Docker internal IP) 2026-06-23 08:21:57 +00:00
root 05d4d86d37 feat: Python script replacing n8n first SMS campaign
- sms_first_campaign.py: full replacement for n8n workflow JnfZwOnpjEazseW5
- sms_campaign_log table: full audit trail in Supabase (visible in admin)
- sms_campaign_settings table: configurable by megaadmin (wait times, attempts, schedule)
- systemd service + timer (NOT activated, ready for deployment)
- Logic: send SMS → wait 25s → check status (102=in transit, 103=delivered)
  → retry check up to 90 min → retry SMS send up to 2 attempts → manual_required
- Telegram notifications after each send/delivery/failure
- Log file: /var/log/supersam-sms-first.log
2026-06-23 08:20:42 +00:00
root f792ea6fb9 fix: table fonts 12px (text-xs), compact padding py-1.5 2026-06-23 08:01:49 +00:00
root b0370ed03e fix: handle status=first_sms_sent when notification_status=link_ready
n8n workflow writes status='first_sms_sent' but leaves notification_status='link_ready'.
Added first_sms_sent/second_sms_sent to ORDER_GROUP_STATUS_LABELS and tone logic.
2026-06-23 07:53:01 +00:00
root a55e5857f8 fix: add SMS notification statuses to filter options, increase Badge font size
- Add first_sms_sent, second_sms_sent, send_failed, link_ready, ready_to_launch
  to ORDER_GROUP_DISPLAY_STATUS_OPTIONS (were missing from filter dropdown)
- Badge: text-xs (12px) → text-sm (14px), font-semibold → font-medium,
  px-3 py-1 → px-2.5 py-0.5 (matches table text size, less padding)
2026-06-23 07:38:54 +00:00
root bbe578eb3a fix: parseGroupDate now handles DD.MM.YYYY (4-digit year) format
customer_date in DB is stored as 23.06.2026 (DD.MM.YYYY) but parseGroupDate
only matched DD.MM.YY (2-digit year). This caused date filter to reject all
groups when filtering by date range, since parseGroupDate returned null
for 4-digit year dates.
2026-06-23 07:22:09 +00:00