Appearance
Stores menu: interface-to-workflow map
The Stores menu combines three kinds of work: shared sales queues filtered by store or source, provider-specific sales state pages, and supplier/carrier operations such as imports, shipment exceptions, and stock reports. The menu is assembled in src/AppBundle/Menu/Builder.php; a menu leaf's route and parameters determine which controller and data flow the page uses.
Evidence boundary
This page is checked against the pinned axelites/logidav source revision in source_refs. It describes static source behavior, not a live user's visible menu, current provider data, or production status. The shared Twig templates and web/assets/scripts/sales.js handlers were inspected together; no PHP/Symfony runtime, browser, or external system was used.
View diagram source
flowchart LR
M[Stores menu leaf] --> P[GET page route and parameters]
P --> V[Controller renders provider or shared Twig view]
V --> D[DataTables request: columns, order, start, length]
D --> R[Controller and repository query local sales or products]
R --> J[JSON rows or CSV/XLS export]
V --> A[Separate form or row action]
A --> L[Local sale, stock, label, or import record]
A --> C[Provider or carrier connector when that action calls one]
Menu visibility and controller access
Builder::checkMenuPermission() hides menu nodes using the user's saved menuAccess names; administrators bypass that filter. Controller methods that call mz.menu_provider->hasAccess() then check a menu name separately when the route is requested. A hidden menu item is therefore not proof that its URL or data callback is denied. Some list page handlers check access while their pagination callbacks do not repeat the same check in that method; this page is not a complete review of the application's global route firewall.
The saleShowAccess extra in Builder.php is used by Builder::hasAccessToSaleShow() to scope access to a sale detail using a sale attribute such as source or storeId. It is not a menu-visibility rule. The Portugal node passes storeId = 29 for that detail-scope hint even though its list links pass storeId = 19; confirm sale-detail access for that node if it is being changed. Several supplier leaves also share the EPrice source hint while their list queries use distinct dropship:<supplier> types, so check the actual sale source and user menu grants before changing their detail access.
Shared store and source lists
These entries use the same AppBundle\Controller\Sale\SaleController routes. A source selector is sent as a query parameter; a country-store selector is the storeId route parameter.
| Menu group | Selector | Active menu leaves | Page and data path |
|---|---|---|---|
| Mosaikasa, Meuble Promo, Channable, Temu | source = the menu's source name | sale_list_processing_not_printed, sale_list_processing_not_printed_nostock, all_sale_list | Shared pages in AppBundle:Sale:processingNotPrinted.html.twig, processingNotPrintedNoStock.html.twig, and allSaleList.html.twig. |
| Italie, Allemand, Pays-Bas, Espagne, Boutique Espagne | storeId = 14, 2, 25, 29, 30 respectively | Same three routes | The route filters the shared sales view by the store ID. Spain also has shipment and complete-sales export pages described below. |
| Portugal | storeId = 19 | sale_list_processing_not_printed, all_sale_list | There is no “Hors stock” leaf for this menu node in the pinned builder. |
The three shared pages have different purposes:
| Page | Route inputs and table query | What the operator sees or does |
|---|---|---|
sale_list_processing_not_printed | Optional storeId path value or source query value. The page calls sale_list_paginate_processing_not_printed; DataTables supplies column filters, ordering, paging, and export fields. | Orders awaiting fulfillment/printing, with product availability, shipment method, and order details. When store is empty, the page renders the Actions menu (including for source-filtered lists); it contains carrier export and shipment creation, preparation sheets, stock routing, and Amazon actions. Row selection is kept in the Symfony session. Country-store pages with a non-empty store omit this Actions menu. See the request map below. |
sale_list_processing_not_printed_nostock | Optional storeId or source; the page can also pass stock0 = 1 to the same route for the stock-zero view. Its callback is sale_list_paginate_processing_not_printed_nostock, which queries the sale-product repository with store, source, stock-zero, and table filters. | Products in processing orders that need stock or availability follow-up. The template offers stock-status moves, customer-availability updates, selected-order mail actions, and stock-zero processing actions. These change sale-product state or send communication when submitted. |
all_sale_list | Optional storeId path value, type path value, and/or source query value. all_sale_list_paginate passes the filters to SaleRepository::findAllSaleListSql(). | A searchable all-orders table with links to sale details, status-edit controls, and CSV/XLS export. The unscoped global view has additional export and carrier actions; store/source views use the same table with narrower filters. |
The shared list callbacks use server-side DataTables inputs (columns, order, start, length); exports add format and allVisiblecolumns. The request map below ties the main shared-page controls to their handlers and routes. Some per-row and toolbar actions are implemented inline in the Twig page, while sales.js handles reusable row controls such as status, real-shipping-method, and non-stock edits.
Shared controls: labels, requests, and effects
| Page/control | Request or handler | What it does and what to check |
|---|---|---|
| All three lists — table | Server-side DataTables request to the page's *_paginate* route; the initial URL carries the current storeId and/or source. Table controls submit column searches, order, offset, and page size. | Reads local sales or sale-product rows. A list load does not create a shipment or update provider state. |
All three lists — Télécharger les éléments visibles | DataTables Excel/CSV buttons export the currently loaded, visible columns in the browser. | With server-side paging this is the loaded table page, not a request to export every matching row. |
All three lists — Exporter tout | POST to the matching pagination route with format=xls or format=csv, allVisiblecolumns, and DataTables columns/order. | The full-export URL/payload omits the page's storeId and source; the all-orders page also omits type, and the no-stock page omits stock0. The controller reads these filters from the request, so this code path does not carry the table's scope. Treat full exports as unfiltered until that behavior is corrected or verified at the endpoint. |
| Processing list — select orders/products | Checkbox changes POST to session_manage_session under orders_not_printed, orders_not_printed_show, and orders_not_printed_item_id. Clear selection uses session_manage_session_clear. | Selection persists across table redraws and is consumed by the Actions menu. The handlers refuse to start an action if no order is selected. |
Processing list — carrier export labels (Exporter pour GLS, SDEN, SIC Express, TDL, Calberson variants) | sale_export_csv receives selected order IDs, selected sale-product IDs, a generated token, and the data-liv action in p; the page polls the tokenized result and shows generated files/messages. | This is an export-file workflow, distinct from creating a shipment. The menu is rendered only when store is empty. |
Processing list — Créer l'expédition Chronopost, BRT Italie, GLS, TAMDIS, Amazon | POST respectively to sale_create_chronopost_expedition, sale_create_brt_expedition, sale_create_gls_expedition, sale_create_tamdis_expedition, and sale_create_amazon_expedition; payloads contain selected order and item IDs (BRT also sends a token). | Starts carrier/provider shipment operations per selected order and displays returned status/messages. Confirm a successful response and persisted label/shipment at the owning controller/provider boundary. |
Processing list — Créer l'expédition Calberson Thiais / Chaulnes / Saint-Quentin | All three POST to sale_create_calberson_expedition; warehouse is 1, 2, or 3 respectively, with order ID, selected items, and token. | The warehouse choice is the meaningful route difference; inspect the returned per-order status for errors. |
Processing list — Créer l'expédition ECO IDF / IDF ETAGE | Both POST to sale_create_idf_expedition; carrier is ecoIdf or etageIdf. | Same endpoint, distinct carrier value. |
Processing list — Créer l'expédition VIR / VIR Etage / VIR bas d'immeuble | The first two menu labels share the same data-liv value and POST to sale_create_vir_expedition with no method override. Bas d'immeuble uses the same route with real_shipping_method=VIR_BAS_IMMEUBLE. | The template does not distinguish the displayed “VIR Etage” action from ordinary VIR; do not infer an étage-specific request from its label. |
Processing list — Créer l'expédition SDEN | POST to send_products_to_sden with selected order/item IDs and a token. | This is a separate SDEN operation; its label is not the same as Exporter pour SDEN. |
Processing list — Imprimer les fiches de préparation | Downloads from sale_print_preparation with selected orders/items and the chosen grouping criterion (category or location). | Produces preparation sheets; the normal sale_print form in this Twig is under {% if false %} and is not rendered. |
Processing list — Envoyer vers non en stock / IDF / monté à l'étage / Retrait | Per selected item, POST to sale_update_product_stock (ismass=1), sale_update_product_idf, sale_update_product_up_stairs, or sale_update_product_retrait. | These are local sale-product routing/state updates, not the carrier shipment-creation routes. The result is shown in the modal; verify the row state after refresh. |
| No-stock list — Actions emails | sale_email_notif_historique loads prior email history for delay-email actions; sale_email_notif sends the selected order/item IDs, action, and optional delay/geste/bon fields. | The actual send is a POST side effect. The page clears its selection cookies after submission and displays the returned message. |
No-stock list — Envoyer vers stock 0 | After the confirmation modal, selected sale-product IDs are posted individually to stock0_add_product with executeSaleProductService=false. | The response output is shown in the modal. This action adds the selected products to the stock-zero workflow; it is different from Vers en stock, which calls sale_switch_items. |
No-stock list — Modifier la date de disponibilité client | Collects a date, then posts selected sale-product IDs and token to bulk_update_sale_product_availability. | Requires a non-empty date and the page-level CAN_UPDATE_CLIENT_AVAILABILITY grant or admin role for the menu entry. The page shows per-item progress/results. |
No-stock list — Vers en stock | Posts selected IDs to sale_switch_items; the individual confirmation button follows the returned row URL. | Moves selected sale-product items out of the no-stock queue and redraws the list. |
No-stock list in stock0 mode — print/process, remove, mark valid | The stock-zero script groups selected {saleId, sku} values and posts them to sale_print_stock0_bulk, stock0_remove_line, or stock_stock0_mark_as_valid; the single-row print control uses sale_print_stock0. | Bulk print downloads a file, moves items through the stock workflow, and marks orders printed; remove and mark-valid actions redraw the table after success. These controls have a separate route path from ordinary Vers en stock. |
Shared sales.js row control — edit sale status | .edit-sale-status builds a dropdown from salesStatusLabel; confirming POSTs {sale_id,status,comment:""} to sale_status_update, then redraws the table on success. | The server-generated edit control is present in the all-orders list except the Phalimi row, which instead exposes tracking entry. |
Shared sales.js row control — edit real shipping method | .edit-real-shipping builds a dropdown from realShipment; confirm POSTs {sale,method,new_retrait} to sale_update_real_shipment. | A successful OK response updates the displayed method. |
Shared sales.js row control — send one product to non-stock | .send-no-stock prompts for confirmation and POSTs sale_product to sale_update_product_stock. | The success/failure response is appended beside the row; the handler does not itself reload the table. |
| Processing list — scan selection | The scan dialog decodes a QR value, posts sale/product IDs to sale_qrcode_check, and uses session_manage_session to retain successful rows; a rejected scan can be rechecked through ajax_final_sale_product_ids. | This prepares selected orders for the Actions menu; scan acceptance is not itself shipment creation. |
The all-orders page's Voir toutes les commandes VidaXL toggle redraws the table with filterSales switched between 0 and 1. Phalimi's Ajouter le tracking control loads rows through show_modal_tracking_sale_product and saves entered links through set_palimi_sale_product_tracking; it replaces the normal status-edit control for that supplier type.
Spain-specific shipping
The Espagne node adds two workflows beyond the shared store lists:
| Menu leaf | Route and inputs | Result and side effects |
|---|---|---|
| Expedition | shipment_spain_list | Renders the Spanish shipment table. Its pagination query searches store IDs 29 and 30 and includes the source filter. The page uses AppBundle\Controller\Sale\ShipmentController. |
| Export des Expedition | export_complete_spanish_sales | Opens an export form with a default date range from one week before the current date through today. Submitting the date starts menzzo:sale:spanish:export-complete-sales with a user ID and token; the page polls token-backed progress. This is a command-backed export, not a list-page read. |
Provider-specific sales state pages
These menu groups have dedicated route families and provider-aware repository filters. Similar French labels do not make the routes interchangeable. List pages generally read the imported local Sale records; integrations and outbound feedback happen through the provider service or separate action/command paths.
| Provider menu | Active state routes | Scope passed to the route | Controller and notable behavior |
|---|---|---|---|
google_pending_sales, google_shipped_sales, google_all_sales | Google source is configured by mz.google.shopping; no account ID is added by the menu. | src/ErpBundle/Controller/SaleController.php; Google-specific pending, shipped, and all-sale queries. Return queues are listed separately below. | |
| Shopdeco | shop_deco_shipped_sales, shop_deco_invoiced_sales, shopdeco_pending_sales, shopdeco_sale_errors, shopdeco_all_sales | Shopdeco source. | Same ERP controller. The error page filters persisted errors and can display the stored Shopdeco XML order file through get_shopdeco_file; it does not re-fetch the order just to render the row. |
| ApiShopping | api_shopping_shipped_sales, api_shopping_invoiced_sales, api_shopping_pending_sales, api_shopping_all_sales | accountId = all from this menu node. | Same ERP controller; the account ID is also sent with table requests and used in the access-menu name. |
| EdenRed | The same four api_shopping_* state routes, plus api_shopping_export_invocies | accountId comes from ApiShoppingService::getEdenRedAccountId(). | Same ERP controller, but the explicit account value scopes the table. Invoice export opens a date-range page; its default range is from one month ago through today. |
| Lengow | lengow_pending_invoice_sales, lengow_shipped_sales, lengow_pending_sales, lengow_all_sales; lengow_sales_issues is added under the configured Cotecosy account node | accountId is read from the lengow parameter and passed on every state route and table request. Menzzo and optional Mosaikasa nodes have four states; Cotecosy also has the issue view. | Same ERP controller. The repository queries are account-scoped; the issue query sets haveIssues = true, and the all-orders view includes the holded status. See Lengow integration for import and status-feedback details. |
| Wayfair | erp_wayfair_shipped_pending_invoice, erp_wayfair_invoiced_sales, erp_wayfair_pending_sales, erp_wayfair_sale_all | Wayfair source; no explicit menu account parameter. | src/ErpBundle/Controller/Wayfair/SaleController.php; separate Wayfair page and query methods. |
| Shopping Feed | erp_shopping_feed_shipped_pending_invoice, erp_shopping_feed_invoiced_sales, erp_shopping_feed_pending_sales, erp_shopping_feed_sale_all | storeId is read from the configured shoppingFeed[35777] entry. | src/ErpBundle/Controller/ShoppingFeed/SaleController.php; the selected store ID is carried into each route and list query. |
| Les Tendances | erp_les_tendances_shipped_pending_invoice, erp_les_tendances_invoiced_sales, erp_les_tendances_pending_sales, erp_les_tendances_sale_all | Provider source from LesTendancesService. | src/ErpBundle/Controller/LesTendances/SaleController.php. |
| ePrice | erp_eprice_shipped_pending_invoice, erp_eprice_invoiced_sales, erp_eprice_pending_sales, erp_eprice_sale_all | Provider source from EPriceService. | src/ErpBundle/Controller/EPrice/SaleController.php. |
| Paris Prix | erp_paris_prix_shipped_pending_invoice, erp_paris_prix_invoiced_sales, erp_paris_prix_pending_sales, erp_paris_prix_sale_all | Provider source from ParisPrixService. | src/ErpBundle/Controller/ParisPrix/SaleController.php. |
| Tati | erp_tati_shipped_pending_invoice, erp_tati_invoiced_sales, erp_tati_pending_sales, erp_tati_sale_all | Provider source from TatiService. | src/ErpBundle/Controller/Tati/SaleController.php. |
For these provider pages, the label Commandes expédiées (à facturer) is a local invoicing stage; it is not evidence that an invoice was created. Check the provider controller's route and repository method before diagnosing a missing row. In particular, keep accountId, storeId, and source distinct when following a table request.
Other channel and dropship order lists
These leaves are intentionally grouped by implementation. Most have one “Toutes les commandes” entry; their controllers filter on a dropship type and may expose supplier-specific columns or errors.
| Menu group | Route family | Implementation |
|---|---|---|
| AsirGroup | erp_asirgroup_sale_all | src/AsirGroupBundle/Controller/SaleController.php; lists type = dropship:AsirGroup, with supplier invoice, shipment, and tracking fields. It also owns the error, import, and stock leaves below. |
| AsirGroupMode | erp_asirgroupmode_sale_all | src/AsirGroupModeBundle/Controller/SaleController.php; list query uses type = dropship:AsirGroupMode. A Calberson error view is also exposed. |
| Notio | erp_notio_sale_all | src/NotioBundle/Controller/SaleController.php; list query uses type = dropship:Notio. Carrier exception views are exposed separately. |
| Mauro Ferretti SRL | erp_mauro_sale_all | src/MauroFerrettiSRLBundle/Controller/SaleController.php; list query uses type = dropship:MauroFerretti. |
| BigBuy | erp_bigbuy_sale_all | src/BigbuyBundle/Controller/SaleController.php; list query uses type = dropship:bigbuy. |
| Adsteroide | erp_adsteroide_sale_all | src/ErpBundle/Controller/Adsteroide/SaleController.php; forwards to the shared all-sales page with type = dropship:adsteroide. |
| Phalimi | erp_palimi_sale_all | src/ErpBundle/Controller/Palimi/SaleController.php; forwards to the shared all-sales page with type = dropship:palimi, which enables the Palimi tracking action in that table. |
| VidaXL | erp_vidaxl_sale_all | src/VidaxlBundle/Controller/SaleController.php; list query uses type = dropship:vidaxl and includes supplier error information. |
| Cmp | erp_cmp_sale_all | src/CmpBundle/Controller/SaleController.php; list query uses type = dropship:Cmp. |
Supplier, carrier, and import workflows
AsirGroup and Notio shipment exceptions
The error leaves are separate from each supplier's all-orders table:
| Menu leaf | Route path through source | What it filters or renders |
|---|---|---|
| AsirGroup — Commandes erronées Calberson | all_sale_asir_group_error | Renders the shared Calberson table with type = AsirGroup; rows come from shipment/error data rather than the all-sales query. |
| AsirGroup — Étiquettes Geodis | calberson_index with drop_ship = AsirGroup | Targets GeodisController; the menu omits the path parameter warehouse (see the route-generation caveat below). The controller table passes carrier, warehouse, error, and dropship filters to the shipped-Calberson repository query. Ticket-print errors and their messages are returned on rows with a shipping-address edit action. |
| AsirGroup — Commandes erronées Chronopost / GLS | all_sale_asir_group_chronopost_error, all_sale_asir_group_gls_error | Each checks its menu permission, sets showAsirGroupErrors = 1, then forwards to the shared Chronopost or GLS controller. |
| AsirGroupMode — Commandes erronées Calberson | all_sale_asir_group_mode_error | Dedicated AsirGroupMode controller page and list query. |
| Notio — Commandes erronées Calberson | all_sale_notio_error | Renders the shared Calberson table with type = Notio. |
| Notio — Étiquettes Geodis | calberson_index with drop_ship = Notio | Targets the same Geodis controller with the Notio filter; this menu leaf also omits warehouse. |
| Notio — Commandes erronées Chronopost / GLS | all_sale_notio_chronopost_error, all_sale_notio_gls_error | Forwards to the shared carrier controllers with the Notio error filter enabled. |
The calberson_index annotation declares /geodis/{warehouse} without an explicit route default. The AsirGroup and Notio leaves supply only drop_ship, and the Commandes parent supplies no warehouse; its warehouse-specific children do supply 1/2/3. The PHP action parameter defaults to null, but effective route generation was not inspected. Treat these menu links as unresolved until the framework-generated route confirms how the missing parameter is handled.
When a Geodis label fails, start with the row's saved ticket error and message, then check the matching shipment product and shipping address in the carrier workflow. A successful page load does not mean a label was issued. Chronopost and GLS error leaves reuse shared carrier pages; preserve the showAsirGroupErrors filter when tracing the forwarded request.
AsirGroup invoice and promotion imports
| Menu leaf | Input and route | Processing and result |
|---|---|---|
| Facturation | asir_group_import_invoice_files forwards to the shared file-import page with AsirGroupInvoiceProcessors as its model. Upload accepts the importer-supported workbook through the shared sales_upload_general_invoice_csv_files endpoint. | menzzo:file:import-processor consumes pending import records. The processor reads invoice number/date from the workbook and sale-product references, then updates invoiced quantity and supplier invoice amount/date/number. It records alerts for duplicate/over-quantity invoices, price differences, and invoices on unshipped products. Review the import status, error count, and detail output before treating a file as reconciled. |
| Import promotions | asir_group_import_promo_files renders the Asir promotion page. The form accepts .xls, .xlsx, or .csv files and submits them with ImportPromoFileProcessor as the model. | The processor validates SKU, wholesale/promo price, and dates; it creates ProductPriceHistory rows. If the file lowers a supplier wholesale price, it updates the product and queues ProductPriceUpdateProcessor for affected EU stores at at_5th_minute. Invalid rows and missing products are recorded in the import messages. This import mutates price history and can enqueue catalog price updates. |
Both imports use the shared FilesImportController, FilesImportService, and FilesImportProcessorCommand. The UI tracks pending, processing, complete, and error states, plus error counts and detail logs. The source confirms the processor command, but not the current schedule that invokes it.
AsirGroup internal stock and parcel reports
| Menu leaf | Data path and purpose | Mutating action |
|---|---|---|
| Colis non conforme | non_conform_index renders the parcel exception table; pagination calls SaleProductRepository::searchNonConformColis(). Rows can show damaged/non-compliant parcel types and dates. | The parcel scan flow can upload a JPEG from the scanned parcel evidence and save its path and non-conformance date on the SaleProductShippingLabel. The image is stored under web/non_conform_parcel_image/. |
| Log Stock Asir | asir_stock_index renders stock-log entries through ProductStockAsirController and ProductRepository::getAsirStock(), including SKU, quantity, source, user, and timestamp. | The page has quantity update controls; controller actions update supplier-internal stock and append an Asir stock log. |
| Stock Asir | list_asir_internal_stock renders the current internal stock view and uses the same controller's paginated data and log endpoints. | Manual quantity changes use update_asir_quantity or add_update_asir_quantity_product; both update product stock and record the operator/action. |
| Commandes scannées mais non livrées | asir_scanned_and_undelivered_orders queries scanned, undelivered Asir orders through ProductRepository::getAsirScannedAndUndeliveredOrders(). viewAllStatuses changes the status scope. | The “Masquer” action posts selected saleProductIds to hide_scanned_unshipped_asir_sale_bulk, which sets isHided = true; it hides the row from this report and does not mark the order delivered. |
The parcel exception page's GET action does not show a hasAccess() call in the inspected controller method. This source observation does not establish whether a global firewall protects it; verify the effective route policy separately when changing access.
Other distinct Store workflows
| Menu group | Page and user input | Result or side effect |
|---|---|---|
| Amazon | sale_list_amazon_commands shows the Amazon orders list. amazon_scanned_orders_list shows sale products with at least one scanned shipping label, including parcel and scan counts. | On the scanned page, the delivered action posts spId to mark_amazon_product_as_delivered; the controller calls mz.amazon.shopping->createSaleProductShipment() with the current user ID. This changes shipment state and invokes the Amazon service. |
| Google — Retours commandes | sale_return_index is the unprocessed queue (returned = 0); sale_return_returned is the processed queue (returned = 1). Both use paginate_return and show sale, shipment, carrier, tracking, SKU, quantity, reason, and date. | Selected return rows post IDs to sale_return_refund_items; the action calls the Google Shopping refundLineItem() connector and returns per-item success/error results. This is an external refund action. |
| Drop | sale_drop_pending, sale_drop_invoiced, all_drop_sales | Three shared AppBundle\Controller\Sale\SaleController pages, backed by separate pending, invoiced, and all-Drop queries. The tables show the supplier order identifier, Menzzo order, tracking, status, and products. |
| Cotecosy — Import des commandes | cotecosy_index renders the import page. The no-ID “Importer les commandes” control currently alerts that the action is disabled and returns before its request. The active single-order form requires a Cotecosy increment ID and posts it to import_sale_cotecosy. | The controller starts or resumes a token-backed job and polls one order at a time. The processing call goes through SaleApi::importCoteCosySale() to GET rest/V1/logidav-api/import-cotecosy-sale/{incrementId}. The page polls every two seconds and displays returned text; the handler can return error text with HTTP 200, so inspect the message and Cotecosy application log when a row does not import. |
| Cotecosy — Gestion des produits | product_list renders the product table from ct.api's catalog_product.list; row editing loads catalog_product.info. | Saving uses the remote catalog_product.update operation and writes a local CotecosyProductLog entry. The product name has its own update action. |
Troubleshooting by route boundary
- If a menu is absent, compare its leaf name with the user's
menuAccessand the parent node'shasDisplayedChildren()behavior. Then test the controller'shasAccess()name separately; a menu label or source value is not enough to infer a permission key. - If a shared queue is empty or shows another store's rows, inspect the generated route for
storeIdversussource. For provider pages, inspectaccountId; for supplier all-order pages, inspecttype = dropship:<provider>. - If the page loads but the table does not, follow the template's DataTables URL to its pagination route and check the posted
columns,order,start, andlength. For exports, also checkformatandallVisiblecolumns. Some callback actions do not repeat the page controller's access call. - For Lengow, verify that the same account ID reaches the page and its table request. The mismatch view sets
haveIssues = true; the all-orders view also labelsholdedsales. See Lengow integration for the importer and status refresh sources. - For AsirGroup imports, use the file-import status, error count, and per-file detail log. Duplicate invoice quantities and supplier-price discrepancies are represented as alerts; promotion files can create queued price updates after changing local price history.
- For carrier exceptions, distinguish saved ticket errors from a missing row. Geodis displays ticket error text on the row; the Chronopost/GLS views are shared pages with an AsirGroup or Notio filter.
Source and live-state limits
The source revision proves the menu definitions, route/controller mapping, page templates, and the local repository/service calls cited above. It does not prove that a given user currently sees a node, that credentials or provider endpoints work, that a scheduled processor is running, or that any production sale, invoice, label, refund, or import has completed. Verify those at their owning runtime boundary before calling a workflow live or complete.