Skip to content

Meduse product editing and spreadsheet updates ​

This guide follows product edits from the Vue product grid through the Laravel request and job, into raw_values and the flat catalog, then to the source-visible export handoff. It documents the pinned code paths; it does not establish deployed configuration or live processing. For the screen and endpoint inventory, see the frontend interface map, backend request flow, and integration workflows.

Choose the editing path ​

The active product grid is Products2.vue. Its visible Export action calls PrimeVue's local exportCSV() method. The import control beside it is commented out, so this screen does not upload a CSV or XLSX file. “Excel-like” describes an editable grid and a bulk API save, not a spreadsheet file import.

NeedScreen action and requestWhat the request means
Edit attributes for selected products in the spreadsheet-like gridSelect product rows, open Modifier, choose a channel, edit allowed cells, then save. The page first posts {channel, product_id, attrs} to /api/get-products-info-excel; it saves changed rows to /api/bulk-update-products-excel with {likeExcel: true, data, channel_code}.The backend consumes data and channel_code and creates an UpdateProductsExcel job. The likeExcel flag is present in the Vue payload; the controller and job do not branch on it in this revision. Grid load/save · service actions
Apply a small set of attributes to selected productsUse the separate bulk-attribute dialog. It posts {product_ids, attributes, channel_code} to /api/bulk-update-products; each attribute contains a code, value, and channel code. The dialog adds category-level values to the request.This creates an UpdateProducts job. It is a different payload and backend path from the spreadsheet-like grid. Payload construction · request mapping
Edit names and descriptions by localeUse the names/descriptions dialog. It shows tabs for active locale codes and posts locale maps plus selected product IDs to /api/bulk-update-products-names.This payload matches the controller and creates an UpdateProductsNames job. A separate inline name action posts productsData, but this controller reads productsNameData, productsDescriptionData, and selectedProduct; that inline payload does not match the backend contract in this revision, so persistence through that action is not established. Do not treat the spreadsheet editor's channel dropdown as an explicit locale-tab selector. Locale tabs · dialog payload · inline payload · request mapping

When the spreadsheet editor opens, the Vue page locks the selected product IDs, requests the selected rows and attributes for the chosen channel, and refreshes lock state every five seconds. The editor has client-side restrictions for locked rows and some fields based on the product family. Those controls describe the UI; confirm any authorization or validation requirement in the server path. If no cells changed, the page cancels the edit and shows a warning without posting a save request. Editor initialization and lock refresh · edit guards

Spreadsheet save path ​

View diagram source
sequenceDiagram
    actor U as Catalog editor
    participant V as Products2.vue
    participant A as Meduse API
    participant J as UpdateProductsExcel
    participant C as CatalogProduct and flat catalog
    participant E as ExportProducts event listener
    participant F as Menzzo export feed
    participant X as Downstream consumer
    U->>V: Select rows, choose channel, edit cells
    V->>A: POST get-products-info-excel
    A-->>V: Selected product and attribute values
    U->>V: Save changed rows
    V->>A: POST bulk-update-products-excel
    A->>J: Push processing job and return tracked job ID
    J->>C: Update raw_values and synchronize flat rows
    J->>E: Emit ExportProductsEvent after successful job work
    E->>F: Dispatch Menzzo ExportProducts on export-products
    F->>F: Build JSONL and upload to configured FTP pending path
    Note over F,X: Consumer acknowledgement and final catalog/storefront state are outside the supplied source

Diagram

The active route maps POST /api/bulk-update-products-excel to CatalogProductController::bulkUpdateProductsExcel. The controller takes data and channel_code (defaulting to fr_FR if the latter is absent), pushes UpdateProductsExcel to the named processing queue, notifies the user, and returns a tracked job ID. A successful HTTP response means the request handler returned; it is not by itself proof that the job, feed, or downstream consumer completed. Route · controller

Queue timing depends on runtime configuration. The source default is sync, which runs pushed jobs inline; QUEUE_CONNECTION can select a deferred driver that needs a worker. The deployed value was not inspected. Queue default

Channel, locale, and catalog storage ​

The spreadsheet save sends the selected channel code as channel_code. The job loads the channel and the catalog's scopable-attribute codes and locale codes. For each edited attribute, the code applies these rules:

Existing attribute state in raw_valuesWrite behavior in this job
Attribute is marked scopable, or already has a value under the selected channel codeWrite the edited value under raw_values[attribute][channel_code]. A prior <all_channels> fallback is removed for this per-channel write.
Attribute contains one or more keys that match codes in catalog_localeRemove a stale <all_channels> fallback and do not recreate a shared fallback. For an edited value to be written as a channel entry, the selected channel must be the existing key or the attribute must be scopable.
Attribute has neither a scoped channel slot nor a known locale keyWrite the shared value under raw_values[attribute][<all_channels>].

The locale check uses existing raw-value keys and the catalog_locale table; it is not a separate locale choice in the spreadsheet request. This matters for localized fields: use a selected channel key that matches the intended existing locale slot, or use the names/descriptions dialog when the task is explicitly to edit the locale tabs. The backend's dcos/update-products-excel-all-channels.md describes the same current fallback-removal logic. Its root-cause section describes the earlier behavior, and its verification section is a proposed check, not evidence that a live or non-production regression test ran. Scope and locale decision · write intent · second write pass

Before writing, the job converts select values represented as option codes or IDs into stored values, reduces multi-select arrays to comma-separated codes or IDs, normalizes boolean wrappers, and parses date values in d/m/Y H:i:s form. It skips the image, id, and $id fields in its generic attribute pass. is_enabled and family_id are handled as direct columns on catalog_product and catalog_product_flat; remaining recognized catalog attributes are stored in the product's JSON raw_values and then mapped into the flat row. Value conversion and direct columns

Saving the CatalogProduct model records version changes and synchronizes its flat data through the model update hook. The job also calls CatalogProductFlat::syncProductFlatData after saving. These are Meduse-side persistence steps; they do not prove that an external catalog has accepted the update. Model update hook · flat synchronization

After successful Excel-job work, Meduse emits ExportProductsEvent. The Menzzo and MeublePromo module providers both declare listeners that dispatch their ExportProducts jobs. The Menzzo exporter requires an enabled connector, a product resource, and a usable sync cursor before it writes JSONL and uploads it to its configured FTP destination. A finished exporter job is an upload-level signal; the supplied code does not include the receiving consumer's acknowledgement. The diagram shows the Menzzo branch only. Menzzo listener · MeublePromo listener · export preconditions and JSONL creation · FTP upload

Errors and job polling ​

The Vue page shows a warning and sends no request when there are no changed rows. For a save request, it shows a success or error toast based on the response. In the backend, the Excel endpoint accepts a generic request rather than a dedicated request validator; the job wraps its work in a Throwable catch and calls the queue failure handler if processing throws. Check the tracked job record to distinguish a completed job from a failed or still-running one. Vue save response handling · job failure handling

The product page polls /api/has-job every ten seconds. That endpoint only reports whether UpdateProductsExcel jobs are in started, queued, or retrying states. A false value means there is no job in those active states; it does not distinguish success from failure or prove that an export was consumed. Open the job in Processus or inspect its tracked-job record for status, timestamps, and output. UI poll · status endpoints · tracked-job response

Non-production validation journey ​

Run this only in an isolated development or test environment with a disposable product and a test connector. This journey was not executed as part of this source review.

  1. Prepare a disposable product whose family permits editing the chosen fields. Seed its name with the intended locale key, a second locale key, and a stale <all_channels> fallback. Include one non-scopable test attribute without locale keys. Record the starting raw_values and flat row.
  2. In the Meduse product grid, select that product, open Modifier, choose the channel code matching the intended locale key, and edit the name plus the non-scopable test attribute. Save once and capture the returned tracked job ID.
  3. Follow the job in Processus or by its tracked-job record until it has a final status. Do not treat the save toast or /api/has-job becoming false as the final result.
  4. Read back the same product from the non-production database. Confirm the selected locale value changed, the other locale stayed the same, the stale fallback was removed, and the non-scopable field is under <all_channels>. Confirm the flat row reflects the resulting catalog values.
  5. If the test connector is enabled, inspect the corresponding non-production export handoff and then confirm the test consumer's acknowledgement and final readback. If the evidence stops at job completion, flat-row sync, or FTP upload, report exactly that boundary and leave downstream acceptance unclaimed.

Evidence limits ​

The backend paths above were read from axelites/menzzo-meduse commit 5d3de6cb63b976aaeef739a8a7f288c4b46509ad with git show; the supplied frontend files were verified against the requested pinned tree. This page is marked partial because the deployed queue/configuration, database outcome, export runtime, and downstream acceptance remain unverified. No application commands, API calls, database reads, browser journey, queue-worker inspection, FTP check, or downstream consumer validation were performed. The Menzzo module source dispatches an export job that writes a JSONL feed and uploads it to its configured pending path; the external consumer's acknowledgement and customer-visible result are outside the supplied source. See integration workflows for the wider export boundary.

Internal developer documentation for Menzzo systems.