Lengow Integration
Lengow is the marketplace connector used by Logidav for several marketplace channels. The active V3 flow imports marketplace orders into Sale / SaleProduct, stores the Lengow account and marketplace on the sale, and sends shipment or action feedback back to Lengow when Logidav changes the order.
Accounts
| Account / feed | Label | Status | Notes |
|---|---|---|---|
5622 | Lengow Menzzo | Active V3 | Configured under lengow in app/config/parameters.yml.dist; imported with menzzo:lengow:sales --marketplace=5622. |
6395 | Lengow Cotecosy | Active V3 | Configured under lengow; imported with menzzo:lengow:sales --marketplace=6395. |
17220 | Mosaikasa | Active V3 | New V3 account. It should reuse the V3 command, menu views, and lengow parameter structure. Product resolution has a special mz_product.ean_bis path. |
113959 | Lengow Menzzo Auchan | Retired V2 | Old V2 feed. Do not restore /erp/lengow/v2/all/113959 or the menzzo:lengow:v2:sales --feedId=113959 cron unless the retirement is intentionally reversed. |
The V3 service is registered as mz.lengow.shopping in src/ErpBundle/Resources/config/services.yml and implemented by src/ErpBundle/Services/Lengow/V3/LengowService.php. The V2 service is mz.erp.lengow.v2, implemented by src/ErpBundle/Services/Lengow/V2/LengowService.php, and should be treated as historical for feed 113959.
Command Flow
src/ErpBundle/Command/Lengow/V3/LengowSalesCommand.php is the entry point. It first checks mz.sale->canImportSales(), requires --marketplace, selects the account with LengowService::setLengowAccount(), and defaults --importFrom to 10 days ago for V3 imports.
The token refresh path is the same command with --refreshToken=1. It calls LengowService::getToken() and stores the returned token in Config under MZ_LENGOW_REFRESH_TOKEN_<account> through LengowSalesCommand::refreshToken(). The request helper in LengowService::execute() still obtains a token through getToken() before calling api_url, so token refresh is both an operational cron path and the place to verify account credentials.
Order Import Details
LengowService::getOrders() calls orders/?account_id=<account>&lengow_status=waiting_shipment&imported_from=<date> and follows next pagination. Each order is skipped when a local sale already exists with saleId = marketplace_order_id and source = Lengow.
For each non-canceled cart line, the service builds the line item payload expected by SaleService::addOrder():
| Lengow data | Logidav target |
|---|---|
marketplace_order_id | order_id, increment_id, duplicate key |
lengow_status | Sale status, mapped by the service status table |
marketplace | Sale::lengowMarketplace |
| selected account | Sale::lengowAccountId |
| billing/delivery blocks | Sale billing and shipping address fields |
packages[0].cart | SaleProduct rows |
| full Lengow order | orderinfo.lengow_order_info |
After parent::addOrder(), LengowService::addOrder() writes the Lengow marketplace/account fields and recalculates the real shipping method with setRealShippingMethodForLengow().
Product Resolution
The normal V3 product resolution logic lives in src/ErpBundle/Services/Lengow/V3/LengowService.php inside the cart loop:
| Lengow merchant product field | Resolution path |
|---|---|
field = sku | Match mz_product_info.mpn for storeId = 3, then fall back to mz_product.cotecosySku. |
field = id with numeric id | Match the Magento feed id through mz.product->getProductByFeedId(). |
field = id with string id | Try mz_product_info.mpn, then mz_product.cotecosySku, then mz_product.sku. |
| Empty merchant id with marketplace product id | Try mz_product_info.mpn, then mz_product.cotecosySku. |
Account 17220 | Mosaikasa-specific caveat: match the Lengow merchant product id against mz_product.ean_bis instead of the normal EAN/feed-id path. Keep this branch account-scoped so Menzzo and Cotecosy imports keep their existing resolution behavior. |
If no product can be found, the import catches the exception, sends a MARKETPLACE notification, logs the throwable through mz.log->notifyDevelopmentTeam(), and marks the order status as holded so it remains visible in operational views.
Status and Feedback to Lengow
Outbound feedback is centralized in LengowService::setActionToOrder(). It rebuilds the Lengow account from orderinfo.lengow_order_info, logs the outgoing body under the Lengow log directory, and posts to orders/actions/ with:
marketplace_order_idaccount_idmarketplaceaction_type- optional action-specific fields such as
tracking_number,tracking_url, andcarrier
LengowService::onSaleProductsShipped() listens to SaleProductsShippedEvent for sales whose source is Lengow. It collects tracking data, normalizes carrier-specific edge cases, and sends action_type = ship through setActionToOrder().
src/ErpBundle/Command/Lengow/V3/UpdateLengowStatusCommand.php checks Lengow actions updated yesterday with getActionsUpdatedOnDate(), reloads each order, maps Lengow statuses (shipped / closed to complete, waiting_shipment to processing, canceled to canceled), and stores any mismatch in Sale::lengowErrorMessage.
Error and Holded Path
There are two operational error buckets:
| Bucket | How it is set | Where to look |
|---|---|---|
status = holded | Import failed while resolving or creating an order line. | src/ErpBundle/Services/Lengow/V3/LengowService.php, lengow_sales_issues view, daily issue email. |
lengowErrorMessage IS NOT NULL | Logidav status does not match the mapped Lengow status after action status refresh. | src/ErpBundle/Command/Lengow/V3/UpdateLengowStatusCommand.php, src/ErpBundle/Command/Lengow/V3/LengowOrderIssueAlertCommand.php. |
src/ErpBundle/Command/Lengow/V3/LengowOrderIssueAlertCommand.php sends the daily anomaly email for source = Lengow sales in holded status and sales with a non-empty lengowErrorMessage.
Back-office Views
The V3 menu is built in src/AppBundle/Menu/Builder.php under the Lengow store menu. Each account should expose the same V3 views:
| View | Route | Meaning |
|---|---|---|
| Commandes expédiées (à facturer) | lengow_pending_invoice_sales | Shipped sales waiting for invoicing. |
| Commandes facturées | lengow_shipped_sales | Invoiced / completed sales. |
| Commandes à expédier | lengow_pending_sales | Imported sales waiting for shipment work. |
| Commandes avec statut différent | lengow_sales_issues | Status mismatches detected by the Lengow status update job. |
| Toutes les commandes | lengow_all_sales | Full account-scoped sales list. |
Mosaikasa account 17220 should be nested under Lengow and reuse the V3 submenus like account 5622. Retired V2 feed 113959 should not remain reachable from the menu.
Operational Commands
Run these locally or through cron only when you intend to contact Lengow. They call external APIs.
# Refresh credentials for one V3 account.
php bin/console menzzo:lengow:sales --refreshToken=1 --marketplace=5622
php bin/console menzzo:lengow:sales --refreshToken=1 --marketplace=6395
php bin/console menzzo:lengow:sales --refreshToken=1 --marketplace=17220
# Import waiting-shipment orders.
php bin/console menzzo:lengow:sales --marketplace=5622
php bin/console menzzo:lengow:sales --marketplace=6395
php bin/console menzzo:lengow:sales --marketplace=17220
# Replay from a specific date.
php bin/console menzzo:lengow:sales --marketplace=17220 --importFrom=2026-05-01
# Refresh status mismatch markers and send issue summary emails.
php bin/console menzzo:lengow:update-status
php bin/console menzzo:lengow:send-order-issues-alert
:::warning External systems The commands above call Lengow and can mutate local sales or send outbound action feedback. Do not run them against production or external services without explicit operational approval. :::
Retired V2 Feed
The legacy V2 importer is src/ErpBundle/Command/Lengow/V2/LengowSalesCommand.php and the V2 service is src/ErpBundle/Services/Lengow/V2/LengowService.php. Feed 113959 used the old XML endpoint and stored sales with source = LengowV2.
For current work, treat feed 113959 as retired:
- remove or keep removed the
menzzo:lengow:v2:sales --feedId=113959cron entry; - remove or keep removed
/erp/lengow/v2/all/113959from the menu; - keep historical documentation only for incident investigation on old
LengowV2sales.
Related Code
| Area | Path |
|---|---|
| V3 command | src/ErpBundle/Command/Lengow/V3/LengowSalesCommand.php |
| V3 service | src/ErpBundle/Services/Lengow/V3/LengowService.php |
| V3 status update | src/ErpBundle/Command/Lengow/V3/UpdateLengowStatusCommand.php |
| V3 issue email | src/ErpBundle/Command/Lengow/V3/LengowOrderIssueAlertCommand.php |
| Back-office menu | src/AppBundle/Menu/Builder.php |
| Back-office routes | src/ErpBundle/Controller/SaleController.php |
| Account parameters | app/config/parameters.yml.dist |
| Retired V2 importer | src/ErpBundle/Command/Lengow/V2/LengowSalesCommand.php |