Appearance
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.
| Need | Screen action and request | What the request means |
|---|---|---|
| Edit attributes for selected products in the spreadsheet-like grid | Select 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 products | Use 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 locale | Use 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
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_values | Write behavior in this job |
|---|---|
| Attribute is marked scopable, or already has a value under the selected channel code | Write 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_locale | Remove 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 key | Write 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.
- Prepare a disposable product whose family permits editing the chosen fields. Seed its
namewith 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 startingraw_valuesand flat row. - 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. - 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-jobbecoming false as the final result. - 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. - 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.