diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index e2b67ba..16f505c 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -17,6 +17,7 @@ function loadSidebar(project: string): DefaultTheme.SidebarItem[] { } const projects = [ + { slug: 'akeneo-migration', label: 'Akeneo Migration' }, // { slug: 'ai-product-feed-openai', label: 'AI Product Feed (OpenAI)' }, { slug: 'auto-sku-generator', label: 'Auto SKU Generator' }, { slug: 'aws-integration', label: 'AWS Integration' }, diff --git a/docs/akeneo-migration/assets/connection/create-form.png b/docs/akeneo-migration/assets/connection/create-form.png new file mode 100644 index 0000000..2dcbc83 Binary files /dev/null and b/docs/akeneo-migration/assets/connection/create-form.png differ diff --git a/docs/akeneo-migration/assets/connection/edit-page.png b/docs/akeneo-migration/assets/connection/edit-page.png new file mode 100644 index 0000000..67bbb4c Binary files /dev/null and b/docs/akeneo-migration/assets/connection/edit-page.png differ diff --git a/docs/akeneo-migration/assets/migration/job-tracker.png b/docs/akeneo-migration/assets/migration/job-tracker.png new file mode 100644 index 0000000..a86fca6 Binary files /dev/null and b/docs/akeneo-migration/assets/migration/job-tracker.png differ diff --git a/docs/akeneo-migration/assets/migration/select-entities.png b/docs/akeneo-migration/assets/migration/select-entities.png new file mode 100644 index 0000000..68d9529 Binary files /dev/null and b/docs/akeneo-migration/assets/migration/select-entities.png differ diff --git a/docs/akeneo-migration/assets/overview/hero-banner.png b/docs/akeneo-migration/assets/overview/hero-banner.png new file mode 100644 index 0000000..f095082 Binary files /dev/null and b/docs/akeneo-migration/assets/overview/hero-banner.png differ diff --git a/docs/akeneo-migration/assets/overview/package-view.png b/docs/akeneo-migration/assets/overview/package-view.png new file mode 100644 index 0000000..16013e7 Binary files /dev/null and b/docs/akeneo-migration/assets/overview/package-view.png differ diff --git a/docs/akeneo-migration/assets/permissions/acl.png b/docs/akeneo-migration/assets/permissions/acl.png new file mode 100644 index 0000000..fd9df78 Binary files /dev/null and b/docs/akeneo-migration/assets/permissions/acl.png differ diff --git a/docs/akeneo-migration/contact-support.md b/docs/akeneo-migration/contact-support.md new file mode 100644 index 0000000..0c3992a --- /dev/null +++ b/docs/akeneo-migration/contact-support.md @@ -0,0 +1,3 @@ +# Support + +For any questions, reach out to us at [support@webkul.com](mailto:support@webkul.com) or raise a ticket through our [HelpDesk System](https://webkul.uvdesk.com/en/). diff --git a/docs/akeneo-migration/create-connection.md b/docs/akeneo-migration/create-connection.md new file mode 100644 index 0000000..1be67e0 --- /dev/null +++ b/docs/akeneo-migration/create-connection.md @@ -0,0 +1,71 @@ +# Create & Test a Connection + +A **connection** holds the Akeneo REST API credentials the plugin uses to read your catalog. Every connection is **validated live against Akeneo before it is saved**, so you never store credentials that don't work. + +## Open the Connections List + +In the admin sidebar, open **Akeneo Migration → Connections**. This lists every connection you have created, with its name, base URL, username, and status (**Enabled** / **Disabled**). Click **Create Connection** to add a new one. + +## Enter the Connection Details + +Fill in your Akeneo REST API (Connection) credentials: + +| Field | Description | +|-------|-------------| +| **Akeneo Base URL** | The URL of your Akeneo instance — for example, `https://your-instance.cloud`. Must be a valid URL. | +| **Client ID** | The Client ID from your Akeneo API connection. | +| **Secret** | The Secret from your Akeneo API connection. | +| **Username** | The Akeneo API user's username. | +| **Password** | The Akeneo API user's password. | + +
+ +
+ Create Connection form +
+ +
+ +> [!TIP] +> On create, the connection is **enabled** automatically and **named from its base URL**. You can rename it later from the connection's edit page. + +> [!NOTE] +> You will need an Akeneo account with REST API (Connection) credentials. In Akeneo, these are created under **Connect → Connection settings**, which provides the Client ID, Secret, username, and password used here. + +## Test & Save + +When you save, the plugin tests the credentials against Akeneo. If they are valid, the connection is created and you land straight on its **edit page**. + +If the test fails, the connection is **not** saved and a clear reason is shown so you can fix it: + +| Message | What it means | +|---------|---------------| +| **The Akeneo API was not found at this Base URL** | The Base URL is wrong or does not point to your Akeneo instance. Check it (for example, `https://your-instance.cloud`). | +| **Authentication was rejected** | One or more of the Client ID, Secret, Username, or Password is incorrect. | +| **Access was denied by Akeneo** | The API user does not have permission to use the API — check its roles and permissions in Akeneo. | +| **Akeneo rejected the request** | Review the connection details and try again. | +| **Akeneo returned a server error** | A temporary problem on the Akeneo side — try again in a few moments. | +| **Could not reach the Akeneo server** | The Base URL is wrong, or the server is offline or unreachable from this network. | + +## Edit a Connection + +From a connection's edit page you can rename it, update its details, and enable or disable it. The edit page has three tabs: + +- **Connection** — the connection details and the **Run a Migration** controls. +- **History** — field-level changes made to this connection over time. +- **Migration History** — every migration run started from this connection. + +
+ +
+ Connection edit page +
+ +
+ +> [!NOTE] +> For security, the stored **Secret** and **Password** are never shown in plain text — on edit they appear as a masked length. Leave them blank to keep the stored value, or type a new value to replace it. + +## Next Steps + +With a working connection in place, you can now [run a migration](./run-migration). diff --git a/docs/akeneo-migration/index.md b/docs/akeneo-migration/index.md new file mode 100644 index 0000000..38a3aec --- /dev/null +++ b/docs/akeneo-migration/index.md @@ -0,0 +1,72 @@ +# Akeneo to UnoPim Migration + +The **Akeneo to UnoPim Migration** plugin is a one-way migration tool that imports a complete **Akeneo PIM** catalog into [UnoPim](https://unopim.com) over the **Akeneo REST API** — no manual exports, spreadsheets, or custom scripts. + +
+ +
+ Akeneo to UnoPim Migration +
+ +
+ +Migrating between PIM platforms is usually slow and risky — attributes, families, categories, locales, channels, and thousands of products all have to land in the right place with their relationships intact. This plugin automates the whole process and records every relationship as it goes, so you can move from Akeneo to UnoPim while keeping the data you have already invested years in building. + +Because it reuses UnoPim's native **Data Transfer** import framework, every migration run appears in the **Job Tracker** with downloadable logs you can audit. + +## How It Works + +The plugin adds a dedicated **Akeneo Migration** section to the UnoPim admin panel. From there you manage Akeneo connections, choose what to import, and run the migration — all without leaving the interface. + +A typical migration flow works as follows: + +1. You add and validate an Akeneo connection using your REST API credentials. +2. You open the connection's edit page and select the entities to import. +3. UnoPim connects to Akeneo over the REST API and pulls the selected data. +4. The plugin imports each entity using UnoPim's Data Transfer framework. +5. Mappings between Akeneo and UnoPim records are recorded automatically and reused on later runs to resolve relationships (for example, linking a product to the correct family or categories). +6. The run appears in the Job Tracker, where you can follow progress and download logs. + +Because the migration is one-way (**Akeneo → UnoPim**), the flow stays simple and predictable. You can run it in stages and trust that connections between entities stay consistent. + +## What Gets Migrated + +The plugin brings across both your **structure** and your **catalog**, imported in dependency order so relationships stay intact: + +| # | Entity | Description | +|---|--------|-------------| +| 1 | **Locales** | The locales defined in Akeneo. | +| 2 | **Currencies** | The currencies defined in Akeneo. | +| 3 | **Attributes** | Attributes together with their options. | +| 4 | **Attribute Groups** | Groupings used to organise attributes. | +| 5 | **Attribute Families** | Families that define which attributes a product can hold. | +| 6 | **Categories** | The category tree. | +| 7 | **Channels** | Akeneo channels (scopes). | +| 8 | **DAM Assets** | Digital asset library entries. *Available only when the UnoPim DAM package is installed.* | +| 9 | **Configurable Products** | Akeneo product models. | +| 10 | **Products** | Products, including product media. | + +> [!NOTE] +> Entities import in dependency order — structure first, then categories and channels, then the optional DAM assets, then the catalog. This ensures that, for example, a product's family and categories already exist before the product itself is imported. + +## Key Features + +- **Live-validated connections** — every Akeneo connection is tested against Akeneo before it is saved, so you never store credentials that don't work. +- **Pick what to import** — select individual entities or use the single **Select All / Clear All** toggle to migrate everything at once. +- **Automatic mappings** — Akeneo↔UnoPim relationships are recorded during each import and reused on later runs. +- **Full audit trail** — every run is logged in the **Migration History** tab with the entities imported, status, timing, and the user who ran it. +- **Masked credentials** — Client ID, Secret Key, and Password are masked (`*****`) throughout the interface and in the migration history. +- **Granular permissions** — each action (viewing connections, running a migration, deleting migration runs, and more) is governed by its own permission. +- **Native Job Tracker integration** — runs use UnoPim's Data Transfer framework, so the experience matches every other import in UnoPim. + +## Requirements + +- **UnoPim 2.1.0** +- **PHP 8.3+** +- An **Akeneo** account with REST API (Connection) credentials + +## Next Steps + +- [Install the plugin](./installation) +- [Create and test an Akeneo connection](./create-connection) +- [Run your first migration](./run-migration) diff --git a/docs/akeneo-migration/installation.md b/docs/akeneo-migration/installation.md new file mode 100644 index 0000000..3745da3 --- /dev/null +++ b/docs/akeneo-migration/installation.md @@ -0,0 +1,94 @@ +# Installation + +Follow the steps below to install the **Akeneo to UnoPim Migration** plugin. You'll need terminal access to your UnoPim server before getting started. + +## Requirements + +- **UnoPim 2.1.0** +- **PHP 8.3+** +- An **Akeneo** account with REST API (Connection) credentials + +## Step 1 — Add the Package Files + +Copy the package into your UnoPim project at: + +``` +packages/Webkul/AkeneoMigration +``` + +## Step 2 — Register the Autoloading + +Open the project's root `composer.json` and add the package namespace under the `autoload > psr-4` section: + +```json +"autoload": { + "psr-4": { + "Webkul\\AkeneoMigration\\": "packages/Webkul/AkeneoMigration/src" + } +} +``` + +## Step 3 — Register the Service Provider + +Open `bootstrap/providers.php` and register the service provider: + +```php +use Webkul\AkeneoMigration\Providers\AkeneoMigrationServiceProvider; + +return [ + // ...existing providers... + AkeneoMigrationServiceProvider::class, +]; +``` + +## Step 4 — Register the Concord Module + +Open `config/concord.php` and register the module service provider: + +```php +Webkul\AkeneoMigration\Providers\ModuleServiceProvider::class, +``` + +## Step 5 — Install the Akeneo API Client + +Install the Akeneo PHP API client and refresh the autoloader: + +```bash +composer require akeneo/api-php-client +composer dump-autoload +``` + +## Step 6 — Run the Install Command + +```bash +php artisan akeneo-migration:install +``` + +This command creates the package tables, publishes the sidebar-icon assets, and refreshes the config, route, view, and application caches so the menu, ACL, and routes load. + +| Command | Purpose | +|---|---| +| `composer require akeneo/api-php-client` | Installs the Akeneo PHP REST API client the plugin uses to read from Akeneo. | +| `composer dump-autoload` | Regenerates Composer's autoloader mapping to include the new namespace. | +| `php artisan akeneo-migration:install` | Creates the package tables, publishes assets, and refreshes caches so the menu, ACL, and routes load. | + +## Verify the Installation + +Once all commands have completed, log in to your UnoPim dashboard. You should see the **Akeneo Migration** option appear in the left sidebar — this confirms the plugin is installed and ready to configure. + +
+ +
+ Akeneo Migration package in the admin panel +
+ +
+ +If it doesn't appear, run `php artisan optimize:clear` again and refresh the page. + +## Next Steps + +Add a connection, test it, and run your first import: + +- [Create and test an Akeneo connection](./create-connection) +- [Run a migration](./run-migration) diff --git a/docs/akeneo-migration/migration-history.md b/docs/akeneo-migration/migration-history.md new file mode 100644 index 0000000..45e1573 --- /dev/null +++ b/docs/akeneo-migration/migration-history.md @@ -0,0 +1,38 @@ +# Migration History + +Every migration you start is recorded, giving you a full audit trail of what was imported, when, and by whom. Two tabs on a connection's edit page give you this visibility. + +## Migration History Tab + +Open a connection and switch to the **Migration History** tab. Each row represents one migration run and shows: + +| Column | Description | +|--------|-------------| +| **ID** | The run identifier. | +| **Connection** | The connection the run was started from. | +| **Base URL** | The Akeneo base URL used. | +| **Client ID** | Masked (`*****`). | +| **Secret Key** | Masked (`*****`). | +| **Password** | Masked (`*****`). | +| **Entities** | The entities included in the run. | +| **Status** | The run's status (for example, *queued*). | +| **Started At** | When the run was started. | +| **User** | The admin user who started the run. | + +> [!NOTE] +> Sensitive credentials — **Client ID**, **Secret Key**, and **Password** — are masked (`*****`) everywhere in the migration history, so your catalog moves securely. + +## View Run Details + +Use the **View** action on a row to open a **read-only details view** for that run, showing the same information for a single migration. + +You can also **delete** a single run, or select multiple runs and delete them together. Deleting a run removes it from the history only — it does not undo the imported data. + +## Connection History Tab + +The **History** tab on the same connection records **field-level changes** to the connection itself — so you can see what was edited, and when. + +## Next Steps + +- Need to migrate more entities? [Run another migration](./run-migration) — mappings from earlier runs are reused automatically. +- Control who can view, run, and delete migrations on the [Permissions](./permissions) page. diff --git a/docs/akeneo-migration/permissions.md b/docs/akeneo-migration/permissions.md new file mode 100644 index 0000000..76e0e4d --- /dev/null +++ b/docs/akeneo-migration/permissions.md @@ -0,0 +1,29 @@ +# Permissions + +Every action in the Akeneo Migration plugin is governed by its own **permission (ACL)**. This means you can grant roles access to specific actions independently — for example, let one role manage connections while only senior users run or delete migrations. + +Permissions are managed from UnoPim's role settings, under **Settings → Roles**, when editing a role's access. + +
+ +
+ Akeneo Migration permissions in role settings +
+ +
+ +## Available Permissions + +| Group | Permission | Allows the user to… | +|-------|-----------|---------------------| +| **Connections** | View | Open the Akeneo Migration section and view connections. | +| | Create | Create a new connection. | +| | Edit | Edit an existing connection. | +| | Delete | Delete a connection. | +| | Test Connection | Validate a connection's credentials against Akeneo. | +| **Migration** | Run | Start a migration for a connection. | +| | Migration Runs | View the migration history. | +| | Delete Migration Run | Delete one or more migration runs. | + +> [!TIP] +> Because each action has its own permission, you can keep your migration process safe across larger teams — for example, granting broad read access to connections while restricting who can actually run or delete migrations. diff --git a/docs/akeneo-migration/run-migration.md b/docs/akeneo-migration/run-migration.md new file mode 100644 index 0000000..087e073 --- /dev/null +++ b/docs/akeneo-migration/run-migration.md @@ -0,0 +1,70 @@ +# Run a Migration + +Once you have a working [connection](./create-connection), you can run a migration directly from its edit page. + +## Select the Entities to Migrate + +Open the connection and stay on the **Connection** tab. Under **Entities to migrate**, choose what you want to import. You can: + +- Select individual entities, or +- Use the single **Select All / Clear All** toggle to migrate everything at once. + +The page shows how many entities are **selected** as you choose. + +
+ +
+ Select entities to migrate +
+ +
+ +The available entities are, in dependency order: + +1. Locales +2. Currencies +3. Attributes +4. Attribute Groups +5. Attribute Families +6. Categories +7. Channels +8. DAM Assets *(only when the UnoPim DAM package is installed)* +9. Configurable Products +10. Products + +> [!NOTE] +> Entities import in **dependency order** so relationships stay intact — regardless of the order in which you select them, the plugin always runs them structure-first. This guarantees that prerequisites (such as families and categories) exist before the records that depend on them (such as products). + +## Start the Migration + +Click **Start Migration**. The selected entities are queued and run sequentially, and you are taken to the **Job Tracker** to follow progress. + +> [!IMPORTANT] +> - You must select **at least one** entity before starting. +> - A **disabled** connection cannot be migrated — enable it first from the connection page. + +## Follow Progress in the Job Tracker + +The migration runs on UnoPim's native **Data Transfer** framework, so each entity appears as a job in the **Job Tracker** (pre-filtered to Akeneo migration jobs). From here you can watch each job's state and **download detailed logs** for auditing or troubleshooting. + +
+ +
+ Job Tracker showing Akeneo migration jobs +
+ +
+ +The logs record, per entity: + +- When the migration **started** for that entity. +- When it **finished**, with its state and the number of records processed. +- A clear message if **no records** were returned by Akeneo (verify the records exist in Akeneo and that the API connection's catalog exposes them). +- A clear message if the entity **failed**, including the error (verify the connection credentials are valid and that Akeneo is reachable). + +> [!TIP] +> Because mappings between Akeneo and UnoPim records are recorded automatically, you can run the migration in **stages** — for example, structure first, then products later — and the plugin will reuse those mappings to keep relationships consistent across runs. + +## Next Steps + +After a run completes, review what was imported in the [Migration History](./migration-history). diff --git a/docs/akeneo-migration/sidebar.json b/docs/akeneo-migration/sidebar.json new file mode 100644 index 0000000..04c3775 --- /dev/null +++ b/docs/akeneo-migration/sidebar.json @@ -0,0 +1,38 @@ +[ + { + "text": "Getting Started", + "items": [ + { "text": "Overview", "link": "/akeneo-migration/" }, + { "text": "Installation", "link": "/akeneo-migration/installation" } + ] + }, + + { + "text": "Connections", + "items": [ + { "text": "Create & Test a Connection", "link": "/akeneo-migration/create-connection" } + ] + }, + + { + "text": "Migration", + "items": [ + { "text": "Run a Migration", "link": "/akeneo-migration/run-migration" }, + { "text": "Migration History", "link": "/akeneo-migration/migration-history" } + ] + }, + + { + "text": "Reference", + "items": [ + { "text": "Permissions", "link": "/akeneo-migration/permissions" } + ] + }, + + { + "text": "Support", + "items": [ + { "text": "Contact Support", "link": "/akeneo-migration/contact-support" } + ] + } +]