Skip to content

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"]

Diagram

The dashed marketplace edge is a missing source path, not a claim that the queue currently updates those destinations.

Trigger ​

SourceSource-backed behaviorEvidence boundary
Sale importSaleService::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 updateUpdateSaleCommand 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 importmenzzo:v2:products uses a Magento API import path with fast/full modes and a progress marker.The installed schedule is unknown.
Availability / price updateProducers queue updates; current processors choose the Magento API batch path.The generic queue's marketplace destinations are not established.
Container or manual adjustmentTraced separately through UI/controller paths in Stock and Purchasing.These are not inferred ProductQtyLogService action branches.
Physical returnUnknown in this source review.Do not infer quantity direction from the business label alone.

Components ​

ComponentFile PathRole
ProductQtyLogService::productChangeLog()src/AppBundle/Services/ProductQtyLogService.phpSkips canceled sale products; the sale branch decrements product/inventory quantities and writes logs.
ProductQtyLogService::log()src/AppBundle/Services/ProductQtyLogService.phpCreates a ProductQtyLog row on each invocation; no existing-entry lookup is present in the reviewed method.
SaleService::addOrder() / UpdateSaleCommandsrc/AppBundle/Services/SaleService.php; src/AppBundle/Command/Sale/V2/UpdateSaleCommand.phpReviewed order/status call paths into the sale mutation.
Availability/price producers and processorsProductService.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.phpPosts 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"]

Diagram

Mutation Types ​

Action branchWhat this source review establishes
sale / uncancelThe sale branch decrements product and inventory quantities and writes quantity logs. See the cited method before relying on uncancel semantics.
updateA named branch exists; its direction and full contract are not summarized here.
cancel / cancelProductNamed branches exist; their direction and caller coverage remain to be verified.
qtyA named branch exists; its direction and caller coverage remain to be verified.
return, container, manualNo branch/caller for these actions was established by the source review. Do not describe them as implemented mutation types.

Side Effects ​

Database ​

  • The sale branch updates product and inventory quantities and writes log entries
  • The reviewed log() method creates a ProductQtyLog row 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 ​

  1. Identify the affected product/SKU, the value that is wrong, and the system believed to own that field.
  2. For a sale-related mutation, record the source order ID/status and the exact ProductQtyLogService action path involved.
  3. 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.
  4. For availability/price propagation, follow the queue batch to the Magento API response. Do not infer marketplace delivery from a successful Magento response.
  5. 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.
  6. 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.
CommandPurpose
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:productsProduct import command with fast/full modes and a persisted progress marker.
Availability/price processorsCurrent 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.

Internal developer documentation for Menzzo systems.