Appearance
Stock Updates
What It Does
This page covers the stock mutation and catalog-update segments established by the source review. ProductQtyLogService applies several named action branches; its sale branch decrements product and inventory quantities and writes quantity logs. Separate availability and price queues currently use a Magento API batch path. The reviewed code does not prove a physical-return action, a common duplicate guard, or propagation to every marketplace. See the source-backed stock and catalog flow. The separate Stock and Purchasing interface guide traces manual edits, container unloading and inventory synchronization at its newer pinned revision, including retry and external-update limits.
How It Connects
View diagram source
flowchart LR
Magento["Magento product/order state"] -->|product import API| Import["ProductCommand"]
Import --> Logidav["Logidav product data"]
Sale["Sale import/status paths"] -->|sale action| PQL["ProductQtyLogService"]
PQL -->|quantity + log| Local["Logidav product/inventory state"]
ProductService["ProductService availability producer"] --> Queue["Logidav update queue"]
PriceService["PriceService price producer"] --> Queue
Queue --> Processor["Availability/price processors"]
Processor -->|current API batch path| API["Magento Logidav import API"]
API --> Magento
Queue -. "marketplace fanout not established" .-> Marketplace["Amazon / Cdiscount / ManoMano"]
The dashed marketplace edge is a missing source path, not a claim that the queue currently updates those destinations.
Trigger
| Source | Source-backed behavior | Evidence boundary |
|---|---|---|
| Sale import | SaleService::addOrder() calls the sale mutation for all lines on a new active order; an existing order applies it only to newly added lines when status is processing or complete. | Sale import path |
| Sale status update | UpdateSaleCommand has separate passes. Its first processing pass calls SaleService::addOrder() when the remote status differs; that call only logs stock for newly added lines in an existing order. The later selected-status pass and the 48-hour delta pass explicitly call productChangeLog(..., 'sale') when the remote status is processing. | The first pass does not explicitly stock-log every existing line; no general replay guarantee. |
| Product import | menzzo:v2:products uses a Magento API import path with fast/full modes and a progress marker. | The installed schedule is unknown. |
| Availability / price update | Producers queue updates; current processors choose the Magento API batch path. | The generic queue's marketplace destinations are not established. |
| Container or manual adjustment | Traced separately through UI/controller paths in Stock and Purchasing. | These are not inferred ProductQtyLogService action branches. |
| Physical return | Unknown in this source review. | Do not infer quantity direction from the business label alone. |
Components
| Component | File Path | Role |
|---|---|---|
ProductQtyLogService::productChangeLog() | src/AppBundle/Services/ProductQtyLogService.php | Skips canceled sale products; the sale branch decrements product/inventory quantities and writes logs. |
ProductQtyLogService::log() | src/AppBundle/Services/ProductQtyLogService.php | Creates a ProductQtyLog row on each invocation; no existing-entry lookup is present in the reviewed method. |
SaleService::addOrder() / UpdateSaleCommand | src/AppBundle/Services/SaleService.php; src/AppBundle/Command/Sale/V2/UpdateSaleCommand.php | Reviewed order/status call paths into the sale mutation. |
| Availability/price producers and processors | ProductService.php, PriceService.php, and src/AppBundle/Services/Queue/Processor/ | Queue producer and current Magento API batch consumer path. |
ProductApi::importLogidavQueueBatch() | src/CoreBundle/Api/V2/ProductApi.php | Posts queue batches to Magento rest/V1/logidav-api/import-logidav-queue. |
Step-by-Step Flow
View diagram source
flowchart TD
SaleImport["SaleService order import"] -->|"sale action on applicable lines"| Mutation["ProductQtyLogService"]
StatusUpdate["UpdateSaleCommand: selected-status / delta pass"] -->|"explicit sale action"| Mutation
FirstPass["UpdateSaleCommand: first processing pass"] -->|"delegates changed order"| SaleService["SaleService::addOrder"]
SaleService -->|"newly added lines"| Mutation
Mutation -->|"sale branch decrements"| State["Logidav product/inventory state"]
Mutation -->|"creates a row per call"| Journal["ProductQtyLog"]
Availability["ProductService"] --> Queue["Availability/price queue"]
Price["PriceService"] --> Queue
Queue --> Process["API batch processor"]
Process -->|"POST import-logidav-queue"| Magento["Magento"]
Return["Physical return action"] -. "no verified caller/branch" .-> Unknown["Evidence missing"]
Mutation Types
| Action branch | What this source review establishes |
|---|---|
sale / uncancel | The sale branch decrements product and inventory quantities and writes quantity logs. See the cited method before relying on uncancel semantics. |
update | A named branch exists; its direction and full contract are not summarized here. |
cancel / cancelProduct | Named branches exist; their direction and caller coverage remain to be verified. |
qty | A named branch exists; its direction and caller coverage remain to be verified. |
return, container, manual | No branch/caller for these actions was established by the source review. Do not describe them as implemented mutation types. |
Side Effects
Database
- The
salebranch updates product and inventory quantities and writes log entries - The reviewed
log()method creates aProductQtyLogrow on every invocation - No existing-entry lookup/deduplication guard is present in the reviewed methods; full audit fields and all other action effects require reading those branches
External Systems
- Availability and price producers feed Logidav queue processors that currently select an API path to Magento
- The reviewed generic queue path does not prove marketplace propagation, bidirectional sync, or a schedule
Schedule and downstream propagation unknown
The source audit identifies a queue-to-Magento API path, but it does not verify an installed cron frequency or a downstream marketplace schedule. Do not use the earlier “15–30 minutes” estimate as an operational promise. See the shared source-backed flow.
Inventory rows and store visibility
menzzo:product:inventory:sync-stock is a separate inventory reconciliation command. It groups unsynchronised mz_product_inventory rows by product, sums their quantities, calls ProductService::updateProductQty(), and marks those inventory row IDs as is_sync = 1 in the same per-product transaction. A failure rolls back that product's transaction and writes an error to the command log; the command continues with the next product. It requires a block token and uses a lock. The command does not establish a live schedule.
menzzo:products:sync-store-visibility updates non-France EU store visibility from the product availability bucket. It selects active Menzzo products with a source ID and excludes dropship products unless --include-dropship is supplied. The default allowed buckets are En_Stock, 1_semaines, 2_semaines, 3_semaines, and 4_semaines; Austria permits only En_Stock and 1_semaines. Products outside the allowed set receive Magento visibility 1; allowed products receive visibility 4. Missing ProductInfo assignments are counted and not queued. --dry-run produces the report without local or queue writes, and --force queues even when the local visibility already matches.
The visibility command targets the configured EU store IDs, excluding France (store 3), and queues a visibility update through ProductDataUpdateProcessor with the source product ID. A queued row still needs downstream Magento readback.
Arrival-reservation quantities use a different command and payload. See Arrival reservations and restock notifications for its long-availability, supplier remainder, fallback, exclusion, tag and customer-notification rules.
Failure Modes
Repeated stock mutation calls
The reviewed ProductQtyLogService::log() creates an entry on each invocation; the inspected service methods do not look up an existing matching entry or establish a duplicate guard. Multiple order/status paths can call the sale mutation. This makes repeated calls a risk to investigate, but the audit did not test concurrency or prove a particular duplicate incident.
Use the approved Logidav owner procedure to reconcile order status, quantity-log history, and current stock before any correction. A manual action or fix-up path was not verified here.
Negative stock
Whether negative values are accepted and under what configuration is not established by the reviewed source paths. Check the owning inventory rules before treating a negative value as allowed or as a defect.
Marketplace sync failure
Marketplace-specific producer/consumer paths, API failure handling, and retry schedule were not established by this audit. Use the relevant marketplace integration runbook if available; otherwise mark the path unknown.
Debugging Path
- Identify the affected product/SKU, the value that is wrong, and the system believed to own that field.
- For a sale-related mutation, record the source order ID/status and the exact
ProductQtyLogServiceaction path involved. - Use only the project owner's approved environment and runbook to inspect product/inventory state and quantity-log entries. The inspected
log()method can create an entry on each invocation, so repeated rows require investigation rather than an assumed idempotency guard. - For availability/price propagation, follow the queue batch to the Magento API response. Do not infer marketplace delivery from a successful Magento response.
- For container receipt or a manual edit, follow Stock and Purchasing to the specific controller and its state/retry boundary. Physical returns and marketplace schedules still need their own producer/consumer evidence.
- Do not correct remote stock or replay a queue item from this page alone. Use the approved operator procedure and record both the before/after owner states.
Related Commands
| Command | Purpose |
|---|---|
SaleCommand::execute() | Reads Magento orders after LAST_MAGENTO_ID and calls SaleService::addOrder(); installed command name/schedule not stated here. |
UpdateSaleCommand::execute() | Reconciles order status in three passes. The first processing pass delegates changed orders to SaleService::addOrder() and does not explicitly log every existing line; the selected-status and 48-hour delta passes explicitly call the sale mutation for remote processing. |
menzzo:v2:products | Product import command with fast/full modes and a persisted progress marker. |
| Availability/price processors | Current reviewed path submits batches to Magento's Logidav import API. |
Evidence and Open Questions
Source-verified at axelites/logidav@42116ebc0ba509bce9cc6651a55ecefd9a5fdb38: quantity action and canceled-line filter, sale branch, log creation without an existing-entry lookup, availability producer, price producer, availability processor, price processor, and Magento queue import API.
Physical-return producers, marketplace fanout and schedules, negative-stock policy, generic queue retries/deduplication, deployed configuration, and production outcomes remain unknown. Container/manual UI paths and inventory synchronization are documented separately in Stock and Purchasing.