Files
orderPRO/DOCS/plans/2026-02-27-per-integration-product-content-design.md
2026-02-27 21:43:15 +01:00

3.3 KiB

Design: Per-Integration Product Content

Date: 2026-02-27 Status: Approved

Summary

Products need separate name, short_description, and description for each integration. Global values in product_translations remain the fallback. Integration-specific overrides are stored in a new table.

Model

Global + override per integration:

  • product_translations stays as the global/base content (unchanged)
  • New table product_integration_translations stores per-integration overrides
  • NULL field = use global value
  • When exporting to a specific integration, prefer integration-specific content, fall back to global

Database

New migration file: 20260227_000014_create_product_integration_translations.sql

CREATE TABLE product_integration_translations (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    product_id INT UNSIGNED NOT NULL,
    integration_id INT UNSIGNED NOT NULL,
    name VARCHAR(255) NULL,
    short_description TEXT NULL,
    description LONGTEXT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY pit_product_integration_unique (product_id, integration_id),
    CONSTRAINT pit_product_fk FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE,
    CONSTRAINT pit_integration_fk FOREIGN KEY (integration_id) REFERENCES integrations(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Data migration: For all products currently linked to the "marianek.pl" integration via product_channel_map, copy name, short_description, description from product_translations to product_integration_translations.

Import Flow

In SettingsController::importExternalProductById:

  1. Save to product_translations as now (global, unchanged)
  2. Additionally upsert name, short_description, description to product_integration_translations for the current integration_id

Repository

New methods in ProductRepository:

  • findIntegrationTranslations(int $productId): array — returns all per-integration translation rows for a product
  • upsertIntegrationTranslation(int $productId, int $integrationId, string|null $name, string|null $shortDescription, string|null $description): void

Edit UI

In products/edit.php, the Name/Short description/Description section gets tabs at the top:

[ Globalna ] [ marianek.pl ] [ inny sklep... ]
  • Each tab shows: Nazwa, Krótki opis, Opis (WYSIWYG with Quill)
  • "Globalna" tab = existing global fields (name, short_description, description)
  • Integration tabs = per-integration overrides (integration_content[{id}][name], etc.)
  • Rest of the form (prices, SKU, images, meta) is global — no tabs

Controller Changes

ProductsController:

  • edit action: load active integrations + findIntegrationTranslations($id), pass to view
  • update action: process integration_content[{id}] array, call upsertIntegrationTranslation for each

Existing Products Migration

One-off SQL script assigns existing product content to "marianek.pl" integration. All products in product_channel_map linked to the marianek.pl integration get their current product_translations content copied to product_integration_translations.