Skip to content

Stock and Purchasing ​

This page begins at the active Produits menu in src/AppBundle/Menu/Builder.php, then follows its screens into Symfony annotations, Twig pages, form/AJAX actions, services, and local state. The evidence is the reviewed immutable axelites/logidav source snapshot at 88d9180215a5d489407498fe4905fdd38efd756d. This is a static source map; it does not establish deployed behavior, active permissions, configured schedules, current external-provider responses, or operator acceptance.

The stock menu contains several different quantities and states. Product.qty, inventory quantity, warehouse quantity, ProductInventory rows, incoming CommandProduct/ContainerProduct quantities, and availability dates are maintained through different screens and actions. Treat these as separate data until a traced action connects them.

Active menu groupMenu entries / route familiesUI purpose and traced continuation
Gestion des stocksproduct_index, product_prospect_index, product_dropship_stock, end_of_product_stock, product_stock_value_stock_value, product_stock_value_stock_value20210331, product_stock_value_0104202231082023_stock_value, product_stock_value_stock_value20210331_c1204, product_container_stock_value_stock_value20210331, product_calculate_product_stock_value, products_qty_stat_indexStock table and editable product data; prospects; supplier/dropship stock view; end-of-life product queue; current and named historical stock valuations; quantity statistics. Named historical valuation leaves are separate screens/data snapshots, not a single live-stock total.
Achats fournisseursproduct_purchases, product_arrivals, product_arrivals_calendar, product_commands, product_arrival_date_index, product_arrival_reservation_ignore, product_reservations, product_buying_price_indexPurchase and supplier-order tables; container arrivals/calendar; arrival-date follow-up; reservation exclusion/call follow-up; buying-price table. The command/container/unload path is the state-changing purchasing lifecycle below.
Les fabricantsmanufacturer_index, manufacturer_stock_value_indexManufacturer maintenance, plus CBM/currency and manufacturer valuation configuration.
Gestion des produitsMedia library; supplier new-product screens; product catalogue/all/same-SKU/tags/archived; translations; creation stats/synchronization; attributes, price calculation, universe/category tools, decoration images, category positions, EAN and recent-product screensProduct content and catalog administration. Supplier intake families are enumerated below; menu labels sharing a controller still lead to different pages/actions.
Emplacements des produitsemplacement, product_orphelin_indexMaintain product location assignments and resolve unassigned/orphan locations.
Suivi des quantités venduesv2_index(redirect_to=app.products_sales_quantity_overview)Symfony creates a login-token row and redirects to the configured newer Logidav URL. The new application target is outside this source path, so its screen/actions are not asserted.
Produits hors stocksale_list_products_nostockProduct-level shortage report (SKU, availability, order count, quantity), not the out-of-stock order-line queue under Commandes.
Inventaire / Inventaire 2product_inventory_index, product_inventory_new_indexEmplacement-level inventory rows; second screen adds scanning/print workflow. A separate explicit sync action aggregates unsynced rows into product quantity.
Gestion des prixproduct_shipping_price_index, product_price_tariff_propose_index, product_price_sheet, product_price_sheet_log, v2_index(redirect_to=app.product_price_update_planning)Shipping-price grid and update/resync history; tariff proposal and price-sheet calculations/logs; newer price-planning app bridge.
Dictionnairesproduct_dictionaries_indexSKU dictionary/local-SKU mappings with search/export/update.
Gestion des disponibilitésavailability_index, availability_all, product_threshold_by_categoryPending and validated availability logs, inline date correction/validation, category threshold maintenance.
DropShipJolipa, BigBuy, VidaXL, Asir Group, Asir Group Mode, CMP, Notio route familiesSupplier catalogue/category/selection and online-product views as available per supplier. See supplier matrix.
Merchantsproduct_merchants_info_index, product_merchants_alert_index, V2 custom labels bridgeMerchant listing and alert screens; custom-label menu route hands off to the newer app.
Veille des produitsproduct_monitoring_index, product_monitoring_report_indexManage tracked products/URLs and view monitoring report/history.
AIchat_aiChat screen; message POST calls the configured OpenAI wrapper and returns generated text.

Active means the child is not commented out in the pinned menu source. The old product_stock_value route, attribute-management alternative, price V2 menu, dropship-price menu, commented container departure, and several supplier selection leaves are not active menu paths in this snapshot.

Main stock table and location-specific quantities ​

GET /product/ (product_index) checks stock_product_index, loads manufacturers, attribute sets, any SKU forwarded through the session, and warehouse choices, then renders AppBundle:Product:index.html.twig. GET / POST /product/paginate-product-stock/ reads table filters/order, showNewProducts, and optional SKU, calls ProductRepository::searchProductStock, and returns rows/export. Rows combine SKU/product data, Product.qty, per-warehouse quantities, inventory quantity, arrivals/ordered quantities, stock valuation and latest quantity-log date. Product data and warehouse totals appear together, but use different edit actions.

Screen control / actionMethod and URLHandler and state effect
Change product availabilityPOST /product/update-product-dispo (update_product_dispo), fields id and dispoProductController::updateProductDisponibilityAction delegates to ProductService::updateProductDispo. The broader availability/queue contract is in Stock Updates.
Edit product quantityPOST /product/update-qty-product (update_qty_product), product ID and quantity fieldsUpdates core product quantity through the product service and logs the stock change. Negative values are refused unless the user is admin or has CAN_SET_NEGATIVE_QTY. It is not an edit to a single warehouse row.
Edit one warehouse quantityPOST /product/update-warehouse-products-qty (update_warehouse_products_qty), product ID, warehouse ID, quantity, commentUpdates the product/warehouse relation through ProductWarehouseService; warehouse quantity history is separately viewable.
Move quantity between warehousesPOST /product/move-warehouse-qty (move_warehouse_qty), product ID, from/to warehouse IDs, quantity and commentDelegates to warehouse quantity move path; it is not equivalent to increasing total product stock.
View quantity journals/product/product-qty-log, /product/product-inventory-qty-log, /warehouse-product-qty-log/warehouse-product-qty-history-by-warehouseProduct, inventory and warehouse histories use separate log screens/actions. They help reconcile which quantity was changed.
Product-level shortage viewGET /sale/sale-list-products-nostock (sale_list_products_nostock), then /sale/sale-products-nostock-paginateSaleController::productsNoStockAction() → Sale/saleProductsNoStock.html.twig; JSON rows show SKU, availability, order count and quantity through ProductRepository::searchProductsNoStock. This is a report, not the Commandes → Expédition → Hors stock queue.
Prospects / supplier stock / end-of-lifeGET /product-prospect/, /product/dropship-stock, /product/end-of-product-stock and each paginate routeDedicated ProductProspect/ProductController pages render prospect data/photos, supplier-stock rows, or end-of-product stock. These are separate views; their displayed quantities do not replace the main stock-edit workflow.

ProductQtyLogService and the linked Stock Updates page document reviewed stock mutation branches and the Magento availability/price queue path. The menu action alone does not show a queue schedule or prove propagation to marketplaces.

Supplier orders, containers, arrivals, and unloading ​

The Achats screen shows products/manufacturers and in-progress commands through ProductController::productPurchasesAction() and Product:purchases.html.twig. Commandes fournisseurs opens GET /product/commandes (product_commands) → Product:commands.html.twig; its paginated table uses mz.command::searchCommandProduct. Command and command-product rows carry supplier reference, deposit, ordered/shipped quantities, costs and status.

View diagram source
flowchart LR
    Purchase["Achats / supplier products"] -->|create or edit command lines| Cmd["Command + CommandProduct"]
    Cmd -->|create container| Container["Container + ContainerProduct"]
    Container -->|arrivals/calendar and status edits| Arrival["Expected arrival and warehouse"]
    Arrival -->|unload-container-store| Stock["Product.qty + inventory qty + ProductWarehouse"]
    Stock --> QtyLogs["ProductQtyLog / InventoryQtyLog / ContainerLog"]
    Container -->|eligible processing lines| PrintQueue["SaleProduct.toPrint + warehouse"]
    InvRows["ProductInventory rows, is_sync=0"] -->|explicit sync command| Stock

Diagram

The main command/container endpoints are:

Operator actionMethod and URLInputs / output / state
Create supplier commandPOST /product/create-command (create_command)reference, created_at, arrival_at, deposit, products {id, qty, value}, and optional action/id_cmd. CommandProductInputNormalizer rejects invalid line inputs with a flash error/redirect; accepted lines are saved under Command, then the page redirects.
View/edit a commandGET /product/command/{id} (product_command_view)Route-bound Command; renders Product:viewCommand.html.twig with warehouse list. Per-line quantity/value changes use /product/update-cmd-qts or transactional /product/update-cmd-qts-bulk; changes are logged by ContainerLogService.
Add products to command/product/add-product-command (add_product_command)id_cmd, normalized product IDs, ordered quantities and unit values; redirects to command view.
Create container from command lines/product/create-container (create_container)cmd_id, selected command-line IDs/quantities, reference, ship name, created/sent/arrival dates, warehouse and transport price. Increments CommandProduct.qtyShipped, creates ContainerProduct rows and marks a command complete when every ordered quantity is covered.
Arrivals list / editGET /product/arrivals (product_arrivals), GET / POST /product/paginate-product-arrivals; POST /product/update-date-arrival, /product/update-status-container, /product/update-sku-containerEntry requires product_arrivals menu access plus LIST_ARRIVAL or admin for the list. Grid shows container reference, shipment/arrival date, status, warehouse, products, transport and approach fee. Edits save fields and write container logs.
Arrival calendarGET /product/arrivals/calendar; GET /product/paginate-product-arrivals-calendarCalendar query takes start/end or container_id; returns Container plus ContainerPlanning events. Print controls depend on admin or CAN_PRINT_FROM_INTERFACE_UNLOADING.
Print container/product labelsPOST /product/etiquettes-container-print; POST /product/print-sale-products-for-containerContainer ID and/or warehouse selection produce PDF/print data. Printing is not unloading.
Unload container into warehousePOST /product/unload-container-storeid container and JSON emplacements. Requires a container warehouse; missing warehouse throws an error. If status is already arrived, returns arrived. For lines not matched by its quantity-log heuristic, adds quantities to Product.qty, inventory quantity and an existing matching ProductWarehouse; writes quantity logs, makes eligible processing sale lines printable for that warehouse, applies emplacement assignments and sets container status arrived.
Change command/container status/product/update-status-command, /product/update-status-containerEntity ID and new status; persists and logs transition. These endpoints do not by themselves unload quantities.

Command, CommandProduct, Container, ContainerProduct, ContainerPlanning, ProductWarehouse and container/quantity logs are the local state boundary. Container creation automatically sets a supplier command complete when its ordered and recorded shipped quantities match. Manual status updates can also set complete, and container-line edits/removals do not reconcile CommandProduct.qtyShipped. Neither the status nor that total is a fulfillment invariant.

Unloading normally sets arrived after its stock changes, but the separate status endpoint can set arrived directly. An already-arrived container returns before warehouse validation or quantity changes; manually assigning that status can therefore bypass unloading.

Retry detection is best-effort: it searches product logs for action Unload, a message containing the container reference, and a quantity delta equal to the individual container line. The loop aggregates duplicate product lines before writing one quantity log and has no enclosing transaction. After a partial failure, the aggregate log may not match an individual line, so a retry can add quantities again. Do not treat the log check as durable per-line idempotency or retry without reconciling container, product, inventory, warehouse and quantity-log state.

The separate Suivi des arrivages leaf (product_arrival_date_index) and buying-price list (product_buying_price_index) are follow-up tables, not additional state transitions in container unloading.

Reservation screens and supplier prices ​

Reservations ignorées renders Product:arrivalReservationIgnore.html.twig. Paginate returns each product’s SKU/name/image, ignored flag and a status derived from ignore/no-sell state. Inline select POSTs sku and ignore to /product/update-arrival-reservation-ignore. Blank SKU returns HTTP 400; unknown SKU returns HTTP 404; otherwise Product.isIgnoredFromReservation is saved. This setting excludes a product from the reservation path; it does not modify stock quantity.

Réservations de produits renders Product:productReservations.html.twig and uses ProductReservationServiceInterface for its table. /product/product-reservations/{id}/call-info reads call status; POST to the same URL updates call metadata; /email-history reads existing restock-message history. Rows may show mail/SMS/WhatsApp timestamps and errors, but this controller evidence does not prove a notification is delivered or that opening the reservation page sends one.

Prix d’achat des produits (product_buying_price_index) and Achats can edit buying-price/cost-related data. Les fabricants → Gérer les fabricants provides manufacturer management; Gérer les cbm et les devises uses ManufacturerStockValueController/ManufacturerStockValueService for valuation factors. The same menu group includes current and historical valuation reports; date labels (including 31/03/2021 and the 04/22–08/23 interval) describe menu entries and should not be represented as current figures.

Product inventory is not the product-stock table ​

Inventaire opens GET /product-inventory/ → Product:Inventory/index.html.twig; Inventaire 2 opens /product-inventory/new → Product:Inventory/indexNew.html.twig. Both check the inventory menu permission. The table manages ProductInventory rows keyed to a product and emplacement, with row quantity and is_sync state. Inline row actions call:

Inventory controlMethod and URLInputs and effect
List/searchGET /product-inventory/paginateTable filters/order; returns inventory/emplacement view and isSync.
Add scanned/product quantityPOST /product-inventory/add-newproductId, emplacement, qty, optional force-update flag. Existing product+emplacement row returns a conflict-style prompt unless merge is confirmed; otherwise row is created or quantity accumulated.
Edit inventory quantity / emplacementPOST /product-inventory/update-qty; /product-inventory/update-emplacementRow ID plus new quantity or emplacement ID; modifies inventory-row fields, not core product quantity.
Delete inventory rowPOST /product-inventory/delete-product-inventoryInventory row ID; removes that row.
Print inventory sheetPOST /product-inventory/printToken starts menzzo:v2:products:inventory:print; repeated token requests read Block progress.
Synchronize inventory into product stockPOST /product-inventory/sync-products-stockToken starts menzzo:product:inventory:sync-stock; repeated token requests read progress. This is the explicit bridge from inventory rows to core stock.

SyncStockCommand uses a lock, selects mz_product_inventory rows where is_sync=0, sums quantities by product, calls ProductService::updateProductQty(...), and marks those rows synchronized inside the transaction. It passes updateInMagento=true: for Menzzo products, ProductService calls ProductApi::updateProductStockData before local writes, issuing PUT rest/V1/products/{sku}/stockItems/1. A local transaction rollback does not undo an already accepted external stock update. It catches row-level throwables, rolls back that product’s transaction and records an error in progress/log output. A progress token ending with !END! is the command protocol’s completion marker; this static trace does not prove the command ran successfully in a particular environment.

Availability, thresholds, price, and SKU maintenance ​

The availability submenu separates unvalidated changes from all/validated history. GET /availability/availability-log/{productId} → Availabilitylog:index.html.twig; GET /availability/paginate-availability-log filters validated=0; POST /availability/availability-update takes productId and date, changes product availability and logs old/new date; POST /availability/mark-as-valid takes selected activity IDs and transactionally marks those log rows validated. GET /availability/availability-log-all and its paginate action show broader history. The separate Seuil du stock par catégorie route (product_threshold_by_category) updates a category threshold; it is not a product availability date.

GET /product/shipping-price/ opens the shipping-price grid, with POST /product/shipping-price/paginate and POST /product/shipping-price/update. Update requires the menu permission, a valid CSRF token and authenticated User; it accepts the edited grid payload, returns HTTP 202 with store/status/bulk UUID records, reports no-op updates separately, and returns HTTP 400 on the service update exception. Resync has GET /resync/candidates and POST /resync; it refuses when the feature is disabled or CSRF/user checks fail and returns queued/skipped/remaining counts. /lookup, /add and /{productId}/history support lookup/manual addition/history. Processing after a bulk UUID is outside this UI action trace.

The Proposition d’offre tarifaire, Base de calcul and Log de calcul des prix routes go through product tariff/price-sheet controller families. Price-sheet rows can be updated/reset/recalculated and logged; their presence is a calculation workflow, not proof a store price has been published. Planification de mise à jour des prix is a v2_index handoff, separate from the legacy price-sheet controller.

The Dictionnaires → SKUs page uses ProductController dictionary routes to list/export mappings and update a local SKU. It is distinct from product identity creation and warehouse stock editing.

Product setup, catalogue, and supplier dropship ​

Use Product Content and Media for media, category, attribute, universe, decoration and EAN actions; Supplier Catalogues traces intake, selection, review, translation and publication. Pricing and Monitoring expands price calculations, valuations and monitoring.

The menu has a product-content administration branch and a separate supplier dropship branch. The first concerns Logidav product records/content; the second has supplier-specific catalogue/selection/online lists. A menu path in one branch is not evidence that a supplier record was published to every connected store.

Active menu entriesSource controller family and UI routesTraced action / state boundary
Création produit Menzzo, BigBuy, VidaXL, Palimi, Adsteroide, Asir Group, Asir Group Mode, CMP, Notionew_products_index, new_products_bigbuy_index, new_products_vidaxl_index, new_products_palimi_index, new_products_adsteroide_index, new_products_asir_group_index, new_products_asir_group_mode_index, new_products_cmp_index, new_products_notio_index → NewProductController and supplier controllersEach menu leaf opens its own supplier intake page; NewProductService and product entities carry candidate rows and processing/status metadata. Supplier pages have distinct selection, creation, description and publication steps. Every supplier field mapping through final Magento/provider acceptance was not traced.
Asir Group: Validation de description; Traduction et publication; Notio: Validation de description; Traduction et publicationnew_products_to_be_processed_asir_group_index, translation_and_publication_process_asir_group_index; new_products_to_be_processed_notio_index, translation_and_publication_process_indexDedicated review/translation queues for candidates; do not collapse into the initial intake list. Translation/publication destination acceptance was not verified.
Catalogue, Tous les produits, Produits consolidés, tags, archivés, produits nouvellement créésproduct_catalog, product_all, product_same_sku_index, product_tags, archived_products_index, product_list_recent_products → ProductController pages and paginate/update endpointsReads/filters local product catalog; consolidated/SKU/tags/archive screens use separate predicates/actions. Product status changes and queueing are action-specific; do not infer every catalog screen publishes changes automatically.
Mediathèques / Liste des produitsmedialibrary_index, medialibrary_product_listMedia-library and product-list routes. Upload, association and deletion actions are mapped in Product Content and Media.
Traductions → Produits Menzzo / Produits DropShip / Titres Asir Grouptrans_product_index, trans_product_dropship_index, trans_drop_ship_title_index → TransController familyMenzzo route enters TransController::indexAction() and immediately returns a literal “Veuillez traduire dans meduse” exit response; this is a deliberate boundary before a working local page/action. Other translation routes exist, but full downstream publication state is not established here.
Statistiques de créations; Synchronizationstat_product_creation_index; synchronize_indexSeparate creation-statistics and synchronization pages. The menu alone does not establish import schedule or vendor propagation. See Product Sync for reviewed product-import and queue boundary.
Attributes, univers, categories, decoration imagesmanagement_attributes_product, calcul_product_price_index, univers_products_index, products_new_categories, product_deco_image, update_product_categories, manage_sync_categoriesAttribute/price inputs, universe/category assignment, decoration image operations and category positions are separate edit surfaces. Their individual button contracts are expanded in Product Content and Media and Pricing and Monitoring.
EAN managementmanage_ean_product, generate_ean, list_ean_by_parcelProduct-level EAN maintenance/generation and parcel EAN listing; external allocation/scan acceptance was not reviewed.

DropShip submenu matrix:

SupplierActive menu leaves and route namesShared workflow shape / traced boundary
Jolipaproduct_jolipa_index, product_creation_index, product_dropship_online(dropshipName=jolipa)Product list and product-creation page in ProductController; online list is the parameterized generic dropship view. Product update/creation actions exist in this controller.
BigBuybigbuy_catalog_category, bigbuy_catalog_index, bigbuy_catalog_selection, bigbuy_index_dicionary, bigbuy_shipping_rates_update_rates_by_csv, bigbuy_dropship_onlineBigBuy category/catalog/selection pages plus dictionary, CSV shipping-rate update and online-product table in BigbuyBundle. Selection can add/remove candidates and create supplier-side new-product work; online list uses supplier services/state.
VidaXLvidaxl_category_index, vidaxl_catalogue_index, vidaxl_catalog_selection, vidaxl_dropship_onlineVidaXL category/catalog/selection/online screens in VidaxlBundle; selection operations connect catalog candidates to supplier product pipeline.
Asir Groupasir_product_management, asir_group_catalogue_index, asir_group_catalog_selection, asir_group_catalog_fast_selection, asir_group_online_products, asir_group_online_products_to_negociate, asir_group_online_products_to_remvoe, asir_group_amazon_productsAsir-specific product management, catalog/selection and distinct online, negotiation, removal and Amazon data views. Online list exposes review/action/visibility workflows; they update Asir product/supplier state and logs.
Asir Group Modeasir_group_mode_catalogue_index, asir_group_mode_catalog_selection, asir_group_mode_online_products, asir_group_mode_catalogue_ai_titles, asir_group_mode_refused_ai_titlesDedicated bundle routes for catalog/selection/online products and accepted/refused AI-title queues. Title decision endpoints persist title state; AI-title decision is not equivalent to publishing a product.
CMPcmp_category_index, cmp_catalogue_index, cmp_selection_index, cmp_dropship_onlineCMP categories/catalog/selection and online-product listing in CmpBundle.
Notionotio_catalogue_index, notio_catalog_selectionNotio catalogue and selection pages; menu snapshot has no Notio online-product leaf.

These suppliers are distinct entry points but share the high-level candidate → selection → new-product/local product → online-review progression only where their controller code exposes that path. Specific external listing calls, provider responses and all supplier-specific error contracts remain outside this page’s traced boundary. Legacy service wiring is used in this repository; this documentation does not assume Symfony Messenger or universal autowiring.

Emplacements, merchants, monitoring, and AI ​

Emplacements opens /product/emplacement → Product:emplacement.html.twig; paginate and product-emplacement endpoints maintain hierarchical Emplacement assignments on Product. Produits orphelin opens /product-orphelin/; ProductOrphelinController lists products without a usable emplacement and exposes add/remove/assign/update-quantity actions. These affect product location/orphan state; they do not stand in for ProductInventory row counts.

Merchants pages use MerchantsProductsController: product list, alert list, and filter-state actions. Gestion des libellés personnalisés points to v2_index(redirect_to=app.products.custom_labels), not this controller. V2Controller stores an encoded login token containing user ID, source IP, user agent, action date and redirect target, then redirects to configured new_logidav_url. The target app screens and their authorization/operations were not inspected.

Product monitoring configuration (GET /product/monitoring/) has paginate/search/add-product/add-links/delete-link endpoints and a separate /report page with table/history/status actions. This is a tracked-product/link/report workflow, not stock mutation. Its external monitor execution schedule/result collection is not established by the page routes reviewed here.

AI opens GET /chat-ai/chat-ai → ChatAi/chatAi.html.twig; the page checks chat_ai permission. Its POST /chat-ai/chat-ai-message accepts message, passes it to OpenAi::openaiCompletion with a fixed model identifier and token limit, and returns the text portion as JSON result. The source does not show validation for missing/empty message or a persisted chat-log write in this action; no external request was made during this review.

Trace gaps ​

The linked product-content, supplier-catalogue, and pricing/monitoring guides trace the principal action contracts for those menu families. Field-by-field supplier validation and every report calculation are not reproduced in this overview. Live supplier publication, reservation notification delivery, installed monitoring schedules/provider responses, and newer-app targets for quantity-sales, price planning and custom labels remain outside the verified boundary.

Other boundaries: entry-page access checks do not prove every AJAX endpoint is separately guarded; no effective user-role matrix was tested; supplier, Magento or monitoring-provider acceptance and installed command schedules were not checked. For reviewed product-import/availability queue behavior, use Product Sync and Stock Updates; for sale-origin stock changes use Sales Import.

Source entry points ​

Internal developer documentation for Menzzo systems.