VOOZH about

URL: https://deepwiki.com/gp247net/shop/2.3-multi-store-and-multi-vendor-architecture

⇱ Multi-Store and Multi-Vendor Architecture | gp247net/shop | DeepWiki


Loading...
Menu

Multi-Store and Multi-Vendor Architecture

Purpose and Scope

This document explains the multi-tenant architecture that enables GP247/Shop to support multiple stores and vendors within a single installation. It covers the hybrid data isolation strategy, store context resolution, automatic query filtering, and the distinction between root store (marketplace admin) and vendor store access patterns.

For information about basic product and category management, see Product Management System. For configuration-driven behavior, see Configuration-Driven System Behavior.


Architecture Overview

GP247/Shop implements a hybrid multi-tenant architecture that balances data isolation with catalog sharing. The system supports two operational modes:

ModePurposeInstallation Check
Multi-StoreMultiple independent stores sharing a codebasegp247_store_check_multi_store_installed()
Multi-Partner (Vendor)Marketplace with multiple vendorsgp247_store_check_multi_partner_installed()

The architecture uses three data isolation strategies:

  1. Direct Column Isolation: Transactional entities include a store_id column for hard isolation
  2. Junction Table Sharing: Catalog entities use many-to-many relationships to enable cross-store sharing
  3. Global Reference Data: Currencies, statuses, and configurations are shared across all stores

Multi-Tenant Architecture Overview


Sources: src/DB/migrations/00_00_00_create_tables_shop.php115 src/DB/migrations/00_00_00_create_tables_shop.php340 src/DB/migrations/00_00_00_create_tables_shop.php418-434


Store Context and Resolution

The system resolves the current store context differently for admin and frontend requests:

ContextSourceUsage
Admin Operationssession('adminStoreId')Filtering admin lists, CRUD operations
Frontend Operationsconfig('app.storeId')Product display, cart operations, orders
Root Store Checkconfig('app.storeId') == GP247_STORE_ID_ROOTDetermines if user has omniscient access

Store Context Resolution Flow


Admin Customer Filtering Example: The admin customer model filters by session store ID to show only customers belonging to the current store:

src/Admin/Models/AdminCustomer.php20-26


Sources: src/Admin/Models/AdminCustomer.php20-26 src/Admin/Models/AdminCustomer.php48-73


Data Isolation Strategy

Store-Scoped Entities

Entities with direct business relationships are isolated using a store_id column. These tables store data that should never be visible across stores:

TableColumn DefinitionPurpose
shop_orderuuid store_id (Line 115)Order belongs to specific store
shop_order_detailuuid store_id (Line 129)Line items isolated by store
shop_customeruuid store_id (Line 340)Customer accounts per store
shop_shoppingcartuuid store_id (Line 316)Cart sessions per store
shop_supplieruuid store_id (Line 382)Vendor/supplier per store

Store-Scoped Entity Schema


Sources: src/DB/migrations/00_00_00_create_tables_shop.php78-117 src/DB/migrations/00_00_00_create_tables_shop.php120-138 src/DB/migrations/00_00_00_create_tables_shop.php321-348 src/DB/migrations/00_00_00_create_tables_shop.php371-386

Shared Catalog Entities

Products and categories are designed to be shared across stores using junction tables. This enables:

  • Marketplace scenarios where products are listed in multiple stores
  • Centralized catalog management
  • Vendor products visible in root store
Core TableJunction TableRelationship Type
shop_productshop_product_storeMany-to-Many
shop_categoryshop_category_storeMany-to-Many

Shared Catalog Schema


Product-Store Relationship Definition: src/Models/ShopProduct.php58-61


Category-Store Relationship Definition: src/Models/ShopCategory.php27-30


Sources: src/DB/migrations/00_00_00_create_tables_shop.php418-434 src/Models/ShopProduct.php58-61 src/Models/ShopCategory.php27-30

Reference Data

The following tables are shared globally across all stores without any isolation:

  • shop_currency - Currency definitions and exchange rates
  • shop_order_status - Order status workflow states
  • shop_payment_status - Payment status options
  • shop_shipping_status - Shipping status options
  • shop_tax - Tax rate definitions
  • shop_brand - Product brands
  • shop_attribute_group - Product attribute definitions

Sources: src/DB/migrations/00_00_00_create_tables_shop.php61-75 src/DB/migrations/00_00_00_create_tables_shop.php154-160 src/DB/migrations/00_00_00_create_tables_shop.php389-396


Query Filtering Mechanisms

The system automatically applies store filtering in model query builders based on the multi-store/multi-partner installation status and current store context.

Product Query Filtering

The ShopProduct::buildQuery() method implements a sophisticated two-stage filtering approach:

Product Query Filtering Flow


Store Filtering Logic in Product Query: src/Models/ShopProduct.php714-741

The method checks for multi-store or multi-partner installations and conditionally joins the junction tables:


Key Points:

  • Uses a subquery to get distinct product IDs first (prevents duplicates from joins)
  • Joins shop_product_store to check store associations
  • Joins admin_store to verify store is active (status = 1)
  • Applies store filtering only if:
    • Multi-store mode is active, OR
    • Multi-partner mode is active AND store is not root

Sources: src/Models/ShopProduct.php703-868

Category Query Filtering

The ShopCategory::buildQuery() method applies similar filtering for categories:

Category Store Filtering: src/Models/ShopCategory.php231-238


Category Detail Retrieval with Store Filtering: src/Models/ShopCategory.php138-145


Sources: src/Models/ShopCategory.php213-282 src/Models/ShopCategory.php126-156

Customer Query Filtering

Customer queries in the admin interface filter by session store ID:

src/Admin/Models/AdminCustomer.php48-73


Sources: src/Admin/Models/AdminCustomer.php48-73


Root Store vs Vendor Store Access

The system differentiates between root store (marketplace admin) and vendor stores using the GP247_STORE_ID_ROOT constant:

Store TypeStore IDAccess LevelQuery Behavior
Root StoreGP247_STORE_ID_ROOTOmniscient - sees all storesNo store filtering in queries
Vendor StoreAny other UUIDRestricted - sees own store onlyStrict store_id filtering

Access Control Flow


Root Store Check in Product Details: src/Models/ShopProduct.php207-211


Multi-Partner Store Filtering Logic: src/Models/ShopProduct.php719-729


Vendor Display on Product Pages: src/Models/ShopProduct.php922-938

The displayVendor() method shows vendor information only in multi-partner mode and only when viewing from the root store:


Sources: src/Models/ShopProduct.php207-234 src/Models/ShopProduct.php922-938


Admin Interface Integration

The admin interface provides UI elements for managing store associations when multi-store mode is detected:

Category Store Selection

Admin Category List Store Column: src/Admin/Controllers/AdminCategoryController.php49-51


Category Create/Edit Store Selection UI: src/Views/admin/screen/category.blade.php137-177

The Blade template conditionally displays a multi-select dropdown for store assignment:


Store Association Persistence

Category Store Attachment on Create: src/Admin/Controllers/AdminCategoryController.php242-249


Category Store Update on Edit: src/Admin/Controllers/AdminCategoryController.php355-362


Sources: src/Admin/Controllers/AdminCategoryController.php49-51 src/Admin/Controllers/AdminCategoryController.php242-249 src/Admin/Controllers/AdminCategoryController.php355-362 src/Views/admin/screen/category.blade.php137-177


Code Integration Points

Helper Functions

The system relies on several helper functions to check multi-tenant modes:

FunctionReturn TypePurpose
gp247_store_check_multi_store_installed()booleanCheck if multi-store mode is active
gp247_store_check_multi_partner_installed()booleanCheck if multi-partner (vendor) mode is active
gp247_store_get_list_code()arrayGet list of all store codes
gp247_get_list_store_of_category()collectionGet stores associated with categories
gp247_store_get_domain_from_code()stringGet domain from store code

Constants

ConstantValue TypePurpose
GP247_STORE_ID_ROOTUUIDIdentifies the root/marketplace store

Sample Data Generation

The sample data command demonstrates how to create multi-store associations:

Category Store Association: src/Commands/ShopSample.php426-429


Product Store Association: src/Commands/ShopSample.php610-613


Sources: src/Commands/ShopSample.php426-429 src/Commands/ShopSample.php610-613

Frontend Vendor Display

The frontend can display vendor information when viewing products in marketplace mode:

src/Views/front/common/shop_display_store.blade.php1-3


Sources: src/Views/front/common/shop_display_store.blade.php1-3


Summary Table: Multi-Tenant Architecture Patterns

AspectImplementationKey Files
Store ContextSession for admin, config for frontendAll model files
Transactional IsolationDirect store_id columnOrders, customers, cart tables
Catalog SharingJunction tables (many-to-many)shop_product_store, shop_category_store
Query FilteringConditional joins in buildQuery()ShopProduct.php, ShopCategory.php
Access ControlRoot store check with GP247_STORE_ID_ROOTProduct and category models
Admin UIConditional store selectorsCategory/product admin views
Frontend DisplayVendor information displayshop_display_store.blade.php

This architecture provides flexibility for both independent multi-store setups and marketplace scenarios where vendors share a common platform while maintaining data isolation where needed.