# Your First Shop App

This tutorial walks through the shop-specific setup: creating a sales channel, registering webhooks, and defining EAV groups. It assumes you already have a working VARIO Cloud app.

## 1. Set Up the Migration

The migration runs on first install. It creates the sales channel backend, a default channel, EAV groups, and webhooks.

```javascript
// api/services/maintenance/install/migrations/1/index.js
const MigratorErp = require('vario-app-framework/backend/utils/migrator.js');

const eavGroupShop = require('./static/erp/eav-groups/myShop.json');

const handle = async function ()
{
  const migratorErp = new MigratorErp('migration1');

  // ERP-level: EAV groups for article listings
  await migratorErp.setMigration('eavStructureErp', async (methods) =>
  {
    await methods.createEavGroup(eavGroupShop);
  });

  // ERP-level: sales channel
  await migratorErp.setMigration('salesChannel', async (methods) =>
  {
    const backend = await methods.createSalesChannelBackend('My Shop', ['ECOMMERCE']);
    await methods.createSalesChannel(backend, 'My Shop', '', 'ECOMMERCE');
    await methods.activateSalesChannelBackend(backend);
  });

  // ERP-level: webhooks
  await migratorErp.setMigration('webhooks', async (methods) =>
  {
    await methods.registerWebhook(
      'sales_channel.create',
      '/api/webhooks/sales_channel.create',
    );
    await methods.registerWebhook(
      'sales_channel.delete',
      '/api/webhooks/sales_channel.delete',
    );
  });

  // App-level: cron webhooks (destinationOwner = 'APP')
  await migratorErp.setMigration('cronWebhooks', async (methods) =>
  {
    await methods.registerWebhook(
      'ORDER_IMPORT',
      '/api/cron-webhooks/ORDER_IMPORT',
      'APP',
    );
    await methods.registerWebhook(
      'PROCESS_QUEUES',
      '/api/cron-webhooks/PROCESS_QUEUES',
      'APP',
    );
  });
};

module.exports = { handle };
```

{% hint style="info" %}
Use `MigratorErp` (from `vario-app-framework`) for ERP-level operations like sales channels, EAV groups, and webhooks.
{% endhint %}

## 2. Define the Shop EAV Group

Adds custom fields to article listings to store the external platform ID.

```json
// static/erp/eav-groups/myShop.json
{
  "key": "myShop",
  "label": "My Shop",
  "description": "My Shop",
  "entities": ["article_listing"],
  "attributes": [
    {
      "key": "id",
      "label": "External ID",
      "type": "TEXT",
      "viewMode": "EDITABLE",
      "active": true,
      "fulltextField": false,
      "searchIndex": true,
      "position": 1
    }
  ]
}
```

## 3. Query Articles via VQL

Use VQL to fetch article data including your custom fields:

```javascript
const ErpApi = require('vario-app-framework/backend/api/ErpApi.js');

const { salesChannel } = getContext();

const { data } = await ErpApi.vql({
  statement: `
    SELECT
        --v:result{displayname='id'}
      id,
        --v:result{displayname='articleNumber'}
      articleNumber,
        --v:result{displayname='name'}
      listings.descriptions.name,
        --v:result{displayname='externalId'}
      listings.custom.myShop.id
    FROM article.shopListing
    WHERE listings.salesChannel.id = '${salesChannel}'
  `,
  limit: 100,
});
```

## Next Steps

* [Core Concepts](https://developer.vario-software.de/guides/onlineshops-and-marketplaces-app/core-concepts) — sales channels, webhooks, data flow, and queue processing
* [Integrations](https://developer.vario-software.de/guides/onlineshops-and-marketplaces-app/integrations) — inbound and outbound sync patterns
* [Configuration](https://developer.vario-software.de/guides/onlineshops-and-marketplaces-app/configuration) — per-channel parameters and transfer toggles
