Sub-market workbook import as a backend module tab

- Extract the complete import logic (label-scan reading, page
  find-or-create, slot filling, content-idempotent image attach) from
  ImportSubmarketWorkbooksCommand into the shared service
  SubmarketWorkbookImporter; the CLI command and the new controller are
  thin shells around importFile(), so both entry points cannot drift.
  CLI regression verified: identical dry-run report for the reference
  workbook (12 elements, page 443)
- New "Sub-Markets" tab in the VITEC Import module
  (SubmarketImportController + Import/Submarkets.html): upload multiple
  filled workbooks into the SAME inbox the CLI uses
  (migrations/submarkets_xlsx_in/), per-file checkboxes, dry-run and
  apply buttons, result cards with the familiar report and a direct
  link into the page module; backend dry-run verified against the CLI
- Submitted filenames are whitelisted against the actual directory
  listing (no path traversal); uploads restricted to sanitized .xlsx
  basenames
- Routes submarkets/submarket_upload/submarket_process in Modules.php,
  Sub-Markets tab link in the sibling module views, ok/danger badge
  colors in backend-import.css
- Docs section 5y (incl. operations note: apply in small batches in the
  module, mass runs via CLI - image downloads run inside the web
  request)
This commit is contained in:
orasche committed 2026-10-05 15:35:40 +02:00
1 parent d496877a53
commit 3d5459b8d2
9 files changed
+980 -585

No files matched your search

@@ -26,6 +26,9 @@
<li class="nav-item">
<a class="nav-link" href="{f:be.uri(route: 'web_vitecimport.products')}">Products</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{f:be.uri(route: 'web_vitecimport.submarkets')}">Sub-Markets</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{f:be.uri(route: 'web_vitecimport.seo')}">SEO Research</a>
</li>