Skip to content

Shelf Code Management

Flow ID: AD-51 | Module(s): eshop | Complexity: Medium Last Updated: 2026-05-12

Business Context

Shelf code management provides CRUD operations for warehouse shelf/location codes. Each product can be assigned a shelf code that indicates its physical location in the warehouse, enabling faster order picking and inventory management. This is primarily used by businesses with physical warehouse operations (e.g., pharmaceutical distributors, large e-commerce warehouses).

The admin interface at /eshop/shelfcodes_admin.htm is a simple form-based CRUD for creating, editing, and deleting shelf code entries. Products reference shelf codes via a plain non-unique shelfcode_id foreign key (no DB-level FK constraint) and the shelf label is surfaced throughout the order picking pipeline -- order detail, packing slips, build summaries, and customer order history -- so warehouse staff can locate each line item.

A complementary barcode-wedge / mobile scanner workflow (Scanaccess) lets warehouse operators scan a product barcode to immediately land on a single-page form for adjusting the product's shelf code, base price, and stock without navigating the full product admin.


API Reference

REST Endpoints

MethodEndpointActionsAuthRoles
GET/rest/product/shelfcodeindex, item, showBackendADMIN, PRODUCTS
POST/rest/product/shelfcodestore, updateBackendADMIN, PRODUCTS
DELETE/rest/product/shelfcodedestroyBackendADMIN, PRODUCTS

Read routes registered in application/config/rest_routes.php:352-357, write routes in application/config/rest_routes.php:1541-1546. RBAC defaults in application/config/rest_policies.php:518.

Legacy Admin Routes

RouteControllerMethodHTTPDescription
eshop/shelfcodes_adminAdv_shelfcodes_adminindex()GETList all shelf codes
eshop/shelfcodes_admin/addAdv_shelfcodes_adminadd()GET/POSTCreate shelf code form
eshop/shelfcodes_admin/edit/{id}Adv_shelfcodes_adminedit($id)GET/POSTEdit shelf code form
eshop/shelfcodes_admin/delete/{id}Adv_shelfcodes_admindelete($id)GETDelete a shelf code (soft-dereferences products first)

Route definitions at application/config/routes.php:374-377 (default + locale-prefixed variants).

Barcode Scanner Routes

RouteControllerMethodHTTPDescription
scanaccessScanaccessindex()GETFull-screen autofocused barcode input
scanaccess/setupScanaccesssetup()POSTLook up product by scanned ID and render edit form
scanaccess/updateScanaccessupdate()POSTCommit shelf code / price update

Registered at application/config/routes.php:124-127.


Code Flow

Admin CRUD

Adv_shelfcodes_admin::add() / edit($id)
  |
  +--> GET: render form view (create.php / update.php)
  +--> POST submit -> $this->validation() at Adv_shelfcodes_admin.php:105-108
  |     |-- single rule: set_rules('shelfcode_value', ..., 'trim|numeric')
  |
  +--> Build $data = ['code' => $post['shelfcode_value']]
  +--> shelfcodes_model->add_record($data) | edit_record($id, $data)
  +--> afterAdd($id) / afterEdit($id) hook (empty stub, lines 110-123)
  +--> set_userdata('eshop_success', ...)
  \--> redirect('eshop/shelfcodes_admin')

Controller methods live at ecommercen/eshop/controllers/Adv_shelfcodes_admin.php:35-103. RBAC enforced in the constructor at lines 17-33: [AUTH_ROLE_ADVISABLE, AUTH_ROLE_ADMIN, AUTH_ROLE_PRODUCTS].

Soft-Dereference Delete (legacy)

php
// ecommercen/eshop/models/Adv_shelfcodes_model.php:113-118
function delete_record($id) {
    $this->db->update($this->tableProduct, ['shelfcode_id' => null], ['shelfcode_id' => $id]);
    $this->db->delete($this->table, ['id' => $id]);
    $this->session->set_userdata('eshop_success', t('eshop.admin.success.entrydelete'));
}

The legacy delete always succeeds: every shop_product.shelfcode_id that references the deleted shelf is first NULLed, then the shelf row is removed. There is no confirmation dialog, no blocking if products still reference the shelf, and no count of affected products shown to the admin.

Product Admin Integration

The product admin controller Adv_products_admin.php wires shelf codes into create/edit/clone/ERP-import forms and the list-view filter/batch action surface:

  • Model loaded in constructor at line 32.
  • List filter: multiselect shelves filter populated via shelfcodes_model->getCombo() at line 147, rendered in application/views/admin/products/list.php:194-200.
  • Form integration via shelfcodes_combo render variable at lines 689, 749, 806, and 1815. Consumed by:
    • application/views/admin/products/create.php:583-589
    • application/views/admin/products/update.php:749-762
    • application/views/admin/products/clone.php:662-673
    • application/views/admin/products/add_erp_product.php:571-577
    • application/views/admin/products/new_products_create.php:343-349
  • Save logic defaults shelfcode_id to null (line 392) and sets it from posted shelfcode_value only if non-empty (lines 411-413).
  • Product-level validation: set_rules('shelfcode_value', 'Shelfcode', 'trim') at line 959 -- note this drops the numeric constraint that the shelf codes admin enforces.
  • Batch action alter_shelfcode: handler at line 1095, submit at 1583-1587. Calls batchMasterUpdate($products, ['shelfcode_id' => ..., 'date_changed' => ...]). Hook afterBatchActionSubmitAlterShelfCode at line 2066. UI in application/views/admin/products/list.php:549-551 and batch_update.php:312-315.
  • Search filter: Adv_product_model::get_records() accepts a shelves condition and applies WHERE shop_product.shelfcode_id IN (...) at Adv_product_model.php:2180-2182.

Modern Domain Layer

A full Domain + REST layer was added in 4.99.0 (see docs/changelog/Changelog.4.99.md:769-774). It lives under src/Domains/Product/Shelfcode/ and src/Rest/Product/.

Domain Files

FileRoleNotes
src/Domains/Product/Shelfcode/Repository/Entity.phpEntityFields: int $id, ?string $code
src/Domains/Product/Shelfcode/Repository/Repository.phpRead repositorytable = 'shop_product_shelfcodes'
src/Domains/Product/Shelfcode/Repository/RepositoryConfigurator.phpRelations configgetRelations(): array { return []; } -- no relations
src/Domains/Product/Shelfcode/Repository/WriteRepository.phpWrite repositoryExtends BaseWriteRepository, primary key id; adds nullProductReferences() at lines 18-23
src/Domains/Product/Shelfcode/Service.phpRead serviceall(), item(), get()
src/Domains/Product/Shelfcode/WriteService.phpWrite servicecreate(), update(), delete() (lines 47-54; transactional soft-dereference)
src/Domains/Product/Shelfcode/WriteData.phpWrite DTOSingle ?string $code field, OpenAPI schema name Shelfcode
src/Domains/Product/Shelfcode/Validator.phpValidatorEmpty stub -- no length / format / uniqueness rules
src/Domains/Product/Shelfcode/ListRequest.phpList filter specFilters id (Exact), code (Partial); sorts id, code. Comment explicitly notes "Shelfcode does not have MUI translations."

Modern Delete Behavior

php
// src/Domains/Product/Shelfcode/WriteService.php:47-54
public function delete(int|string $id): bool {
    return (bool) $this->writeRepository->transactional(function () use ($id) {
        $this->writeRepository->nullProductReferences($id);
        return $this->writeRepository->delete($id);
    });
}
php
// src/Domains/Product/Shelfcode/Repository/WriteRepository.php:18-23
public function nullProductReferences(int|string $id): void {
    $this->db
        ->where('shelfcode_id', $id)
        ->update('shop_product', ['shelfcode_id' => null]);
}

The modern write service now mirrors the legacy soft-dereference: nullProductReferences() NULLs every shop_product.shelfcode_id that references the deleted shelf before removing the shelf row. In addition, both operations are wrapped in transactional(), making the modern path atomically safer than the legacy delete_record(), which issues the two statements without a transaction (ecommercen/eshop/models/Adv_shelfcodes_model.php:113-118).

REST Layer

FileRole
src/Rest/Product/Controllers/Shelfcode.phpREST controller (lines 1-150). Extends HandlesRestfulActions, uses HandlesWriteActions. Methods: index, show, item, store, update, destroy. Full OpenAPI annotations.
src/Rest/Product/Resources/Shelfcode/Resource.phpResource transformer. OpenAPI schema ProductShelfcodeResource. Fields: id, code.
src/Rest/Product/Resources/Shelfcode/Collection.phpCollection wrapper. OpenAPI schema ProductShelfcodeCollection.

Product Relation

The modern Product domain declares shelf code as a BELONGS_TO relation:

php
// src/Domains/Product/Product/Repository/RepositoryConfigurator.php:26
'shelfcode' => new Relation(Relation::BELONGS_TO, ShelfcodeRepository::class, 'shelfcode_id'),
  • src/Domains/Product/Product/Repository/Entity.php:11 declares ?int $shelfcode_id.
  • src/Domains/Product/Product/WriteData.php:12, 58, 99, 140 accepts shelfcodeId on create / update.
  • src/Rest/Product/Resources/Product/Resource.php:79-80 exposes shelfcodeId only when $this->context?->isBackend() is true -- this field is backend-only on the Product REST resource (see docs/changelog/Changelog.4.99.md:95-96).
  • Lines 46 and 106 of the Product resource expose an optional embedded shelfcode relation. The OA schema name referenced there does not match the actual class declaration (see Known Issues #10).

DI Registration

  • Domain: src/Domains/Product/container.php:318-324
  • REST: src/Rest/Product/container.php:242-247

Tests

FileScope
tests/Integration/Domains/Product/Shelfcode/RepositoryTest.phpIntegration -- repository
tests/Integration/Domains/Product/Shelfcode/ServiceTest.phpIntegration -- read service
tests/Unit/Domains/Product/Shelfcode/ServiceTest.phpUnit -- read service
tests/Unit/Rest/Product/Resources/Shelfcode/ResourceTest.phpUnit -- Resource transformer
tests/Unit/Rest/Product/Resources/Shelfcode/CollectionTest.phpUnit -- Collection transformer

Architecture

ComponentPathPurpose
Shelfcodes_admin (wrapper)application/modules/eshop/controllers/Shelfcodes_admin.php:1-13Empty client-override shim
Adv_shelfcodes_adminecommercen/eshop/controllers/Adv_shelfcodes_admin.php:1-124Legacy admin CRUD, extends Admin_c
Shelfcodes_model (wrapper)application/modules/eshop/models/Shelfcodes_model.php:1-7Empty client-override shim
Adv_shelfcodes_modelecommercen/eshop/models/Adv_shelfcodes_model.php:1-119Legacy model, extends Adv_base_model
Scanaccessapplication/controllers/Scanaccess.phpStandalone barcode scanner controller
Domain Entitysrc/Domains/Product/Shelfcode/Repository/Entity.phpModern entity
Domain Servicesrc/Domains/Product/Shelfcode/Service.phpModern read service
Domain WriteServicesrc/Domains/Product/Shelfcode/WriteService.phpModern write service
REST Controllersrc/Rest/Product/Controllers/Shelfcode.phpREST endpoints
Routesapplication/config/routes.php:374-377Legacy admin routes
REST routesapplication/config/rest_routes.php:352-357,1541-1546REST read + write routes
Admin menuapplication/config/admin_menu.php:570-576Menu registration

Legacy Model Method Inventory (Adv_shelfcodes_model.php)

MethodLinesPurpose
get_records($cond, $asrow)24-40List shelf codes with optional conditions
shelfcode_label($shelfcode_id)42-47Return the code string for a given PK
getCombo($emptyFirst = false)55-71Return [id => code] map for form_dropdown()
add_record($data)73-80Insert a shelf code
edit_record($id, $data)82-88Update a shelf code
product_shelfcode($productId)90-97Join product -> shelfcode, return shelfcode_id
productShelfCodeLabel($productId)99-111Join product -> shelfcode, return label string
delete_record($id)113-118Soft-dereference then delete

Deprecated Global Helper

ecommercen/helpers/eshop_helper.php:3-26 defines a global product_shelfcode($productId) function that delegates to productShelfCodeLabel(). It is marked @deprecated but is still called by four marketplace order-ingestion models (see Marketplace Order Imports).

Admin Menu

Registered in application/config/admin_menu.php:570-576 inside the PRODUCTS group with label "Shelves" and icon <i class="mdi mdi-server"></i>. Visible to roles [AUTH_ROLE_ADVISABLE, AUTH_ROLE_ADMIN, AUTH_ROLE_PRODUCTS].

Views

ViewPurpose
application/views/admin/shelfcodes/list.phpSimple table: ID, Code, Actions
application/views/admin/shelfcodes/create.phpSingle-field form (shelfcode_value)
application/views/admin/shelfcodes/update.phpSame form, pre-populated

Data Model

shop_product_shelfcodes Table

Defined in database/initial/initial.sql:1824-1829. No Phinx migration has ever altered the schema.

ColumnTypeNullDefaultDescription
idINT(10) AUTO_INCREMENTNo--Primary key
codeVARCHAR(255)Yes'0'Shelf code string. The DDL has no NOT NULL, so the column is technically nullable, but the default is the literal string "0" rather than NULL.

Indexes

  • PRIMARY KEY (id)
  • KEY code (code) -- plain non-unique index

No _mui table. Shelf codes have no translations by design (see comment in ListRequest.php).

Reference from shop_product

database/initial/initial.sql:1521-1574 declares:

  • shelfcode_id INT(11) DEFAULT NULL
  • KEY shelfcode_id (shelfcode_id) -- plain non-unique index
  • No FOREIGN KEY constraint. Referential integrity is maintained entirely in PHP (legacy soft-dereference on delete).

No other tables in the schema reference shop_product_shelfcodes.


Barcode Scanner Workflow

Scanaccess is a standalone controller for USB barcode-wedge / mobile scanner workflows. There is no AdvBarcodeScanner library and no label-printing infrastructure -- labels are assumed to be printed externally; Scanaccess only covers the scan-in / edit side.

Controller

application/controllers/Scanaccess.php extends Admin_c. It loads eshop/shelfcodes_model and eshop/product_model in the constructor. Notably it makes no allowRole call, so any logged-in admin role can use it -- see Known Issues & Security Gaps.

Actions

MethodLinesBehavior
index()22-25Renders scanaccess/scanview.php -- a minimal full-page autofocused text input named id with form action scanaccess/setup.
setup()27-51Looks up the product by ID, joins the current shelf code, passes $this->shelfcodes_model->get_combo() (Scanaccess.php:46) to application/views/scanaccess/setup.php. The snake_case call does not match the actual model method (see Known Issues #9).
update()53-72On POST upd, calls product_model->batchMasterUpdate([$productid], ['shelfcode_id' => $shelfcodeid, 'price' => $productPrice, 'date_changed' => date('Y-m-d H:i:s')]).

Views

  • application/views/scanaccess/scanview.php:1-50 -- single input barcodeInput; a JS onload handler auto-focuses it so a barcode-wedge scanner immediately submits.
  • application/views/scanaccess/setup.php:1-111 -- product image, name, ID, editable base price, shelf code dropdown, vendor code, and an "Αλλαξε στοκ" (change stock) section. A comment at line 50 notes // @TODO drop-old-attrs product code need fix for barcode reference -- barcode display is currently disabled.
  • application/views/scanaccess/update.php exists but is not touched by any action in the visited controller.

Flow Diagram

Scanner/operator
   |
   v
GET /scanaccess            -- scanview.php (autofocused input)
   |
   v
POST /scanaccess/setup     -- resolves product_id, loads shelfcode combo
   |                          and current shelfcode, renders setup.php
   v
POST /scanaccess/update    -- batchMasterUpdate: shelfcode_id, price, date_changed

Picking Workflow

Shelf codes surface at multiple points in the order fulfillment pipeline via joins in Adv_order_basket_model:

php
// ecommercen/eshop/models/Adv_order_basket_model.php:22
protected $tableShelfCodes = 'shop_product_shelfcodes';

Admin Order Detail (lines 381-411)

SELECT ... {$this->tableShelfCodes}.code AS shelf_code ... LEFT JOIN shop_product_shelfcodes ON shop_product_shelfcodes.id = shop_product.shelfcode_id -- joins the line-item product to its current shelf code for display on the admin order detail view.

Packing Slip (lines 470-500)

A similar SELECT with GROUP_CONCAT of barcodes, used by the logistics packing slip.

View Surface Points

ViewLineContext
application/views/admin/orders/update.php232Admin order detail -- label eshop.admin.shelfcode.shelfcode_label
application/views/admin/orders/build_summary.php28-30Order build summary partial
application/views/admin/orders/invoice_logistics.php13-15Logistics packing slip
application/views/admin/customers/order_history.php20Customer order history panel

Marketplace Order Imports

Marketplace order ingestion models snapshot the shelf code label at order time -- storing a string copy rather than a foreign key -- via the deprecated global product_shelfcode() helper:

FileLine
ecommercen/eshop/models/Adv_skroutz_orders_model.php565
ecommercen/eshop/models/Adv_shopflix_orders_model.php374
ecommercen/eshop/models/Adv_public_orders_model.php253
ecommercen/eshop/models/Adv_order_model.php1521

This snapshot approach means that if a shelf code is renamed or deleted after import, the label captured on the order line is preserved for that historical order.

Bug at Adv_orders_admin.php:1082-1085: the order admin stores 'product_shelfcode' => $item->product_id -- writing the product ID under the product_shelfcode key. This is a copy-paste error that corrupts the snapshot for any code path that flows through this branch. See Known Issues & Security Gaps.


Configuration

  • Legacy routes: application/config/routes.php:374-377 (default + locale-prefixed).
  • REST routes: application/config/rest_routes.php:352-357 (read), 1541-1546 (write).
  • Admin menu: application/config/admin_menu.php:570-576.
  • REST policies: application/config/rest_policies.php:518.
  • DI: src/Domains/Product/container.php:318-324, src/Rest/Product/container.php:242-247.
  • No environment variables. Shelf codes have no registry keys, no .env dependencies, and no integration toggles.

Required roles

  • Legacy admin CRUD + admin menu: [AUTH_ROLE_ADVISABLE, AUTH_ROLE_ADMIN, AUTH_ROLE_PRODUCTS]
  • REST API: [AUTH_ROLE_ADMIN, AUTH_ROLE_PRODUCTS]. ADVISABLE is intentionally not listed — application/config/rest_policies.php:33-34 documents that ADVISABLE is a superuser role that auto-bypasses every roles array via RequestContext::isSuperuser() (src/Rest/Middleware/AuthorizationMiddleware.php:70, src/Rest/Middleware/RequestContext.php:47-49). Effective access is identical to the legacy controller's allow-list.
  • Scanaccess: any logged-in admin role (no allowRole call)

Client Extension Points

  • Override admin controller: Create a same-named class in application/modules/eshop/controllers/Shelfcodes_admin.php (the empty wrapper at application/modules/eshop/controllers/Shelfcodes_admin.php:1-13 is where the override lives).
  • Override model: Extend Shelfcodes_model at application/modules/eshop/models/Shelfcodes_model.php.
  • Empty hook stubs in Adv_shelfcodes_admin.php:110-123 (afterAdd, afterEdit, afterDelete) are available for client overrides to attach side effects.
  • Override modern domain / REST: In client repos, register Custom\Domains\Product\Shelfcode\... classes and alias the upstream services via $services->alias(...) in custom/.../container.php.

Business Rules

  1. Optional assignment -- shop_product.shelfcode_id defaults to NULL; products do not require a shelf code.
  2. Legacy numeric-only enforcement -- the shelf codes admin form validates shelfcode_value with trim|numeric, forcing numeric codes in the UI even though the column is VARCHAR(255).
  3. Default code "0" on insert -- the column default is the literal string '0', so inserts that omit the code field materialize as shelf "0" rather than NULL.
  4. Both delete paths soft-dereference first -- legacy delete_record() (ecommercen/eshop/models/Adv_shelfcodes_model.php:113-118) NULLs every referencing shop_product.shelfcode_id then drops the row; modern WriteService::delete() (src/Domains/Product/Shelfcode/WriteService.php:47-54) does the same via WriteRepository::nullProductReferences() (src/Domains/Product/Shelfcode/Repository/WriteRepository.php:18-23). The modern path additionally wraps both operations in a transaction; the legacy path does not. Both always succeed with no confirmation, no blocking, and no count shown.
  5. Marketplace order snapshots -- importers store the shelf code label as a string on the order line, divorced from shelfcodes_id, so historical orders are stable against later shelf code renames.
  6. Backend-only on Product REST -- shelfcodeId on ProductResource is only exposed when the request context is backend (Resource.php:79-80), hiding warehouse location data from the storefront.
  7. No MUI, no feeds, no Solr -- shelf codes are not translated, not indexed, and not published externally.

Known Issues & Security Gaps

  1. Modern WriteService::delete() skips soft-dereference — RESOLVED. src/Domains/Product/Shelfcode/WriteService.php:47-54 now calls WriteRepository::nullProductReferences() (src/Domains/Product/Shelfcode/Repository/WriteRepository.php:18-23) inside a transactional() block before deleting the shelf row, matching legacy behavior and adding the bonus of atomic execution (the legacy path issues the two statements outside a transaction).
  2. No DB-level FK constraint -- shop_product.shelfcode_id has no FOREIGN KEY declaration, so orphans cannot be prevented at the database layer.
  3. Legacy trim|numeric validation vs VARCHAR(255) column -- the admin form forces numeric-only codes (Adv_shelfcodes_admin.php:107), but nothing at the DB or modern REST layer enforces this. Direct inserts or REST POSTs can store arbitrary strings.
  4. No uniqueness constraint -- neither the DB index nor the modern Validator.php enforces unique codes, so duplicates are allowed at every layer.
  5. Scanaccess has no allowRole check -- it extends Admin_c with no explicit role enforcement, meaning any logged-in admin role can adjust product shelf codes, base prices, and stock via the barcode scanner workflow.
  6. Default code value is literal '0' -- brand-new rows created without specifying code become shelf "0", which can collide with legitimate codes.
  7. RBAC divergence between layers — RESOLVED (closed as Advisable-com/ecommercen#54 — not-a-bug). Earlier read of rest_policies.php flagged the missing AUTH_ROLE_ADVISABLE in the shelfcode roles array as a divergence. It is not. ADVISABLE is a project-wide superuser role that auto-bypasses every roles array in REST middleware (src/Rest/Middleware/AuthorizationMiddleware.php:70, src/Rest/Middleware/RequestContext.php:47-49); the convention at rest_policies.php:33-34 is that ADVISABLE is never listed in roles arrays. Effective access on the REST endpoint matches the legacy controller's allow-list.
  8. Adv_orders_admin.php:1082-1085 copy-paste bug -- stores 'product_shelfcode' => $item->product_id, writing the product ID under the shelf code key. Affects any order data path that flows through this branch.
  9. Scanaccess::setup() snake_case method call mismatch -- application/controllers/Scanaccess.php:46 calls $this->shelfcodes_model->get_combo() (snake_case), but the actual model method is getCombo() (camelCase) at ecommercen/eshop/models/Adv_shelfcodes_model.php:55-71. No method named get_combo is declared on the model. The scanner workflow's shelf code dropdown is silently broken.
  10. OA schema name mismatch on Product relation -- src/Rest/Product/Resources/Product/Resource.php:46 references ShelfcodeResource in its OA annotation, but the actual Resource class at src/Rest/Product/Resources/Shelfcode/Resource.php declares its OA schema as ProductShelfcodeResource. The OpenAPI spec will contain a dangling $ref for the embedded shelfcode relation.

Edge Cases & Non-Integration

  • No marketplace feeds -- shelf codes are never published in marketplace XMLs. No references in src/Feeds/ or ecommercen/feeds/. See IN-01 Feed Generation.
  • No Solr indexing -- no references in ecommercen/search/; shelves cannot be used as a storefront facet.
  • No multi-language support -- no *_mui table exists, and ListRequest.php explicitly documents this ("Shelfcode does not have MUI translations").
  • No audit trail -- the legacy model does not write to any history / journal table; edits and deletes leave no record.
  • No batch import -- there is no CSV / Excel / ERP import path dedicated to shelf codes; they can only be created one at a time via the legacy admin form, the REST store endpoint, or via the product admin when a new code is typed into shelfcode_value.

Changelog Highlights

  • docs/changelog/Changelog.4.99.md:769-774 -- Shelfcode Domain + REST layer introduced in 4.99.0.
  • docs/changelog/Changelog.4.99.md:95-96 -- shelfcodeId on Product REST resource restricted to backend context.
  • docs/changelog/Changelog.4.99.md:322-323 -- removal of unused $tableShelfCodes property (legacy cleanup).

  • AD-02 Product Management Admin -- products are assigned a shelf code via the create/edit/clone/ERP-import forms, the shelves list filter, and the alter_shelfcode batch action.
  • AD-03 Order Management Admin -- shelf codes surface on admin order detail, build summary, and logistics packing slip views during picking.
  • IN-01 Feed Generation -- shelf codes are intentionally not included in marketplace feeds.