From 32a296baf2651b8356ad96e70be91f2a9502f7ef Mon Sep 17 00:00:00 2001 From: Michael Czechowski Date: Wed, 29 Apr 2026 17:48:30 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20extract=20cms=20from=20mp/cms=20?= =?UTF-8?q?=E2=80=94=20initial=20libreshop/cms?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Source moved verbatim from mp/cms/ on 2026-04-29; mp was the first concrete adapter consuming the libreshop toolkit. Builds and publishes git.librete.ch/libreshop/cms on every main / v* push via the standard .gitea/workflows/build.yml shared across libreshop components. --- .dockerignore | 8 + .editorconfig | 16 + .gitea/workflows/build.yml | 55 + .gitignore | 130 + .nvmrc | 1 + .prettierrc.json | 9 + CHANGELOG.md | 8 + Dockerfile | 30 + README.md | 25 + config/admin.ts | 22 + config/api.ts | 7 + config/constants.ts | 19 + config/database.ts | 79 + config/logger.ts | 16 + config/middlewares.ts | 12 + config/plugins.ts | 749 + config/server.ts | 13 + database/migrations/.gitkeep | 0 docker-entrypoint.sh | 7 + favicon.png | Bin 0 -> 497 bytes package.json | 40 + public/robots.txt | 3 + public/uploads/.gitkeep | 0 src/admin/app.ts | 9 + src/admin/tsconfig.json | 5 + src/api/.gitkeep | 0 .../content-types/customer/schema.json | 28 + src/api/customer/controllers/customer.ts | 7 + .../documentation/1.0.0/customer.json | 508 + src/api/customer/routes/customer.ts | 7 + src/api/customer/services/customer.ts | 108 + .../content-types/delivery/schema.json | 27 + src/api/delivery/controllers/delivery.ts | 7 + .../documentation/1.0.0/delivery.json | 508 + src/api/delivery/routes/delivery.ts | 7 + src/api/delivery/services/delivery.ts | 7 + src/api/legal/content-types/legal/schema.json | 35 + src/api/legal/controllers/legal.ts | 38 + src/api/legal/documentation/1.0.0/legal.json | 325 + src/api/legal/routes/legal-sitemap.ts | 13 + src/api/legal/routes/legal.ts | 7 + src/api/legal/services/legal.ts | 7 + .../order/content-types/order/lifecycles.ts | 170 + src/api/order/content-types/order/schema.json | 128 + src/api/order/controllers/order.ts | 307 + src/api/order/documentation/1.0.0/order.json | 1344 + src/api/order/routes/order.ts | 124 + src/api/order/services/order.ts | 269 + .../payment/content-types/payment/schema.json | 26 + src/api/payment/controllers/payment.ts | 7 + .../payment/documentation/1.0.0/payment.json | 508 + src/api/payment/routes/payment.ts | 7 + src/api/payment/services/payment.ts | 7 + .../controllers/product-category.ts | 213 + .../documentation/1.0.0/product-category.json | 1 + .../routes/product-category.ts | 73 + .../services/product-category.ts | 80 + .../content-types/product-cover/lifecycles.ts | 3 + .../content-types/product-cover/schema.json | 69 + .../controllers/product-cover.ts | 7 + .../documentation/1.0.0/product-cover.json | 508 + src/api/product-cover/routes/product-cover.ts | 7 + .../product-cover/services/product-cover.ts | 7 + .../content-types/product-image/lifecycles.ts | 3 + .../content-types/product-image/schema.json | 43 + .../controllers/product-image.ts | 7 + .../documentation/1.0.0/product-image.json | 508 + src/api/product-image/routes/product-image.ts | 7 + .../product-image/services/product-image.ts | 7 + .../content-types/product-page/lifecycles.ts | 3 + .../content-types/product-page/schema.json | 42 + .../product-page/controllers/product-page.ts | 7 + .../documentation/1.0.0/product-page.json | 508 + src/api/product-page/routes/product-page.ts | 7 + src/api/product-page/services/product-page.ts | 7 + .../product-pattern/lifecycles.ts | 3 + .../content-types/product-pattern/schema.json | 49 + .../controllers/product-pattern.ts | 7 + .../documentation/1.0.0/product-pattern.json | 508 + .../product-pattern/routes/product-pattern.ts | 7 + .../services/product-pattern.ts | 7 + .../product-ruling/lifecycles.ts | 3 + .../content-types/product-ruling/schema.json | 48 + .../controllers/product-ruling.ts | 7 + .../documentation/1.0.0/product-ruling.json | 508 + .../product-ruling/routes/product-ruling.ts | 7 + .../product-ruling/services/product-ruling.ts | 7 + .../content-types/product/lifecycles.ts | 83 + .../product/content-types/product/schema.json | 59 + src/api/product/controllers/product.ts | 442 + .../product/documentation/1.0.0/product.json | 754 + src/api/product/routes/product.ts | 90 + src/api/product/services/product.ts | 153 + src/api/vat/content-types/vat/schema.json | 36 + src/api/vat/controllers/vat.ts | 7 + src/api/vat/documentation/1.0.0/vat.json | 325 + src/api/vat/routes/vat.ts | 7 + src/api/vat/services/vat.ts | 7 + .../website/content-types/website/schema.json | 22 + src/api/website/controllers/website.ts | 7 + src/api/website/routes/website.ts | 7 + src/api/website/services/website.ts | 7 + .../address/structured-address.json | 28 + src/components/products/cart.json | 21 + src/components/websites/website-in-menu.json | 26 + src/extensions/.gitkeep | 0 .../documentation/config/settings.json | 30 + .../1.0.0/full_documentation.json | 30776 ++++++++++++++++ .../documentation/public/index.html | 70 + src/index.ts | 18 + src/services/MailApi.ts | 92 + src/services/PayPalApi.ts | 165 + src/services/PdfApi.ts | 56 + src/templates/emailTemplates.ts | 441 + src/utils/createComponentLifecycle.ts | 273 + src/utils/formatSlug.ts | 18 + tests/parallel-stress-test-add-to-cart.sh | 73 + tests/parallel-stress-test-finalize-order.sh | 73 + ...llel-stress-test-generate-delivery-note.sh | 73 + tests/parallel-stress-test-get-products.sh | 73 + tests/stress-test-add-to-cart.sh | 19 + tests/stress-test-generate-invoice.sh | 40 + tests/stress-test-get-products.sh | 11 + tsconfig.json | 24 + types/generated/components.d.ts | 62 + types/generated/contentTypes.d.ts | 1001 + types/index.ts | 72 + 127 files changed, 44618 insertions(+) create mode 100644 .dockerignore create mode 100644 .editorconfig create mode 100644 .gitea/workflows/build.yml create mode 100644 .gitignore create mode 100644 .nvmrc create mode 100644 .prettierrc.json create mode 100644 CHANGELOG.md create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 config/admin.ts create mode 100644 config/api.ts create mode 100644 config/constants.ts create mode 100644 config/database.ts create mode 100644 config/logger.ts create mode 100644 config/middlewares.ts create mode 100644 config/plugins.ts create mode 100644 config/server.ts create mode 100644 database/migrations/.gitkeep create mode 100644 docker-entrypoint.sh create mode 100644 favicon.png create mode 100644 package.json create mode 100755 public/robots.txt create mode 100755 public/uploads/.gitkeep create mode 100644 src/admin/app.ts create mode 100644 src/admin/tsconfig.json create mode 100644 src/api/.gitkeep create mode 100644 src/api/customer/content-types/customer/schema.json create mode 100644 src/api/customer/controllers/customer.ts create mode 100644 src/api/customer/documentation/1.0.0/customer.json create mode 100644 src/api/customer/routes/customer.ts create mode 100644 src/api/customer/services/customer.ts create mode 100644 src/api/delivery/content-types/delivery/schema.json create mode 100644 src/api/delivery/controllers/delivery.ts create mode 100644 src/api/delivery/documentation/1.0.0/delivery.json create mode 100644 src/api/delivery/routes/delivery.ts create mode 100644 src/api/delivery/services/delivery.ts create mode 100644 src/api/legal/content-types/legal/schema.json create mode 100644 src/api/legal/controllers/legal.ts create mode 100644 src/api/legal/documentation/1.0.0/legal.json create mode 100644 src/api/legal/routes/legal-sitemap.ts create mode 100644 src/api/legal/routes/legal.ts create mode 100644 src/api/legal/services/legal.ts create mode 100644 src/api/order/content-types/order/lifecycles.ts create mode 100644 src/api/order/content-types/order/schema.json create mode 100644 src/api/order/controllers/order.ts create mode 100644 src/api/order/documentation/1.0.0/order.json create mode 100644 src/api/order/routes/order.ts create mode 100644 src/api/order/services/order.ts create mode 100644 src/api/payment/content-types/payment/schema.json create mode 100644 src/api/payment/controllers/payment.ts create mode 100644 src/api/payment/documentation/1.0.0/payment.json create mode 100644 src/api/payment/routes/payment.ts create mode 100644 src/api/payment/services/payment.ts create mode 100644 src/api/product-category/controllers/product-category.ts create mode 100644 src/api/product-category/documentation/1.0.0/product-category.json create mode 100644 src/api/product-category/routes/product-category.ts create mode 100644 src/api/product-category/services/product-category.ts create mode 100644 src/api/product-cover/content-types/product-cover/lifecycles.ts create mode 100644 src/api/product-cover/content-types/product-cover/schema.json create mode 100644 src/api/product-cover/controllers/product-cover.ts create mode 100644 src/api/product-cover/documentation/1.0.0/product-cover.json create mode 100644 src/api/product-cover/routes/product-cover.ts create mode 100644 src/api/product-cover/services/product-cover.ts create mode 100644 src/api/product-image/content-types/product-image/lifecycles.ts create mode 100644 src/api/product-image/content-types/product-image/schema.json create mode 100644 src/api/product-image/controllers/product-image.ts create mode 100644 src/api/product-image/documentation/1.0.0/product-image.json create mode 100644 src/api/product-image/routes/product-image.ts create mode 100644 src/api/product-image/services/product-image.ts create mode 100644 src/api/product-page/content-types/product-page/lifecycles.ts create mode 100644 src/api/product-page/content-types/product-page/schema.json create mode 100644 src/api/product-page/controllers/product-page.ts create mode 100644 src/api/product-page/documentation/1.0.0/product-page.json create mode 100644 src/api/product-page/routes/product-page.ts create mode 100644 src/api/product-page/services/product-page.ts create mode 100644 src/api/product-pattern/content-types/product-pattern/lifecycles.ts create mode 100644 src/api/product-pattern/content-types/product-pattern/schema.json create mode 100644 src/api/product-pattern/controllers/product-pattern.ts create mode 100644 src/api/product-pattern/documentation/1.0.0/product-pattern.json create mode 100644 src/api/product-pattern/routes/product-pattern.ts create mode 100644 src/api/product-pattern/services/product-pattern.ts create mode 100644 src/api/product-ruling/content-types/product-ruling/lifecycles.ts create mode 100644 src/api/product-ruling/content-types/product-ruling/schema.json create mode 100644 src/api/product-ruling/controllers/product-ruling.ts create mode 100644 src/api/product-ruling/documentation/1.0.0/product-ruling.json create mode 100644 src/api/product-ruling/routes/product-ruling.ts create mode 100644 src/api/product-ruling/services/product-ruling.ts create mode 100644 src/api/product/content-types/product/lifecycles.ts create mode 100644 src/api/product/content-types/product/schema.json create mode 100644 src/api/product/controllers/product.ts create mode 100644 src/api/product/documentation/1.0.0/product.json create mode 100644 src/api/product/routes/product.ts create mode 100644 src/api/product/services/product.ts create mode 100644 src/api/vat/content-types/vat/schema.json create mode 100644 src/api/vat/controllers/vat.ts create mode 100644 src/api/vat/documentation/1.0.0/vat.json create mode 100644 src/api/vat/routes/vat.ts create mode 100644 src/api/vat/services/vat.ts create mode 100644 src/api/website/content-types/website/schema.json create mode 100644 src/api/website/controllers/website.ts create mode 100644 src/api/website/routes/website.ts create mode 100644 src/api/website/services/website.ts create mode 100644 src/components/address/structured-address.json create mode 100644 src/components/products/cart.json create mode 100644 src/components/websites/website-in-menu.json create mode 100644 src/extensions/.gitkeep create mode 100644 src/extensions/documentation/config/settings.json create mode 100644 src/extensions/documentation/documentation/1.0.0/full_documentation.json create mode 100644 src/extensions/documentation/public/index.html create mode 100644 src/index.ts create mode 100644 src/services/MailApi.ts create mode 100644 src/services/PayPalApi.ts create mode 100644 src/services/PdfApi.ts create mode 100644 src/templates/emailTemplates.ts create mode 100644 src/utils/createComponentLifecycle.ts create mode 100644 src/utils/formatSlug.ts create mode 100755 tests/parallel-stress-test-add-to-cart.sh create mode 100755 tests/parallel-stress-test-finalize-order.sh create mode 100755 tests/parallel-stress-test-generate-delivery-note.sh create mode 100755 tests/parallel-stress-test-get-products.sh create mode 100644 tests/stress-test-add-to-cart.sh create mode 100644 tests/stress-test-generate-invoice.sh create mode 100644 tests/stress-test-get-products.sh create mode 100644 tsconfig.json create mode 100644 types/generated/components.d.ts create mode 100644 types/generated/contentTypes.d.ts create mode 100644 types/index.ts diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8576b71 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +.tmp +.cache +.git +build +node_modules +.env +public/uploads/* +package-lock.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8c489cb --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[{package.json,*.yml}] +indent_style = tab +indent_size = 4 + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..b2b411e --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,55 @@ +name: Build and publish + +on: + push: + branches: [main] + tags: ["v*"] + pull_request: + branches: [main] + +# Required secrets: +# REGISTRY git.librete.ch +# REGISTRY_USER libretech-bot +# REGISTRY_PASS bot PAT (write:package; bot is in libreshop Owners team) +# Required variable: +# PUBLISH_ENABLED "true" to actually push (off = build-only on PRs) +# +# Image: git.librete.ch/libreshop/cms +# main pushes → :main + :sha- +# tag pushes → : + :latest + +jobs: + build: + runs-on: ubuntu-latest + container: + image: git.librete.ch/libretech/runner-image:v1 + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + + - uses: docker/setup-buildx-action@v3 + + - name: Login (only when publishing) + if: ${{ vars.PUBLISH_ENABLED == 'true' }} + uses: docker/login-action@v3 + with: + registry: ${{ secrets.REGISTRY }} + username: ${{ secrets.REGISTRY_USER }} + password: ${{ secrets.REGISTRY_PASS }} + + - id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ secrets.REGISTRY }}/libreshop/cms + tags: | + type=ref,event=branch + type=ref,event=tag + type=sha,format=short + type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }} + + - uses: docker/build-push-action@v6 + with: + context: . + push: ${{ vars.PUBLISH_ENABLED == 'true' && github.event_name == 'push' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3d1250b --- /dev/null +++ b/.gitignore @@ -0,0 +1,130 @@ +############################ +# OS X +############################ + +.DS_Store +.AppleDouble +.LSOverride +Icon +.Spotlight-V100 +.Trashes +._* + + +############################ +# Linux +############################ + +*~ + + +############################ +# Windows +############################ + +Thumbs.db +ehthumbs.db +Desktop.ini +$RECYCLE.BIN/ +*.cab +*.msi +*.msm +*.msp + + +############################ +# Packages +############################ + +*.7z +*.csv +*.dat +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip +*.com +*.class +*.dll +*.exe +*.o +*.seed +*.so +*.swo +*.swp +*.swn +*.swm +*.out +*.pid + + +############################ +# Logs and databases +############################ + +.tmp +*.log +*.sql +*.sqlite +*.sqlite3 +database/dump.json + + +############################ +# Misc. +############################ + +*# +ssl +.idea +nbproject +public/uploads/* +!public/uploads/.gitkeep +.strapi +############################ +# Node.js +############################ + +lib-cov +lcov.info +pids +logs +results +node_modules +.node_history + +############################ +# Tests +############################ + +coverage + +############################ +# Strapi +############################ + +.env* +license.txt +exports +*.cache +dist +build +.strapi-updater.json + +# libreshop additions +.env +.env.local +.env.*.local +node_modules/ +.nuxt/ +.output/ +.cache/ +.parcel-cache/ +dist/ +build/ +coverage/ +logs/ +tmp/ diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..517f386 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v22.14.0 diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..cce19ad --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": true, + "tabWidth": 4, + "singleQuote": false, + "printWidth": 150, + "trailingComma": "none", + "useTabs": true +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2478f30 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog + +All notable changes to libreshop/cms are documented here. + +## Unreleased + +- Extracted from `mp/cms/` (2026-04-29). The component history before + the extraction lives in the `muellerprints` repository. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..236d9b3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +FROM node:22.14.0-alpine + +RUN apk update && \ + apk add --no-cache build-base gcc autoconf automake \ + zlib-dev libpng-dev nasm bash vips-dev + +ARG NODE_ENV +ENV NODE_ENV ${NODE_ENV} +ENV PORT 5555 + +WORKDIR /app/ + +COPY ./package.json ./ + +ENV PATH=/node_modules/.bin:$PATH + +RUN npm i --no-audit --no-fund --progress=false --no-warnings --log-level=error +RUN npm i --ignore-scripts=false --foreground-scripts --verbose sharp + +COPY ./ ./ + +RUN chmod +x ./docker-entrypoint.sh + +RUN npm run build + +ENTRYPOINT ["/app/docker-entrypoint.sh"] + +#USER node + +EXPOSE 5555 diff --git a/README.md b/README.md new file mode 100644 index 0000000..71154cc --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# libreshop/cms + +Strapi-based content backend (catalogue, orders, customers). + +Part of the [libreshop](https://git.librete.ch/libreshop) toolkit. Image +published at `git.librete.ch/libreshop/cms` on every push to `main` +and on `v*` tags. + +## Source + +This repo was extracted from `mp/cms/` on 2026-04-29; mp was the +first concrete adapter consuming the toolkit. mp's `compose.yml` now +pulls `git.librete.ch/libreshop/cms:` instead of building locally. + +## Build locally + +``` +docker build -t libreshop/cms:dev . +``` + +## Adapter contract + +See `docker-entrypoint.sh` and `Dockerfile` for the runtime surface. +Adapters configure the component via env vars and bind-mounted volumes; +do not patch the running container or rely on internal paths. diff --git a/config/admin.ts b/config/admin.ts new file mode 100644 index 0000000..5c86914 --- /dev/null +++ b/config/admin.ts @@ -0,0 +1,22 @@ +export default ({ env }) => ({ + auth: { + secret: env("ADMIN_JWT_SECRET") + }, + apiToken: { + salt: env("API_TOKEN_SALT") + }, + transfer: { + token: { + salt: env("TRANSFER_TOKEN_SALT") + } + }, + autoOpen: false, + // watchIgnoreFiles: [ + // "**/controllers/**", + // "**/database/**", + // ], + flags: { + nps: false, + promoteEE: false + } +}); diff --git a/config/api.ts b/config/api.ts new file mode 100644 index 0000000..b675a91 --- /dev/null +++ b/config/api.ts @@ -0,0 +1,7 @@ +export default { + rest: { + defaultLimit: 100, + maxLimit: 1_000, + withCount: true + } +}; diff --git a/config/constants.ts b/config/constants.ts new file mode 100644 index 0000000..6bd7c34 --- /dev/null +++ b/config/constants.ts @@ -0,0 +1,19 @@ +import { Environment } from "@paypal/paypal-server-sdk"; + +export const pdfApiUrl = process.env.PDF_API_ADDRESS!; +export const mailApiUrl = process.env.MAIL_API_ADDRESS!; +export const baseUrl = process.env.BASE_URL!; + +export const paypalClientId = process.env.PAYPAL_CLIENT_ID!; +export const paypalClientSecret = process.env.PAYPAL_CLIENT_SECRET!; +export const paypalEnvironment = process.env.PAYPAL_ENVIRONMENT! === "production" ? Environment.Production : Environment.Sandbox; + +export const adminEmail = process.env.ADMIN_EMAIL_ADDRESS!; + +// TODO: Should be retrieved from DepotApi +export const vatIncludedDecimal = 1.19; +// TODO: Should be retrieved from DepotApi +export const vatDecimal = 0.19; +export const vatDecimalExcluded = 1 - vatDecimal; + +export const maxProductsSitemap = 500; diff --git a/config/database.ts b/config/database.ts new file mode 100644 index 0000000..15f32d7 --- /dev/null +++ b/config/database.ts @@ -0,0 +1,79 @@ +import path from "path"; + +export default ({ env }) => { + const client = env("DATABASE_CLIENT", "sqlite"); + + const connections = { + mysql: { + connection: { + connectionString: env("DATABASE_URL"), + host: env("DATABASE_HOST", "localhost"), + port: env.int("DATABASE_PORT", 3306), + database: env("DATABASE_NAME", "strapi"), + user: env("DATABASE_USERNAME", "strapi"), + password: env("DATABASE_PASSWORD", "strapi"), + ssl: env.bool("DATABASE_SSL", false) && { + key: env("DATABASE_SSL_KEY", undefined), + cert: env("DATABASE_SSL_CERT", undefined), + ca: env("DATABASE_SSL_CA", undefined), + capath: env("DATABASE_SSL_CAPATH", undefined), + cipher: env("DATABASE_SSL_CIPHER", undefined), + rejectUnauthorized: env.bool("DATABASE_SSL_REJECT_UNAUTHORIZED", true) + } + }, + pool: { min: env.int("DATABASE_POOL_MIN", 2), max: env.int("DATABASE_POOL_MAX", 10) } + }, + mysql2: { + connection: { + host: env("DATABASE_HOST", "localhost"), + port: env.int("DATABASE_PORT", 3306), + database: env("DATABASE_NAME", "strapi"), + user: env("DATABASE_USERNAME", "strapi"), + password: env("DATABASE_PASSWORD", "strapi"), + ssl: env.bool("DATABASE_SSL", false) && { + key: env("DATABASE_SSL_KEY", undefined), + cert: env("DATABASE_SSL_CERT", undefined), + ca: env("DATABASE_SSL_CA", undefined), + capath: env("DATABASE_SSL_CAPATH", undefined), + cipher: env("DATABASE_SSL_CIPHER", undefined), + rejectUnauthorized: env.bool("DATABASE_SSL_REJECT_UNAUTHORIZED", true) + } + }, + pool: { min: env.int("DATABASE_POOL_MIN", 2), max: env.int("DATABASE_POOL_MAX", 10) } + }, + postgres: { + connection: { + connectionString: env("DATABASE_URL"), + host: env("DATABASE_HOST", "localhost"), + port: env.int("DATABASE_PORT", 5432), + database: env("DATABASE_NAME", "strapi"), + user: env("DATABASE_USERNAME", "strapi"), + password: env("DATABASE_PASSWORD", "strapi"), + ssl: env.bool("DATABASE_SSL", false) && { + key: env("DATABASE_SSL_KEY", undefined), + cert: env("DATABASE_SSL_CERT", undefined), + ca: env("DATABASE_SSL_CA", undefined), + capath: env("DATABASE_SSL_CAPATH", undefined), + cipher: env("DATABASE_SSL_CIPHER", undefined), + rejectUnauthorized: env.bool("DATABASE_SSL_REJECT_UNAUTHORIZED", true) + }, + schema: env("DATABASE_SCHEMA", "public") + }, + pool: { min: env.int("DATABASE_POOL_MIN", 2), max: env.int("DATABASE_POOL_MAX", 10) } + }, + sqlite: { + connection: { + filename: path.join(__dirname, "..", "..", env("DATABASE_FILENAME", ".tmp/data.db")) + }, + useNullAsDefault: true + } + }; + + return { + connection: { + client, + ...connections[client], + acquireConnectionTimeout: env.int("DATABASE_CONNECTION_TIMEOUT", 60000) + } + }; +}; diff --git a/config/logger.ts b/config/logger.ts new file mode 100644 index 0000000..a0d1663 --- /dev/null +++ b/config/logger.ts @@ -0,0 +1,16 @@ +import { winston } from "@strapi/logger"; + +export default { + transports: [ + new winston.transports.Console({ + format: winston.format.combine( + winston.format.printf(({ timestamp, level, message, ...rest }) => { + let restString = JSON.stringify(rest, undefined, 2); + restString = restString === "{}" ? "" : restString; + + return `${timestamp}Z ${level}: ${message} ${restString}`; + }) + ) + }) + ] +}; diff --git a/config/middlewares.ts b/config/middlewares.ts new file mode 100644 index 0000000..1e339e7 --- /dev/null +++ b/config/middlewares.ts @@ -0,0 +1,12 @@ +export default [ + "strapi::errors", + "strapi::security", + "strapi::cors", + // 'strapi::poweredBy', + "strapi::logger", + "strapi::query", + "strapi::body", + "strapi::session", + "strapi::favicon", + "strapi::public" +]; diff --git a/config/plugins.ts b/config/plugins.ts new file mode 100644 index 0000000..8139c5f --- /dev/null +++ b/config/plugins.ts @@ -0,0 +1,749 @@ +export default ({ env }) => ({ + upload: { + config: { + sizeLimit: 50 * 1024 * 1024 + } + }, + documentation: { + enabled: false, + config: { + openapi: "3.0.1", + info: { + version: "1.0.0", + title: "MUELLERPTINTS. Paperwork", + description: "API Documentation for MUELLERPRINTS. Paperwork", + termsOfService: false, + contact: { + name: "Michael W. Czechowski", + email: "mail@dailysh.it", + url: "https://dailysh.it" + }, + license: "Copyright (C) 2024 Michael W. Czechowski", + externalDocs: false + }, + "x-strapi-config": { + plugins: [], + path: "/documentation", + mutateDocumentation: (draft: any) => { + // Order endpoints - maintain existing modifications + // draft.paths["/orders/{uuid}/cart"].get.parameters[0].schema.type = "string"; + // draft.paths["/orders/{uuid}/cart"].put.parameters[0].schema.type = "string"; + // draft.paths["/orders/{uuid}/generate-delivery-note"].put.parameters[0].schema.type = "string"; + // draft.paths["/orders/{uuid}/generate-invoice"].put.parameters[0].schema.type = "string"; + // draft.paths["/orders/{uuid}/add-product/{productId}"].put.parameters[0].schema.type = "string"; + // draft.paths["/orders/{uuid}/remove-product/{productId}"].put.parameters[0].schema.type = "string"; + // draft.paths["/orders/{uuid}/checkout"].post.parameters[0].schema.type = "string"; + // draft.paths["/orders/{uuid}/send-invoice"].put.parameters[0].schema.type = "string"; + // draft.paths["/orders/{uuid}/send-delivery-note"].put.parameters[0].schema.type = "string"; + // + // // Order request body modifications - maintain existing + // delete draft.paths["/orders/{uuid}/cart"].put.requestBody; + // delete draft.paths["/orders/{uuid}/add-product/{productId}"].put.requestBody; + // delete draft.paths["/orders/{uuid}/remove-product/{productId}"].put.requestBody; + // delete draft.paths["/orders/{uuid}/checkout"].post.requestBody; + // + // // Product publish endpoint - existing documentation + // draft.paths["/products/publish"].post.description = "Publish or unpublish products by filter"; + // draft.paths["/products/publish"].post.requestBody = { + // required: true, + // content: { + // "application/json": { + // schema: { + // type: "object", + // required: ["filters"], + // properties: { + // filters: { + // type: "object", + // description: "Filters to select products (supports pattern, cover, ruling, pages)" + // }, + // publish: { + // type: "boolean", + // description: "Whether to publish (true) or unpublish (false)", + // default: true + // }, + // dryRun: { + // type: "boolean", + // description: "If true, no changes will be made but count will be returned", + // default: false + // } + // } + // } + // } + // } + // }; + // + // draft.paths["/products/publish"].post.responses = { + // "200": { + // description: "Successfully published/unpublished products", + // content: { + // "application/json": { + // schema: { + // type: "object", + // properties: { + // published: { + // type: "integer", + // description: "Number of products published/unpublished" + // }, + // dryRun: { + // type: "boolean", + // description: "Whether this was a dry run" + // } + // } + // } + // } + // } + // }, + // "400": { + // description: "Bad request", + // content: { + // "application/json": { + // schema: { + // type: "object", + // properties: { + // error: { + // type: "string", + // description: "Error message" + // } + // } + // } + // } + // } + // } + // }; + // // Product allVariants endpoint + // if (draft.paths["/products/{id}/variants/all"]) { + // draft.paths["/products/{id}/variants/all"].get.description = "Get all variants for a product"; + // draft.paths["/products/{id}/variants/all"].get.responses = { + // "200": { + // description: "Returns all variants of the product", + // content: { + // "application/json": { + // schema: { + // type: "array", + // items: { + // $ref: "#/components/schemas/Product" + // } + // } + // } + // } + // }, + // "404": { + // description: "Product not found", + // content: { + // "application/json": { + // schema: { + // type: "object", + // properties: { + // error: { + // type: "string", + // description: "Error message" + // } + // } + // } + // } + // } + // } + // }; + // } + // + // // Product variantsByPattern endpoint + // if (draft.paths["/products/{id}/variants/pattern"]) { + // draft.paths["/products/{id}/variants/pattern"].get.description = "Get product variants grouped by pattern"; + // draft.paths["/products/{id}/variants/pattern"].get.responses = { + // "200": { + // description: "Returns product variants grouped by pattern", + // content: { + // "application/json": { + // schema: { + // type: "object", + // properties: { + // allProductPattern: { + // type: "array", + // items: { + // $ref: "#/components/schemas/ProductPattern" + // } + // }, + // productVariants: { + // type: "array", + // items: { + // $ref: "#/components/schemas/Product" + // } + // }, + // patterns: { + // type: "array", + // items: { + // type: "object", + // properties: { + // id: { + // type: "string" + // }, + // name: { + // type: "string" + // }, + // description: { + // type: "string" + // }, + // productVariant: { + // oneOf: [ + // { + // $ref: "#/components/schemas/Product" + // }, + // { + // type: "null" + // } + // ] + // } + // } + // } + // } + // } + // } + // } + // } + // }, + // "400": { + // description: "Bad request", + // content: { + // "application/json": { + // schema: { + // type: "object", + // properties: { + // error: { + // type: "string", + // description: "Error message" + // } + // } + // } + // } + // } + // } + // }; + // } + // + // // Product variants endpoint + // if (draft.paths["/products/{id}/variants"]) { + // draft.paths["/products/{id}/variants"].get.description = "Get product variants grouped by pages, cover, and ruling"; + // draft.paths["/products/{id}/variants"].get.responses = { + // "200": { + // description: "Returns product variants grouped by pages, cover, and ruling", + // content: { + // "application/json": { + // schema: { + // type: "object", + // properties: { + // pages: { + // type: "array", + // items: { + // type: "object", + // properties: { + // id: { + // type: "string" + // }, + // name: { + // type: "string" + // }, + // productVariant: { + // oneOf: [ + // { + // $ref: "#/components/schemas/Product" + // }, + // { + // type: "null" + // } + // ] + // } + // } + // } + // }, + // cover: { + // type: "array", + // items: { + // type: "object", + // properties: { + // id: { + // type: "string" + // }, + // name: { + // type: "string" + // }, + // binding: { + // type: "string" + // }, + // price: { + // type: "number" + // }, + // productVariant: { + // oneOf: [ + // { + // $ref: "#/components/schemas/Product" + // }, + // { + // type: "null" + // } + // ] + // } + // } + // } + // }, + // ruling: { + // type: "array", + // items: { + // type: "object", + // properties: { + // id: { + // type: "string" + // }, + // name: { + // type: "string" + // }, + // productVariant: { + // oneOf: [ + // { + // $ref: "#/components/schemas/Product" + // }, + // { + // type: "null" + // } + // ] + // } + // } + // } + // } + // } + // } + // } + // } + // }, + // "400": { + // description: "Bad request", + // content: { + // "application/json": { + // schema: { + // type: "object", + // properties: { + // error: { + // type: "string", + // description: "Error message" + // } + // } + // } + // } + // } + // } + // }; + // } + // + // // Product Category endpoints + // if (draft.paths["/product-category"]) { + // draft.paths["/product-category"].get.description = "Get all product categories"; + // draft.paths["/product-category"].get.responses = { + // "200": { + // description: "Returns all product categories", + // content: { + // "application/json": { + // schema: { + // type: "array", + // items: { + // $ref: "#/components/schemas/ProductCategory" + // } + // } + // } + // } + // }, + // "400": { + // description: "Bad request" + // } + // }; + // } + // + // if (draft.paths["/product-category/corrupt"]) { + // draft.paths["/product-category/corrupt"].get.description = "Get all corrupted product categories"; + // draft.paths["/product-category/corrupt"].get.responses = { + // "200": { + // description: "Returns all corrupted product categories", + // content: { + // "application/json": { + // schema: { + // type: "array", + // items: { + // $ref: "#/components/schemas/ProductCategory" + // } + // } + // } + // } + // }, + // "400": { + // description: "Bad request" + // } + // }; + // } + // + // if (draft.paths["/product-category/{id}"]) { + // draft.paths["/product-category/{id}"].get.description = "Get a single product category"; + // draft.paths["/product-category/{id}"].get.responses = { + // "200": { + // description: "Returns a single product category", + // content: { + // "application/json": { + // schema: { + // $ref: "#/components/schemas/ProductCategory" + // } + // } + // } + // }, + // "400": { + // description: "Bad request" + // } + // }; + // + // draft.paths["/product-category/{id}"].put.description = "Update a product category"; + // draft.paths["/product-category/{id}"].put.requestBody = { + // required: true, + // content: { + // "application/json": { + // schema: { + // type: "object", + // description: "The data to update the category with" + // } + // } + // } + // }; + // draft.paths["/product-category/{id}"].put.responses = { + // "200": { + // description: "Returns the updated product category", + // content: { + // "application/json": { + // schema: { + // $ref: "#/components/schemas/ProductCategory" + // } + // } + // } + // }, + // "400": { + // description: "Bad request" + // } + // }; + // } + // + // // Update endpoint to match the actual route from product-category.ts + // if (draft.paths["/product-category/bulk"]) { + // draft.paths["/product-category/bulk"].put.description = "Update multiple product categories"; + // draft.paths["/product-category/bulk"].put.requestBody = { + // required: true, + // content: { + // "application/json": { + // schema: { + // type: "object", + // properties: { + // categories: { + // type: "array", + // description: "Array of categories to update" + // } + // } + // } + // } + // } + // }; + // draft.paths["/product-category/bulk"].put.responses = { + // "200": { + // description: "Returns the updated product categories", + // content: { + // "application/json": { + // schema: { + // type: "array", + // items: { + // $ref: "#/components/schemas/ProductCategory" + // } + // } + // } + // } + // }, + // "400": { + // description: "Bad request" + // } + // }; + // } + // // Remove the incorrect "/product-category/update" documentation since it doesn't exist in routes + // + // if (draft.paths["/product-category/fix"]) { + // draft.paths["/product-category/fix"].put.description = "Fix categories with missing cover or pattern"; + // draft.paths["/product-category/fix"].put.responses = { + // "200": { + // description: "Returns information about fixed and failed categories", + // content: { + // "application/json": { + // schema: { + // type: "object", + // properties: { + // fixed: { + // type: "array", + // items: { + // $ref: "#/components/schemas/ProductCategory" + // } + // }, + // failed: { + // type: "array", + // items: { + // $ref: "#/components/schemas/ProductCategory" + // } + // } + // } + // } + // } + // } + // }, + // "400": { + // description: "Bad request" + // } + // }; + // } + // + // if (draft.paths["/product-category/fix-images"]) { + // draft.paths["/product-category/fix-images"].put.description = "Fix product images in categories"; + // draft.paths["/product-category/fix-images"].put.responses = { + // "200": { + // description: "Returns information about fixed and failed product images", + // content: { + // "application/json": { + // schema: { + // type: "object", + // properties: { + // fixed: { + // type: "array", + // items: { + // type: "object", + // properties: { + // categoryId: { + // type: "string" + // }, + // productCount: { + // type: "integer" + // }, + // products: { + // type: "array", + // items: { + // type: "string" + // } + // } + // } + // } + // }, + // failed: { + // type: "array", + // items: { + // type: "object", + // properties: { + // categoryId: { + // type: "string" + // }, + // reason: { + // type: "string" + // }, + // error: { + // type: "string" + // } + // } + // } + // } + // } + // } + // } + // } + // }, + // "400": { + // description: "Bad request" + // } + // }; + // } + // + // // Content controller endpoints + // if (draft.paths["/content"]) { + // draft.paths["/content"].get.description = "Get all content entries"; + // draft.paths["/content"].get.responses = { + // "200": { + // description: "Returns all content entries", + // content: { + // "application/json": { + // schema: { + // type: "array", + // items: { + // $ref: "#/components/schemas/Content" + // } + // } + // } + // } + // } + // }; + // } + // + // // Customer controller endpoints + // if (draft.paths["/customers"]) { + // draft.paths["/customers"].get.description = "Get all customers"; + // draft.paths["/customers"].get.responses = { + // "200": { + // description: "Returns all customers", + // content: { + // "application/json": { + // schema: { + // type: "array", + // items: { + // $ref: "#/components/schemas/Customer" + // } + // } + // } + // } + // } + // }; + // } + // + // // Legal controller endpoints + // if (draft.paths["/legal"]) { + // draft.paths["/legal"].get.description = "Get all legal documents"; + // draft.paths["/legal"].get.responses = { + // "200": { + // description: "Returns all legal documents", + // content: { + // "application/json": { + // schema: { + // type: "array", + // items: { + // $ref: "#/components/schemas/Legal" + // } + // } + // } + // } + // } + // }; + // } + // + // // Delivery controller endpoints + // if (draft.paths["/deliveries"]) { + // draft.paths["/deliveries"].get.description = "Get all deliveries"; + // draft.paths["/deliveries"].get.responses = { + // "200": { + // description: "Returns all deliveries", + // content: { + // "application/json": { + // schema: { + // type: "array", + // items: { + // $ref: "#/components/schemas/Delivery" + // } + // } + // } + // } + // } + // }; + // } + // + // // Payment controller endpoints + // if (draft.paths["/payments"]) { + // draft.paths["/payments"].get.description = "Get all payments"; + // draft.paths["/payments"].get.responses = { + // "200": { + // description: "Returns all payments", + // content: { + // "application/json": { + // schema: { + // type: "array", + // items: { + // $ref: "#/components/schemas/Payment" + // } + // } + // } + // } + // } + // }; + // } + // + // if (draft.paths["/orders/{uuid}"]) { + // draft.paths["/orders/{uuid}"].get.description = "Get order by UUID"; + // draft.paths["/orders/{uuid}"].get.parameters[0].schema.type = "string"; + // draft.paths["/orders/{uuid}"].get.responses = { + // "200": { + // description: "Returns order details", + // content: { + // "application/json": { + // schema: { + // $ref: "#/components/schemas/Order" + // } + // } + // } + // }, + // "404": { + // description: "Order not found" + // } + // }; + // } + // + // if (draft.paths["/orders/webhook"]) { + // draft.paths["/orders/webhook"].post.description = "Handle PayPal webhook events"; + // draft.paths["/orders/webhook"].post.requestBody = { + // required: true, + // content: { + // "application/json": { + // schema: { + // type: "object", + // description: "PayPal webhook event payload" + // } + // } + // } + // }; + // draft.paths["/orders/webhook"].post.responses = { + // "200": { + // description: "Webhook processed successfully" + // }, + // "500": { + // description: "Internal server error" + // } + // }; + // } + } + }, + servers: [ + { + url: "/api", + description: "API server" + } + ], + security: [ + { + bearerAuth: [] + } + ] + } + }, + "strapi-prometheus": { + enabled: false, + config: { + // add prefix to all the prometheus metrics names. + prefix: "cms", + + // use full url instead of matched url + // true => path label: `/api/models/1` + // false => path label: `/api/models/:id` + fullURL: false, + + // include url query in the url label + // true => path label: `/api/models?limit=1` + // false => path label: `/api/models` + includeQuery: false, + + // metrics that will be enabled, by default they are all enabled. + enabledMetrics: { + koa: true, // koa metrics + process: true, // metrics regarding the running process + http: true, // http metrics like response time and size + apollo: false // metrics regarding graphql + }, + + // interval at which rate metrics are collected in ms + interval: 30_000, + + // set custom/default labels to all the prometheus metrics + customLabels: { + name: "strapi-prometheus" + } + } + } +}); diff --git a/config/server.ts b/config/server.ts new file mode 100644 index 0000000..5886453 --- /dev/null +++ b/config/server.ts @@ -0,0 +1,13 @@ +export default ({ env }) => ({ + host: env("HOST", "0.0.0.0"), + port: env.int("PORT", 5555), + app: { + keys: env.array("APP_KEYS") + }, + webhooks: { + populateRelations: env.bool("WEBHOOKS_POPULATE_RELATIONS", false) + }, + logger: { + level: "info" + } +}); diff --git a/database/migrations/.gitkeep b/database/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 0000000..a2e12f0 --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +if [ "$NODE_ENV" = "production" ]; then + npm run start +else + npm run develop +fi diff --git a/favicon.png b/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..df668a881b58175effdf6e6d667cd0a29ce98075 GIT binary patch literal 497 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!Vgr0aT!FNQ%YPz~r|W+YAaeN! zM4m4Hfm|S%I{E+RP5<}p{hyZnKR5G#ea-*Q_WyV8{15c~egC1S$L^sn@(SnS%da63LSXaQ`%;7gOVpveiyr7nQL9IZ= z-A`pVKgIF>S>*T2kpBVWANdax|AfbLJG@L@l;9x3(=mx{2S>{97;cxH>_3zyyzXAU zjjdxQ^WxPEN$-xlJne8sF0xqg#Mjh={AZcjd`yxKaLoVx;=zr@liB5BU%YW{PhSw- uckQM0zm%HSf9!WG&HHyg{qyDQlnaA`#FRum$ErX}4pUXO@geCwXjqE-E literal 0 HcmV?d00001 diff --git a/package.json b/package.json new file mode 100644 index 0000000..8fffac7 --- /dev/null +++ b/package.json @@ -0,0 +1,40 @@ +{ + "name": "cms", + "version": "1.0.0", + "scripts": { + "develop": "DEBUG=app:* npm run strapi develop -- --debug --bundler vite", + "start": "strapi start", + "build": "strapi build --debug", + "strapi": "strapi", + "lint:fix": "prettier --write \"{src,types,config}/**/*.{js,jsx,ts,tsx}\"", + "generate:types": "strapi ts:generate-types", + "import": "npm run strapi import -- -f database/export.tar.gz --force", + "export": "npm run strapi export -- --no-encrypt --file database/export_$(date +'%Y%m%d%H%M%S')", + "transfer-pull": "npm run strapi transfer -- --from $TRANSFER_URL --from-token $TRANSFER_FROM_TOKEN", + "transfer-push": "npm run strapi transfer -- --to $TRANSFER_URL --to-token $TRANSFER_TO_TOKEN --force" + }, + "dependencies": { + "@paypal/paypal-server-sdk": "^0.6.1", + "@strapi/plugin-documentation": "4.25.21", + "@strapi/plugin-i18n": "4.25.21", + "@strapi/plugin-users-permissions": "4.25.21", + "@strapi/strapi": "4.25.21", + "@strapi/utils": "4.25.21", + "lodash": "^4.17.21", + "pg": "^8.11.3", + "react": "^18.0.0", + "react-dom": "^18.0.0", + "react-router-dom": "^5.2.0", + "sharp": "^0.33.5", + "strapi-plugin-populate-deep": "^3.0.1", + "strapi-prometheus": "^1.9.2", + "styled-components": "^5.2.1", + "uuid": "^8.3.2" + }, + "devDependencies": { + "@types/lodash": "^4.17.15", + "@types/node-fetch": "^2.6.11", + "@types/uuid": "^10.0.0", + "prettier": "^3.0.0" + } +} diff --git a/public/robots.txt b/public/robots.txt new file mode 100755 index 0000000..ff5d316 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,3 @@ +# To prevent search engines from seeing the site altogether, uncomment the next two lines: +# User-Agent: * +# Disallow: / diff --git a/public/uploads/.gitkeep b/public/uploads/.gitkeep new file mode 100755 index 0000000..e69de29 diff --git a/src/admin/app.ts b/src/admin/app.ts new file mode 100644 index 0000000..4c24c31 --- /dev/null +++ b/src/admin/app.ts @@ -0,0 +1,9 @@ +export default { + config: { + // Disable video tutorials + tutorials: false, + // Disable notifications about new Strapi releases + notifications: { releases: false } + }, + bootstrap() {} +}; diff --git a/src/admin/tsconfig.json b/src/admin/tsconfig.json new file mode 100644 index 0000000..9578dd2 --- /dev/null +++ b/src/admin/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "@strapi/typescript-utils/tsconfigs/admin", + "include": ["../plugins/**/admin/src/**/*", "./"], + "exclude": ["node_modules/", "build/", "dist/", "**/*.test.ts"] +} diff --git a/src/api/.gitkeep b/src/api/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/api/customer/content-types/customer/schema.json b/src/api/customer/content-types/customer/schema.json new file mode 100644 index 0000000..ff23e54 --- /dev/null +++ b/src/api/customer/content-types/customer/schema.json @@ -0,0 +1,28 @@ +{ + "kind": "collectionType", + "collectionName": "customers", + "info": { + "singularName": "customer", + "pluralName": "customers", + "displayName": "Customer", + "description": "" + }, + "options": { + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "name": { + "type": "string", + "required": true + }, + "address": { + "type": "text" + }, + "addressStructured": { + "type": "component", + "component": "address.structured-address", + "required": false + } + } +} diff --git a/src/api/customer/controllers/customer.ts b/src/api/customer/controllers/customer.ts new file mode 100644 index 0000000..f423e4e --- /dev/null +++ b/src/api/customer/controllers/customer.ts @@ -0,0 +1,7 @@ +/** + * customer controller + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreController("api::customer.customer"); diff --git a/src/api/customer/documentation/1.0.0/customer.json b/src/api/customer/documentation/1.0.0/customer.json new file mode 100644 index 0000000..8a562cf --- /dev/null +++ b/src/api/customer/documentation/1.0.0/customer.json @@ -0,0 +1,508 @@ +{ + "/customers": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Customer" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/customers" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Customer" + ], + "parameters": [], + "operationId": "post/customers", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerRequest" + } + } + } + } + } + }, + "/customers/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Customer" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/customers/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Customer" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/customers/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Customer" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/customers/{id}" + } + } +} diff --git a/src/api/customer/routes/customer.ts b/src/api/customer/routes/customer.ts new file mode 100644 index 0000000..03999e1 --- /dev/null +++ b/src/api/customer/routes/customer.ts @@ -0,0 +1,7 @@ +/** + * customer router + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreRouter("api::customer.customer"); diff --git a/src/api/customer/services/customer.ts b/src/api/customer/services/customer.ts new file mode 100644 index 0000000..49eb712 --- /dev/null +++ b/src/api/customer/services/customer.ts @@ -0,0 +1,108 @@ +import { factories } from "@strapi/strapi"; +import { ID } from "@strapi/database/dist/types"; +import { StructuredAddress } from "../../../../types"; + +// Define a detailed type for customer creation +interface CustomerCreateData { + name: string; + address: string; + email?: string; +} + +export default factories.createCoreService("api::customer.customer", ({ strapi }) => ({ + /** + * Extract customer name from address + * @param address Full address string + * @returns Object with name and cleaned address + */ + extractCustomerDetails(address: string): { name: string; cleanedAddress: string } { + // If address is empty or null, use default values + if (!address || address.trim() === "") { + return { + name: "Unknown Customer", + cleanedAddress: address || "" + }; + } + + // Split address by newline and take the first line as name + const addressLines = address.split("\n").map((line) => line.trim()); + const name = addressLines[0] || "Unknown Customer"; + + // Remove the first line to get the cleaned address + const cleanedAddress = addressLines.slice(1).join("\n").trim(); + + return { + name, + cleanedAddress: cleanedAddress || address + }; + }, + + /** + * Find or create a customer based on address + * @param address Full address string + * @param structuredAddress Optional structured address object + * @returns Customer ID + */ + /** + * Create or update customer with both legacy and structured address + */ + async findOrCreateCustomer(address: string, structuredAddress?: StructuredAddress): Promise { + try { + // Extract name and cleaned address + const { name, cleanedAddress } = this.extractCustomerDetails(address); + + // Try to find by structured address first, then fallback to legacy + let existingCustomers = []; + + if (structuredAddress) { + existingCustomers = await strapi.entityService.findMany("api::customer.customer", { + filters: { + $or: [ + { + addressStructured: { + streetAddress: structuredAddress.streetAddress, + postalCode: structuredAddress.postalCode, + addressLevel2: structuredAddress.addressLevel2 + } + }, + { address: cleanedAddress } + ] + } + }); + } else { + existingCustomers = await strapi.entityService.findMany("api::customer.customer", { + filters: { address: cleanedAddress } + }); + } + + if (existingCustomers && existingCustomers.length > 0) { + const customer = existingCustomers[0]; + + // Update with structured data if provided + if (structuredAddress) { + await strapi.entityService.update("api::customer.customer", customer.id, { + data: { + addressStructured: structuredAddress + } + }); + } + + return customer.id; + } + + // Create new customer with both formats + const newCustomer = await strapi.entityService.create("api::customer.customer", { + data: { + name, + address: cleanedAddress, + ...(structuredAddress && { addressStructured: structuredAddress }) + } + }); + + return newCustomer.id; + } catch (error) { + strapi.log.error("app:e:customer-service: Error managing customer", { error, address }); + throw error; + } + } +})); diff --git a/src/api/delivery/content-types/delivery/schema.json b/src/api/delivery/content-types/delivery/schema.json new file mode 100644 index 0000000..79aacb2 --- /dev/null +++ b/src/api/delivery/content-types/delivery/schema.json @@ -0,0 +1,27 @@ +{ + "kind": "collectionType", + "collectionName": "deliveries", + "info": { + "singularName": "delivery", + "pluralName": "deliveries", + "displayName": "Delivery", + "description": "" + }, + "options": { + "privateAttributes": ["created_at", "updated_at", "created_by", "updated_by", "createdAt", "updatedAt"], + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "name": { + "type": "string", + "required": true + }, + "price": { + "type": "decimal" + }, + "description": { + "type": "text" + } + } +} diff --git a/src/api/delivery/controllers/delivery.ts b/src/api/delivery/controllers/delivery.ts new file mode 100644 index 0000000..58e5e2c --- /dev/null +++ b/src/api/delivery/controllers/delivery.ts @@ -0,0 +1,7 @@ +/** + * delivery controller + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreController("api::delivery.delivery"); diff --git a/src/api/delivery/documentation/1.0.0/delivery.json b/src/api/delivery/documentation/1.0.0/delivery.json new file mode 100644 index 0000000..020d100 --- /dev/null +++ b/src/api/delivery/documentation/1.0.0/delivery.json @@ -0,0 +1,508 @@ +{ + "/deliveries": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeliveryListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Delivery" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/deliveries" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeliveryResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Delivery" + ], + "parameters": [], + "operationId": "post/deliveries", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeliveryRequest" + } + } + } + } + } + }, + "/deliveries/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeliveryResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Delivery" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/deliveries/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeliveryResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Delivery" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/deliveries/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeliveryRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Delivery" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/deliveries/{id}" + } + } +} diff --git a/src/api/delivery/routes/delivery.ts b/src/api/delivery/routes/delivery.ts new file mode 100644 index 0000000..0efb646 --- /dev/null +++ b/src/api/delivery/routes/delivery.ts @@ -0,0 +1,7 @@ +/** + * delivery router + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreRouter("api::delivery.delivery"); diff --git a/src/api/delivery/services/delivery.ts b/src/api/delivery/services/delivery.ts new file mode 100644 index 0000000..8e2d8bd --- /dev/null +++ b/src/api/delivery/services/delivery.ts @@ -0,0 +1,7 @@ +/** + * delivery service + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreService("api::delivery.delivery"); diff --git a/src/api/legal/content-types/legal/schema.json b/src/api/legal/content-types/legal/schema.json new file mode 100644 index 0000000..7965b9e --- /dev/null +++ b/src/api/legal/content-types/legal/schema.json @@ -0,0 +1,35 @@ +{ + "kind": "singleType", + "collectionName": "legals", + "info": { + "singularName": "legal", + "pluralName": "legals", + "displayName": "Legal", + "description": "" + }, + "options": { + "privateAttributes": ["created_at", "updated_at", "created_by", "updated_by"], + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "imprint": { + "type": "richtext" + }, + "contact": { + "type": "richtext" + }, + "terms": { + "type": "richtext" + }, + "delivery": { + "type": "richtext" + }, + "payment": { + "type": "richtext" + }, + "privacy": { + "type": "richtext" + } + } +} diff --git a/src/api/legal/controllers/legal.ts b/src/api/legal/controllers/legal.ts new file mode 100644 index 0000000..d63623d --- /dev/null +++ b/src/api/legal/controllers/legal.ts @@ -0,0 +1,38 @@ +/** + * legal controller + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreController("api::legal.legal", ({ strapi }) => ({ + /** + * Get all legal page paths for sitemap generation + * @returns {Promise} Array of legal page paths + */ + sitemap: async (ctx): Promise => { + try { + strapi.log.verbose("Generating legal sitemap"); + + const legal = await strapi.entityService.findMany("api::legal.legal"); + + if (!legal) { + return []; + } + + strapi.log.silly(`Legal pages response: ${JSON.stringify(legal)}`); + + const internalFields = ["id", "createdAt", "updatedAt", "createdBy", "updatedBy"]; + const legalPages = Object.keys(legal).filter((key) => !internalFields.includes(key)); + + const legalPaths = legalPages.map((page) => `/legal/${page}`); + + strapi.log.verbose(`Generated legal sitemap with ${legalPaths.length} entries`); + strapi.log.silly(`Legal sitemap: ${JSON.stringify(legalPaths)}`); + + return legalPaths; + } catch (error) { + strapi.log.error(error); + return ctx.badRequest("Could not generate legal sitemap"); + } + } +})); diff --git a/src/api/legal/documentation/1.0.0/legal.json b/src/api/legal/documentation/1.0.0/legal.json new file mode 100644 index 0000000..6bfb589 --- /dev/null +++ b/src/api/legal/documentation/1.0.0/legal.json @@ -0,0 +1,325 @@ +{ + "/legal": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LegalResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Legal" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/legal" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LegalResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Legal" + ], + "parameters": [], + "operationId": "put/legal", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LegalRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Legal" + ], + "parameters": [], + "operationId": "delete/legal" + } + } +} diff --git a/src/api/legal/routes/legal-sitemap.ts b/src/api/legal/routes/legal-sitemap.ts new file mode 100644 index 0000000..1a28380 --- /dev/null +++ b/src/api/legal/routes/legal-sitemap.ts @@ -0,0 +1,13 @@ +export default { + routes: [ + { + method: "GET", + path: "/sitemap/legal", + handler: "legal.sitemap", + config: { + auth: false, + policies: [] + } + } + ] +}; diff --git a/src/api/legal/routes/legal.ts b/src/api/legal/routes/legal.ts new file mode 100644 index 0000000..ab12d18 --- /dev/null +++ b/src/api/legal/routes/legal.ts @@ -0,0 +1,7 @@ +/** + * legal router + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreRouter("api::legal.legal"); diff --git a/src/api/legal/services/legal.ts b/src/api/legal/services/legal.ts new file mode 100644 index 0000000..2af385d --- /dev/null +++ b/src/api/legal/services/legal.ts @@ -0,0 +1,7 @@ +/** + * legal service + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreService("api::legal.legal"); diff --git a/src/api/order/content-types/order/lifecycles.ts b/src/api/order/content-types/order/lifecycles.ts new file mode 100644 index 0000000..82d4152 --- /dev/null +++ b/src/api/order/content-types/order/lifecycles.ts @@ -0,0 +1,170 @@ +import { Order } from "../../../../../types"; +import { ID } from "@strapi/database/dist/types"; +import { v4 as uuidv4 } from "uuid"; + +// In-memory processing state tracker +// Using order UUIDs as keys to track which orders are currently being processed +const processingOrders = new Map< + string, + { + invoiceInProgress: boolean; + lastProcessingStarted: number; + } +>(); + +// Cleanup function to prevent memory leaks +const cleanupStaleProcessingEntries = () => { + const now = Date.now(); + const TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes timeout + + for (const [uuid, state] of processingOrders.entries()) { + if (now - state.lastProcessingStarted > TIMEOUT_MS) { + processingOrders.delete(uuid); + strapi.log.verbose(`app:v:order-lifecycles: Cleaned up stale processing state for order ${uuid}`); + } + } +}; + +export default { + beforeCreate(event: { params: { data: { uuid: any } } }) { + // Generate UUID for new orders + if (!event.params.data.uuid) { + event.params.data.uuid = uuidv4(); + } + }, + + async beforeUpdate(event: { + params: { + data: Order; + where: { id: ID }; + }; + }) { + const { data, where } = event.params; + const orderId = where.id; + + strapi.log.debug(`app:d:order-lifecycles: Before order update ${JSON.stringify({ orderId, data })}`); + + // Track what changed for smarter processing + const changes = { + paymentAuthorised: "paymentAuthorised" in data, + addressUpdated: "invoiceAddress" in data + }; + + // Handle address update and customer assignment + if (changes.addressUpdated && data.invoiceAddress) { + try { + const customerService = strapi.service("api::customer.customer"); + + // Find or create customer using the address string only + // The structured address component will be handled by the controller + const customer = await customerService.findOrCreateCustomer(data.invoiceAddress); + + strapi.log.verbose( + "app:d:order-lifecycles: Attaching customer to order", + JSON.stringify({ + order: orderId, + customer + }) + ); + + // Attach customer to order + data.customer = customer; + + // Generate invoice and delivery number in format R-[customer.id]-[order.id] + // Only generate if they don't already exist + if (!data.invoiceNumber) { + data.invoiceNumber = `R-${customer}-${orderId}`; + } + + if (!data.deliveryNoteNumber) { + data.deliveryNoteNumber = `L-${customer}-${orderId}`; + } + + strapi.log.debug("app:d:order-lifecycles: Generated invoice number", { + invoiceNumber: data.invoiceNumber, + deliveryNoteNumber: data.deliveryNoteNumber, + order: orderId + }); + } catch (error) { + strapi.log.error("app:e:order-lifecycles: Error in beforeUpdate", { + error + }); + throw error; + } + } + }, + + async afterCreate(event: { result: Order }) { + const { result } = event; + strapi.log.verbose( + "app:v:order-lifecycles: Order created", + JSON.stringify({ + id: result.id, + uuid: result.uuid + }) + ); + }, + + async afterUpdate(event: { result: Order }) { + const { result } = event; + + // Periodically clean up stale processing entries + cleanupStaleProcessingEntries(); + + // Log order update with relevant fields + strapi.log.debug("app:d:order-lifecycles: ", { + order: { + id: result.id, + uuid: result.uuid, + paymentAuthorised: result.paymentAuthorised, + invoice: result.invoice, + invoiceSent: result.invoiceSent + } + }); + + // Check processing conditions + const shouldProcessInvoice = result.paymentAuthorised && !result.invoiceSent; + + if (!shouldProcessInvoice) { + return; // Early exit if conditions aren't met + } + + // Get order UUID to track processing state + const orderUUID = result.uuid; + + // Check if this order is already being processed + const processingState = processingOrders.get(orderUUID); + if (processingState && processingState.invoiceInProgress) { + strapi.log.verbose("app:v:order-lifecycles: Skipping duplicate invoice generation", { + orderId: result.id, + uuid: orderUUID, + processingStarted: new Date(processingState.lastProcessingStarted).toISOString() + }); + return; + } + + // Mark this order as being processed + processingOrders.set(orderUUID, { + invoiceInProgress: true, + lastProcessingStarted: Date.now() + }); + + try { + strapi.log.info("app:i:order-lifecycles: Starting invoice generation", { orderId: result.id, uuid: orderUUID }); + + // Generate and upload the invoice PDF + const order = await strapi.service("api::order.order").uploadPdf(result, "invoice", "Rechnung"); + + // Send the invoice email + await strapi.service("api::order.order").sendInvoice(orderUUID); + + strapi.log.info("app:i:order-lifecycles: Successfully processed invoice for order", { orderId: result.id, uuid: orderUUID }); + } catch (error) { + strapi.log.error("app:e:order-lifecycles: Error processing invoice", { error, orderId: result.id, uuid: orderUUID }); + // Don't rethrow to prevent transaction failure + } finally { + // Remove the processing marker once complete + processingOrders.delete(orderUUID); + } + } +}; diff --git a/src/api/order/content-types/order/schema.json b/src/api/order/content-types/order/schema.json new file mode 100644 index 0000000..5f783eb --- /dev/null +++ b/src/api/order/content-types/order/schema.json @@ -0,0 +1,128 @@ +{ + "kind": "collectionType", + "collectionName": "orders", + "info": { + "singularName": "order", + "pluralName": "orders", + "displayName": "Order", + "description": "" + }, + "options": { + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "date": { + "type": "date" + }, + "customer": { + "type": "relation", + "relation": "oneToOne", + "target": "api::customer.customer" + }, + "invoice": { + "type": "media", + "multiple": false, + "required": false, + "allowedTypes": [ + "files" + ] + }, + "deliveryNote": { + "type": "media", + "multiple": false, + "required": false, + "allowedTypes": [ + "images", + "files", + "videos", + "audios" + ] + }, + "hash": { + "type": "text", + "unique": true, + "private": true + }, + "email": { + "type": "string" + }, + "delivery": { + "type": "relation", + "relation": "oneToOne", + "target": "api::delivery.delivery" + }, + "payment": { + "type": "relation", + "relation": "oneToOne", + "target": "api::payment.payment" + }, + "VAT": { + "type": "decimal" + }, + "subtotal": { + "type": "decimal" + }, + "total": { + "type": "decimal" + }, + "uuid": { + "type": "string", + "unique": true + }, + "cart": { + "displayName": "cart", + "type": "component", + "repeatable": true, + "component": "products.cart" + }, + "paymentAuthorised": { + "type": "boolean", + "default": false + }, + "paymentStatus": { + "type": "string" + }, + "emailSent": { + "type": "boolean", + "default": false + }, + "acceptedTermsAndConditionsAt": { + "type": "datetime" + }, + "invoiceSent": { + "type": "boolean", + "default": false + }, + "deliveryNoteSent": { + "type": "boolean" + }, + "invoiceNumber": { + "type": "string", + "unique": true + }, + "deliveryNoteNumber": { + "type": "string", + "unique": false + }, + "deliveryTrackingNumber": { + "type": "string" + }, + "deliveryAddress": { + "type": "text" + }, + "invoiceAddress": { + "type": "text" + }, + "invoiceAddressStructured": { + "type": "component", + "component": "address.structured-address", + "required": false + }, + "deliveryAddressStructured": { + "type": "component", + "component": "address.structured-address", + "required": false + } + } +} diff --git a/src/api/order/controllers/order.ts b/src/api/order/controllers/order.ts new file mode 100644 index 0000000..52be99d --- /dev/null +++ b/src/api/order/controllers/order.ts @@ -0,0 +1,307 @@ +import { factories } from "@strapi/strapi"; +import { sanitize } from "@strapi/utils"; +import { Order } from "../../../../types"; +import { paypalApi } from "../../../services/PayPalApi"; +import { orderDefaultParams } from "../services/order"; +import { calculateTotalProductPrice } from "../../product/services/product"; + +/** + * The order controller is a funnel for the client to interact with the order service. + * From creating until finalizing an order, the controller is responsible for handling + * the business logic. + * + * --------------------------------------- + * INIT + * --------------------------------------- + * 1. Create order + * --------------------------------------- + * PRE-ORDER (must have order uuid) + * --------------------------------------- + * 1.1. Find order + * 2. Add/remove product from order + * --------------------------------------- + * ORDER VALIDATION (must have at least one product) + * --------------------------------------- + * 3. Update order + * 3.1. Contact info (email) + * 3.2. Confirm terms and conditions + * 3.3. Address (invoice, delivery) + * 3.4. Delivery method + * --------------------------------------- + * ORDER PAYMENT (order must include all above properties) + * --------------------------------------- + * 4. Checkout order (create adyen payment session) + * --------------------------------------- + * POST-ORDER (payment must be authorised) + * --------------------------------------- + * 5. Finalize order (generate invoice, delivery note) + * 6. Send invoice and delivery note via email + */ +export default factories.createCoreController("api::order.order", ({ strapi }) => ({ + create: async (_) => { + const order = await strapi.entityService.create("api::order.order", { data: {} }); + strapi.log.debug(`app:d:order-controller: Order created: ${JSON.stringify({ order })}`); + return await sanitize.contentAPI.output(order, strapi.getModel("api::order.order")); + }, + + update: async (ctx) => { + const { id } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::order.order")); + strapi.log.verbose(`app:v:order-controller: - Updating order ID${id}`, orderDefaultParams); + const order = await strapi.db.query("api::order.order").findOne({ where: { id }, ...orderDefaultParams }); + if (!order) return ctx.notFound("Order not found"); + + const sanitizedBody = await sanitize.contentAPI.input(ctx.request.body, strapi.getModel("api::order.order")); + strapi.log.verbose("app:v:order-controller: - Updating order", { sanitizedBody }); + + const updatedOrder = await strapi.entityService.update("api::order.order", order.id, { + // @ts-expect-error + data: sanitizedBody?.data, + ...orderDefaultParams + }); + strapi.log.verbose("app:v:order-controller: ✔ Updating order"); + return await sanitize.contentAPI.output(updatedOrder, strapi.getModel("api::order.order")); + }, + + findOne: async (ctx) => { + const { id } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::order.order")); + const order: Order = await strapi.db.query("api::order.order").findOne({ + where: { id }, + ...orderDefaultParams + }); + order.cart = order?.cart.map((item) => ({ + ...item, + product: { + ...item.product, + totalProductPrice: calculateTotalProductPrice(item.product) + } + })); + if (!order) return ctx.notFound("Order not found"); + return await sanitize.contentAPI.output(order, strapi.getModel("api::order.order")); + }, + + findOneByUuid: async (ctx) => { + const { uuid } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::order.order")); + const order: Order = await strapi.db.query("api::order.order").findOne({ + where: { uuid }, + ...orderDefaultParams + }); + order.cart = order?.cart.map((item) => ({ + ...item, + product: { + ...item.product, + totalProductPrice: calculateTotalProductPrice(item.product) + } + })); + if (!order) return ctx.notFound("Order not found"); + return await sanitize.contentAPI.output(order, strapi.getModel("api::order.order")); + }, + + updateByUuid: async (ctx) => { + const { uuid } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::order.order")); + const order = await strapi.db.query("api::order.order").findOne({ where: { uuid } }); + if (!order) return ctx.notFound("Order not found"); + + const sanitizedBody = await sanitize.contentAPI.input(ctx.request.body, strapi.getModel("api::order.order")); + + // Handle customer creation/update if structured addresses are provided + // @ts-expect-error + if (sanitizedBody?.data?.invoiceAddressStructured) { + const customerAddress = + // @ts-expect-error + sanitizedBody.data.invoiceAddress || + // @ts-expect-error + `${sanitizedBody.data.invoiceAddressStructured.givenName} ${sanitizedBody.data.invoiceAddressStructured.familyName}\n${sanitizedBody.data.invoiceAddressStructured.streetAddress}\n${sanitizedBody.data.invoiceAddressStructured.postalCode} ${sanitizedBody.data.invoiceAddressStructured.addressLevel2}`; + // @ts-expect-error + sanitizedBody.data.customer = await strapi + .service("api::customer.customer") + // @ts-expect-error + .findOrCreateCustomer(customerAddress, sanitizedBody.data.invoiceAddressStructured); + } + + const orderUnsafe = await strapi.service("api::order.order").update(order.id, { + // @ts-expect-error + data: sanitizedBody?.data, + ...orderDefaultParams + }); + + return await sanitize.contentAPI.output(orderUnsafe, strapi.getModel("api::order.order")); + }, + + addProduct: async (ctx) => { + const { uuid, productId } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::order.order")); + const order = (await strapi.service("api::order.order").findOneByUuid(uuid)) as Order; + if (!order) return ctx.notFound("Order not found"); + + const product = parseInt(productId as string); + const count = parseInt(ctx.query.count as string) || 1; + const cart = order.cart || []; + const existingIndex = cart.findIndex((item) => item.product.id === product); + + if (existingIndex !== -1) { + // Product already in cart + cart[existingIndex].count += count; + } else { + // @ts-expect-error + cart.push({ count, product }); + } + + strapi.log.info(`app:v:order-controller: - Adding product to cart ${order.id}`, { totalBefore: order.total }); + + const orderUnsafe = await strapi.service("api::order.order").update(order.id, { + data: { cart: cart }, + ...orderDefaultParams + }); + strapi.log.info("app:v:order-controller: ✔ Adding product to cart", { totalAfter: orderUnsafe.total }); + return await sanitize.contentAPI.output(orderUnsafe, strapi.getModel("api::order.order")); + }, + + removeProduct: async (ctx) => { + const { uuid, productId } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::order.order")); + const count = parseInt(ctx.query.count as string) || 1; + const order = (await strapi.service("api::order.order").findOneByUuid(uuid)) as Order; + const product = parseInt(productId as string); + + if (!order) return ctx.notFound("Order not found"); + strapi.log.info("app:v:order-controller: - Removing product from cart", { totalBefore: order.total }); + + const updatedCart = [...(order.cart || [])]; + let existingIndex = -1; + + if (typeof productId === "string") { + existingIndex = updatedCart.findIndex((item) => item.product.id === parseInt(productId)); + } + + if (existingIndex === -1) return ctx.badRequest("Product not found in cart"); + + if (updatedCart[existingIndex].count <= count) { + updatedCart.splice(existingIndex, 1); + } else { + updatedCart[existingIndex].count -= count; + } + + const orderUnsafe = await strapi.service("api::order.order").update(order.id, { + data: { cart: updatedCart }, + ...orderDefaultParams + }); + strapi.log.info("app:v:order-controller: ✔ Removing product from cart", { totalAfter: order.total }); + return await sanitize.contentAPI.output(orderUnsafe, strapi.getModel("api::order.order")); + }, + + checkout: async (ctx) => { + const { uuid } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::order.order")); + const { returnUrl } = await sanitize.contentAPI.query(ctx.query, strapi.getModel("api::order.order")); + const order = await strapi.db.query("api::order.order").findOne({ + where: { uuid }, + ...orderDefaultParams + }); + if (!order) return ctx.notFound("Order not found"); + + return await paypalApi.createSessionOrThrow(returnUrl as string, order); + }, + + capturePayment: async (ctx) => { + const { uuid, paypalOrderId } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::order.order")); + strapi.log.info(`app:i:order-controller: Capturing payment for order ${uuid} with PayPal order ${paypalOrderId}`); + + const order = await strapi.db.query("api::order.order").findOne({ + where: { uuid }, + ...orderDefaultParams + }); + if (!order) return ctx.notFound("Order not found"); + + if (order.paymentAuthorised) { + strapi.log.info(`app:i:order-controller: Payment already authorised for order ${uuid}`); + return { success: true, alreadyCaptured: true }; + } + + try { + // Capture the payment via PayPal server SDK + const captureResult = await paypalApi.checkPaymentStatus({ orderID: paypalOrderId as string }); + + if (captureResult.status === "COMPLETED") { + // Update order with payment info + const updatedOrder = await strapi.entityService.update("api::order.order", order.id, { + data: { + paymentAuthorised: true, + paymentStatus: "authorised", + paypalOrderId: paypalOrderId as string + }, + ...orderDefaultParams + }); + + strapi.log.info(`app:i:order-controller: Payment captured successfully for order ${uuid}`); + return await sanitize.contentAPI.output(updatedOrder, strapi.getModel("api::order.order")); + } else { + strapi.log.error(`app:e:order-controller: Payment capture failed for order ${uuid}`, { captureResult }); + return ctx.badRequest("Payment capture failed", { status: captureResult.status }); + } + } catch (error) { + strapi.log.error(`app:e:order-controller: Error capturing payment for order ${uuid}`, { error }); + return ctx.internalServerError("Payment capture failed"); + } + }, + + generateInvoice: async (ctx) => { + const { uuid } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::order.order")); + strapi.log.info(`app:i:order-controller: Started invoice generation`); + const orderUnsafe = (await strapi.service("api::order.order").findOneByUuid(uuid)) as Order; + + if (!orderUnsafe.paymentAuthorised) { + return ctx.locked("Payment not authorised, cannot generate invoice"); + } + + try { + const updatedOrderUnsafe = await strapi.service("api::order.order").uploadPdf(orderUnsafe, "invoice", "Rechnung"); + return await sanitize.contentAPI.output(updatedOrderUnsafe, strapi.getModel("api::order.order")); + } catch (error) { + strapi.log.error("app:e:order-controller: Error uploading delivery note pdf", { error }); + return ctx.internalServerError("Could not upload delivery note"); + } + }, + + generateDeliveryNote: async (ctx) => { + const { uuid } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::order.order")); + strapi.log.info(`app:i:order-controller: Started delivery note generation`); + const orderUnsafe = (await strapi.service("api::order.order").findOneByUuid(uuid)) as Order; + + if (!orderUnsafe.paymentAuthorised) { + return ctx.locked("Payment not authorised, cannot generate delivery note"); + } + + try { + const updatedOrderUnsafe = await strapi.service("api::order.order").uploadPdf(orderUnsafe, "deliveryNote", "Lieferschein"); + return await sanitize.contentAPI.output(updatedOrderUnsafe, strapi.getModel("api::order.order")); + } catch (error) { + strapi.log.error("app:e:order-controller: Error uploading delivery note pdf", { error }); + return ctx.internalServerError("Could not upload delivery note"); + } + }, + + sendInvoice: async (ctx) => { + const { uuid } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::order.order")); + strapi.log.info("app:i:order-controller: Sending invoice for order", { uuid }); + + try { + const updatedOrderUnsafe = await strapi.service("api::order.order").sendInvoice(uuid, undefined); + return await sanitize.contentAPI.output(updatedOrderUnsafe, strapi.getModel("api::order.order")); + } catch (error) { + strapi.log.error("app:e:order-controller: Error sending invoice", { error }); + return ctx.internalServerError("Could not send invoice"); + } + }, + + sendDeliveryNote: async (ctx) => { + const { uuid } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::order.order")); + strapi.log.info("app:i:order-controller: Sending delivery note for", { uuid }); + return await strapi.service("api::order.order").sendDeliveryNote(uuid, undefined); + }, + + webhook: async (ctx) => { + try { + return await paypalApi.handleWebhook(ctx.request.body); + } catch (error) { + strapi.log.error(`paypal-api: ${JSON.stringify({ error })}`); + return ctx.internalServerError(); + } + } +})); diff --git a/src/api/order/documentation/1.0.0/order.json b/src/api/order/documentation/1.0.0/order.json new file mode 100644 index 0000000..cdb35c3 --- /dev/null +++ b/src/api/order/documentation/1.0.0/order.json @@ -0,0 +1,1344 @@ +{ + "/orders": { + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [], + "operationId": "post/orders", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + }, + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/orders" + } + }, + "/orders/webhook": { + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [], + "operationId": "post/orders/webhook", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/orders/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/orders/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{uuid}/cart": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/orders/{uuid}/cart" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/orders/{uuid}/cart", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{uuid}/add-product/{productId}": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + }, + { + "name": "productId", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/orders/{uuid}/add-product/{productId}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{uuid}/remove-product/{productId}": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + }, + { + "name": "productId", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/orders/{uuid}/remove-product/{productId}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{uuid}/checkout": { + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "post/orders/{uuid}/checkout", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{uuid}/generate-invoice": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/orders/{uuid}/generate-invoice", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{uuid}/generate-delivery-note": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/orders/{uuid}/generate-delivery-note", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{uuid}/send-invoice": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/orders/{uuid}/send-invoice", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{uuid}/send-delivery-note": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/orders/{uuid}/send-delivery-note", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + } +} diff --git a/src/api/order/routes/order.ts b/src/api/order/routes/order.ts new file mode 100644 index 0000000..61acb7f --- /dev/null +++ b/src/api/order/routes/order.ts @@ -0,0 +1,124 @@ +export default { + routes: [ + { + method: "POST", + path: "/orders", + handler: "order.create", + config: { + policies: [] + } + }, + { + method: "POST", + path: "/orders/webhook", + handler: "order.webhook", + config: { + policies: [] + } + }, + { + method: "GET", + path: "/orders", + handler: "order.find", + config: { + policies: [] + } + }, + { + method: "GET", + path: "/orders/:id", + handler: "order.findOne", + config: { + policies: [] + } + }, + { + method: "GET", + path: "/orders/:uuid/cart", + handler: "order.findOneByUuid", + config: { + policies: [] + } + }, + { + method: "PUT", + path: "/orders/:id", + handler: "order.update", + config: { + policies: [] + } + }, + { + method: "PUT", + path: "/orders/:uuid/cart", + handler: "order.updateByUuid", + config: { + policies: [] + } + }, + { + method: "PUT", + path: "/orders/:uuid/add-product/:productId", + handler: "order.addProduct", + config: { + policies: [] + } + }, + { + method: "PUT", + path: "/orders/:uuid/remove-product/:productId", + handler: "order.removeProduct", + config: { + policies: [] + } + }, + { + method: "POST", + path: "/orders/:uuid/checkout", + handler: "order.checkout", + config: { + policies: [] + } + }, + { + method: "POST", + path: "/orders/:uuid/capture/:paypalOrderId", + handler: "order.capturePayment", + config: { + policies: [] + } + }, + { + method: "PUT", + path: "/orders/:uuid/generate-invoice", + handler: "order.generateInvoice", + config: { + policies: [] + } + }, + { + method: "PUT", + path: "/orders/:uuid/generate-delivery-note", + handler: "order.generateDeliveryNote", + config: { + policies: [] + } + }, + { + method: "PUT", + path: "/orders/:uuid/send-invoice", + handler: "order.sendInvoice", + config: { + policies: [] + } + }, + { + method: "PUT", + path: "/orders/:uuid/send-delivery-note", + handler: "order.sendDeliveryNote", + config: { + policies: [] + } + } + ] +}; diff --git a/src/api/order/services/order.ts b/src/api/order/services/order.ts new file mode 100644 index 0000000..6313307 --- /dev/null +++ b/src/api/order/services/order.ts @@ -0,0 +1,269 @@ +import path from "path"; +import fs from "fs"; +import { factories } from "@strapi/strapi"; +import { sanitize } from "@strapi/utils"; +import { ID } from "@strapi/database/dist/types"; +import { vatDecimal, vatIncludedDecimal, baseUrl, adminEmail } from "../../../../config/constants"; +import { calculateTotalProductPrice, productDefaultParams } from "../../product/services/product"; +import { CartProduct, Order, PdfBody } from "../../../../types"; +import { pdfApi } from "../../../services/PdfApi"; +import { invoiceEmailTemplate, deliveryNoteEmailTemplate } from "../../../templates/emailTemplates"; +import _, { template } from "lodash"; +import { PdfMessageBody, MessageBody, mailApi } from "../../../services/MailApi"; + +/** + * This service is responsible for handling the order logic. + */ +export default factories.createCoreService("api::order.order", ({ strapi }) => ({ + findOne: async (id: ID) => { + return await strapi.entityService.findOne("api::order.order", id, orderDefaultParams); + }, + + findOneByUuid: async (uuid: string) => { + const params = { + filters: { + uuid: { + $eq: uuid + } + }, + ...orderDefaultParams + }; + const orderUnsafe = await strapi.db.query("api::order.order").findOne({ + where: { uuid }, + ...orderDefaultParams + }); + orderUnsafe.cart = orderUnsafe?.cart.map((item: CartProduct) => ({ + ...item, + product: { + ...item.product, + totalProductPrice: calculateTotalProductPrice(item.product) + } + })); + return (await sanitize.contentAPI.output(orderUnsafe, strapi.getModel("api::order.order"))) as Order; + }, + + uploadPdf: async (orderUnsafe: Order, field: "invoice" | "deliveryNote", name = "Upload") => { + strapi.log.verbose(`app:v:order-service: – Generating ${field} pdf`); + const pdfBody = field === "invoice" ? invoicePdfBody(orderUnsafe) : deliveryNotePdfBody(orderUnsafe); + strapi.log.debug(`app:d:order-service: - PDF body`, pdfBody); + const blob = field === "invoice" ? await pdfApi.generateInvoice(pdfBody) : await pdfApi.generateDeliveryNote(pdfBody); + strapi.log.verbose(`app:v:order-service: ✔ Generating ${field} pdf`); + + // Save blob to a temp folder + const tempFolder = path.join(__dirname, "temp"); + if (!fs.existsSync(tempFolder)) { + fs.mkdirSync(tempFolder); + } + const deliveryNotePath = path.join(tempFolder, `${name}.pdf`); + fs.writeFileSync(deliveryNotePath, Buffer.from(blob)); + + const uploadData = { + data: { + ref: "api::order.order", + refId: orderUnsafe.id, + field + }, + files: { + path: deliveryNotePath, + name: `${name}_${pdfBody.date.replace(/[^a-z0-9]/gi, "_").toLowerCase()}`, + type: "application/pdf", + size: fs.statSync(deliveryNotePath).size + } + }; + strapi.log.verbose(`app:v:order-service: - Uploading ${field} pdf`); + await strapi.plugins.upload.services.upload.upload(uploadData); + strapi.log.verbose(`app:v:order-service: ✔ Uploading ${field} pdf`); + + return await strapi.service("api::order.order").findOne(orderUnsafe.id); + }, + + sendInvoice: async (uuid: string, blob?: any) => { + strapi.log.info(`app:i:order-service: - Sending invoice for order ${uuid}`); + const oderUnsafe = (await strapi.service("api::order.order").findOneByUuid(uuid)) as Partial; + + try { + const emailConfig: MessageBody = { + to_email: oderUnsafe.email, + subject: template(invoiceEmailTemplate.subject)(oderUnsafe), + message: template(invoiceEmailTemplate.text)({ baseUrl, ...oderUnsafe }), + html: template(invoiceEmailTemplate.html)({ baseUrl, ...oderUnsafe }) + }; + + strapi.log.debug(`app:d:order-service: - Email config ${emailConfig.html}`); + + // Send email to customer + await mailApi.sendTextMessage(emailConfig); + // Send email to administator + await mailApi.sendTextMessage({ + ...emailConfig, + to_email: adminEmail + }); + strapi.log.info(`app:i:order-service: ✔ Sending invoice for order ${uuid}`); + + return await strapi.db.query("api::order.order").update({ + where: { + id: oderUnsafe.id + }, + data: { + invoiceSent: true + } + }); + } catch (error) { + strapi.log.error(`app:e:order-service: χ Sending invoice for order ${uuid}`); + strapi.log.debug(`app:d:order-service: Error: ${JSON.stringify({ error })}`); + return new Error("Could not send invoice"); + } + }, + + sendDeliveryNote: async (uuid: string, blob?: ArrayBuffer) => { + strapi.log.info(`app:i:order-service: - Sending delivery note for order ${uuid}`); + const oderUnsafe = (await strapi.service("api::order.order").findOneByUuid(uuid)) as Partial; + try { + const emailConfig: MessageBody = { + to_email: oderUnsafe.email, + subject: template(deliveryNoteEmailTemplate.subject)(oderUnsafe), + message: template(deliveryNoteEmailTemplate.text)(oderUnsafe), + html: template(deliveryNoteEmailTemplate.html)({ ...oderUnsafe, baseUrl }) + }; + await mailApi.sendTextMessage(emailConfig); + strapi.log.info(`app:i:order-service: ✔ Sending delivery note for order ${uuid}`); + + return await strapi.db.query("api::order.order").update({ + where: { + id: oderUnsafe.id + }, + data: { + deliveryNoteSent: true + } + }); + } catch (error) { + strapi.log.error(`app:e:order-service: χ Sending delivery note for order ${uuid}`); + strapi.log.debug(`app:d:order-service: Error: ${JSON.stringify({ error })}`); + return new Error("Could not send delivery note"); + } + }, + + update: async (id: ID, params: Record): Promise => { + const dataUnsafe = (await strapi.entityService.update("api::order.order", id, params)) as Order; + strapi.log.verbose(`app:v:order-service: Updated order ${id} with initial params`); + let data: { subtotal: number; total: number; VAT: number }; + if (dataUnsafe?.cart) { + const productsTotal = dataUnsafe.cart.reduce((v, p) => v + (calculateTotalProductPrice(p.product) ?? 0) * p.count, 0); + const productsVAT = dataUnsafe.cart.reduce((v, p) => { + const totalProductPrice = calculateTotalProductPrice(p.product) ?? 0; + const amount = totalProductPrice / vatIncludedDecimal; + const tax = totalProductPrice - amount; + return v + tax * p.count; + }, 0); + const deliveryPrice = dataUnsafe.delivery?.price ?? 0; + const paymentPrice = dataUnsafe.payment?.price ?? 0; + strapi.log.debug(`app:d:order-service: Calculating totals`, { productsTotal, deliveryPrice, paymentPrice }); + + const subtotal = productsTotal; + const total = Math.round((subtotal + deliveryPrice + paymentPrice) * 100) / 100; + const VAT = Math.round((subtotal / vatIncludedDecimal) * vatDecimal * 100) / 100; + + strapi.log.verbose(`app:v:order-service: Calculated totals`, { productsTotal, total, VAT, subtotal }); + data = { + subtotal, + total, + VAT + }; + } + const orderUnsafe = await strapi.entityService.update("api::order.order", id, { data, ...orderDefaultParams }); + strapi.log.verbose(`app:v:order-service: Updated order ${id} with calculated totals`); + orderUnsafe.cart = orderUnsafe?.cart.map((item: CartProduct) => ({ + ...item, + product: { + ...item.product, + totalProductPrice: calculateTotalProductPrice(item.product) + } + })); + return (await sanitize.contentAPI.output(orderUnsafe, strapi.getModel("api::order.order"))) as Order; + } +})); + +export const orderDefaultParams = { + populate: { + invoice: true, + deliveryNote: true, + delivery: true, + payment: true, + customer: { + populate: { + addressStructured: true + } + }, + invoiceAddressStructured: true, + deliveryAddressStructured: true, + cart: { + populate: { + product: productDefaultParams + } + } + } +}; + +const invoicePdfBody = (order: Order): PdfBody => { + const pdfBody = defaultPdfBody(order); + + return { + ...pdfBody, + subject: "RECHNUNG", + to: { + name: `${order.customer.addressStructured?.givenName} ${order.customer.addressStructured?.familyName}` || "", + address: [ + order.customer.addressStructured?.streetAddress || "", + `${order.customer.addressStructured?.postalCode} ${order.customer.addressStructured?.addressLevel2}` || "" + ] + }, + nr: { + ...pdfBody.nr, + invoice: order.invoiceNumber + } + } as PdfBody; +}; + +const deliveryNotePdfBody = (order: Order): PdfBody => { + const pdfBody = defaultPdfBody(order); + + return { + ...pdfBody, + subject: "LIEFERSCHEIN", + to: { + name: "", + address: order.deliveryAddress.split("\n") + }, + nr: { + ...pdfBody.nr, + shipping: order.deliveryNoteNumber + } + } as PdfBody; +}; + +const defaultPdfBody = (order: Order): Partial => ({ + date: new Date(order.acceptedTermsAndConditionsAt).toLocaleDateString("de-DE"), + nr: { + customer: `${order.customer.id}`, + order: `${order.id}` + }, + service: + order.cart?.map((cartProduct) => ({ + description: cartProduct.product.name, + price: { + per_unit: calculateTotalProductPrice(cartProduct.product) || 0, + total: (calculateTotalProductPrice(cartProduct.product) || 0) * cartProduct.count + }, + count: cartProduct.count, + nr: `P${cartProduct.product.id}` + })) || [], + currency: "\\euro", + body: "Vielen Dank für Ihren Einkauf und Ihr Vertrauen.", + total: order.total, + subtotal: order.subtotal, + VAT: { + amount: order.VAT, + rate: vatDecimal * 100 + }, + shipping: order.delivery?.price ?? 0 +}); diff --git a/src/api/payment/content-types/payment/schema.json b/src/api/payment/content-types/payment/schema.json new file mode 100644 index 0000000..e714e39 --- /dev/null +++ b/src/api/payment/content-types/payment/schema.json @@ -0,0 +1,26 @@ +{ + "kind": "collectionType", + "collectionName": "payments", + "info": { + "singularName": "payment", + "pluralName": "payments", + "displayName": "Payment", + "description": "" + }, + "options": { + "privateAttributes": ["created_at", "updated_at", "created_by", "updated_by", "createdAt", "updatedAt"], + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "name": { + "type": "string" + }, + "price": { + "type": "decimal" + }, + "description": { + "type": "text" + } + } +} diff --git a/src/api/payment/controllers/payment.ts b/src/api/payment/controllers/payment.ts new file mode 100644 index 0000000..064b6b3 --- /dev/null +++ b/src/api/payment/controllers/payment.ts @@ -0,0 +1,7 @@ +/** + * payment controller + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreController("api::payment.payment"); diff --git a/src/api/payment/documentation/1.0.0/payment.json b/src/api/payment/documentation/1.0.0/payment.json new file mode 100644 index 0000000..6d9cd96 --- /dev/null +++ b/src/api/payment/documentation/1.0.0/payment.json @@ -0,0 +1,508 @@ +{ + "/payments": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Payment" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/payments" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Payment" + ], + "parameters": [], + "operationId": "post/payments", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + } + } + } + } + }, + "/payments/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Payment" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/payments/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Payment" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/payments/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Payment" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/payments/{id}" + } + } +} diff --git a/src/api/payment/routes/payment.ts b/src/api/payment/routes/payment.ts new file mode 100644 index 0000000..3026379 --- /dev/null +++ b/src/api/payment/routes/payment.ts @@ -0,0 +1,7 @@ +/** + * payment router + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreRouter("api::payment.payment"); diff --git a/src/api/payment/services/payment.ts b/src/api/payment/services/payment.ts new file mode 100644 index 0000000..a101bb0 --- /dev/null +++ b/src/api/payment/services/payment.ts @@ -0,0 +1,7 @@ +/** + * payment service + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreService("api::payment.payment"); diff --git a/src/api/product-category/controllers/product-category.ts b/src/api/product-category/controllers/product-category.ts new file mode 100644 index 0000000..1ade40c --- /dev/null +++ b/src/api/product-category/controllers/product-category.ts @@ -0,0 +1,213 @@ +/** + * Product category controller + */ +import { ProductCategory, ProductImage } from "../../../../types"; + +export default () => ({ + // Get all categories + categories: async (ctx, next) => { + try { + ctx.body = await strapi.service("api::product-category.product-category").categories(); + } catch (err) { + ctx.badRequest("Product category controller error", { moreDetails: err }); + } + }, + + corruptCategories: async (ctx, next) => { + try { + const categories = await strapi.service("api::product-category.product-category").categories(); + const corruptedCategories = categories.filter((category) => !category?.product_cover || !category?.product_pattern); + strapi.log.info(`app:i:product-category-controller: Found ${corruptedCategories?.length} categories with missing cover or pattern`); + strapi.log.silly("app:d:product-category-controller:", { corruptedCategories }); + ctx.body = corruptedCategories; + } catch (err) { + ctx.badRequest("Product category controller error", { moreDetails: err }); + } + }, + + // Get single category + category: async (ctx, next) => { + try { + const { id } = ctx.params; + ctx.body = await strapi.service("api::product-category.product-category").category(id); + } catch (err) { + ctx.badRequest("Product category controller error", { moreDetails: err }); + } + }, + + // Update single category + updateCategory: async (ctx, next) => { + try { + const { id } = ctx.params; + const data = ctx.request.body; + ctx.body = await strapi.service("api::product-category.product-category").updateCategory(id, data); + } catch (err) { + ctx.badRequest("Product category controller error", { moreDetails: err }); + } + }, + + // Update multiple categories + updateCategories: async (ctx, next) => { + try { + const { where, data } = ctx.request.body; + + if (!where || !data) { + return ctx.badRequest("Request body must include 'where' and 'data' properties"); + } + + ctx.body = await strapi.service("api::product-category.product-category").updateCategories({ where, data }); + } catch (err) { + ctx.badRequest("Product category controller error", { moreDetails: err }); + } + }, + + fixCategories: async (ctx, next) => { + try { + // find categories with empty cover or pattern + const categories: ProductCategory[] = await strapi.service("api::product-category.product-category").categories({ + filters: { + $or: [{ product_cover: null }, { product_pattern: null }] + }, + populate: { + product_cover: true, + product_pattern: true + } + }); + strapi.log.info(`app:i:product-category-controller: Found ${categories?.length ?? 0} categories with missing cover or pattern`); + strapi.log.silly("app:d:product-category-controller:", { categories }); + + const result = { + fixed: [], + failed: [] + }; + // fix categories with empty cover or pattern by name, e.g. "Notizheft – Geometrische Muster #03" + for (const category of categories) { + const [coverName, patternName] = (category.name as string).split(" – "); + const patterns = await strapi.entityService.findMany("api::product-pattern.product-pattern", { + filters: { + name: patternName + } + }); + const coverNameChunks = coverName.split(" "); + const covers = await strapi.entityService.findMany("api::product-cover.product-cover", { + filters: { + $or: coverNameChunks.map(($containsi: string) => ({ name: { $containsi } })) + } + }); + const pattern = patterns.pop(); + const cover = covers.pop(); + + strapi.log.silly("app:d:product-category-controller:", { cover, pattern }); + + if (!pattern || !cover) { + result.failed.push(category); + strapi.log.warn(`app:w:product-category-controller: Could not find pattern or cover for category ${category?.id}`); + continue; + } + const updatedCategory: ProductCategory = await strapi.service("api::product-category.product-category").updateCategory(category?.id, { + product_pattern: category?.product_pattern ?? pattern?.id, + product_cover: category?.product_cover ?? cover?.id + }); + result.fixed.push(updatedCategory); + strapi.log.info(`app:i:product-category-controller: Updated category ${category?.id} with pattern ${pattern?.id}`); + strapi.log.silly("app:d:product-category-controller:", { updatedCategory }); + } + + strapi.log.info( + `app:i:product-category-controller: Fixed ${result.fixed.length} / Failed ${result.failed.length} categories with missing cover or pattern` + ); + + ctx.body = result; + } catch (err) { + ctx.badRequest("Product category controller error", { moreDetails: err }); + } + }, + + fixProductImages: async (ctx, next) => { + try { + // Find categories/product-images that have no products but have both cover and pattern + const categories = await strapi.service("api::product-category.product-category").categories({ + populate: { + products: true, + product_cover: true, + product_pattern: true + }, + filters: { + products: { $eq: null }, + product_cover: { $ne: null }, + product_pattern: { $ne: null } + } + }); + + const result = { + fixed: [], + failed: [] + }; + + strapi.log.info(`app:i:product-category-controller: Found ${categories?.length ?? 0} categories with missing products`); + strapi.log.silly("app:d:product-category-controller:", { categories }); + + for (const category of categories) { + try { + const coverId = category.product_cover?.id; + const patternId = category.product_pattern?.id; + + if (!coverId || !patternId) { + result.failed.push({ + categoryId: category.id, + reason: "Missing cover or pattern ID" + }); + continue; + } + + // Find all products that match both the cover and pattern IDs + const matchingProducts = await strapi.entityService.findMany("api::product.product", { + filters: { + $and: [{ cover: { id: coverId } }, { pattern: { id: patternId } }] + } + }); + + if (!matchingProducts?.length) { + result.failed.push({ + categoryId: category.id, + coverId, + patternId, + reason: "No matching products found" + }); + continue; + } + + // Update the category with the found products + const updatedCategory = await strapi.service("api::product-category.product-category").updateCategory(category.id, { + products: matchingProducts.map((product) => product.id) + }); + + result.fixed.push({ + categoryId: category.id, + productCount: matchingProducts.length, + products: matchingProducts.map((p) => p.id) + }); + + strapi.log.info(`app:i:product-category-controller: Updated category ${category.id} with ${matchingProducts.length} products`); + strapi.log.silly("app:d:product-category-controller: Updated category details:", { + categoryId: category.id, + products: matchingProducts.map((p) => p.id) + }); + } catch (categoryError) { + result.failed.push({ + categoryId: category.id, + reason: "Error processing category", + error: categoryError.message + }); + strapi.log.error(`app:e:product-category-controller: Error processing category ${category.id}:`, categoryError); + } + } + + strapi.log.info(`app:i:product-category-controller: Fixed ${result.fixed.length} / Failed ${result.failed.length} categories`); + + ctx.body = result; + } catch (err) { + ctx.badRequest("Product category controller error", { moreDetails: err }); + } + } +}); diff --git a/src/api/product-category/documentation/1.0.0/product-category.json b/src/api/product-category/documentation/1.0.0/product-category.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/api/product-category/documentation/1.0.0/product-category.json @@ -0,0 +1 @@ +{} diff --git a/src/api/product-category/routes/product-category.ts b/src/api/product-category/routes/product-category.ts new file mode 100644 index 0000000..a529d07 --- /dev/null +++ b/src/api/product-category/routes/product-category.ts @@ -0,0 +1,73 @@ +export default { + routes: [ + // Get all categories + { + method: "GET", + path: "/product-category", + handler: "product-category.categories", + config: { + policies: [], + middlewares: [] + } + }, + // Get single category + { + method: "GET", + path: "/product-category/:id", + handler: "product-category.category", + config: { + policies: [], + middlewares: [] + } + }, + { + method: "GET", + path: "/product-category/corrupt", + handler: "product-category.corruptCategories", + config: { + policies: [], + middlewares: [] + } + }, + // Bulk update categories + { + method: "PUT", + path: "/product-category/bulk", + handler: "product-category.updateCategories", + config: { + policies: [], + middlewares: [] + } + }, + // Bulk fix categories + { + method: "PUT", + path: "/product-category/fix", + handler: "product-category.fixCategories", + config: { + policies: [], + middlewares: [] + } + }, + // Bulk fix product images + { + method: "PUT", + path: "/product-category/fix-images", + handler: "product-category.fixProductImages", + config: { + policies: [], + middlewares: [] + } + }, + // Update single category + { + method: "PUT", + path: "/product-category/:id", + handler: "product-category.updateCategory", + config: { + policies: [], + middlewares: [] + } + } + ] +}; diff --git a/src/api/product-category/services/product-category.ts b/src/api/product-category/services/product-category.ts new file mode 100644 index 0000000..a33fb97 --- /dev/null +++ b/src/api/product-category/services/product-category.ts @@ -0,0 +1,80 @@ +/** + * Extended product-category service + */ + +interface CategoryUpdate { + where: any; + data: any; +} + +export default () => ({ + // Get all categories + categories: async (params?: Record) => { + try { + return await strapi.entityService.findMany("api::product-image.product-image", { + populate: { + product_cover: true, + product_pattern: true, + images: true + }, + ...params + }); + } catch (error) { + return error; + } + }, + + // Get single category by ID + category: async (id: number) => { + try { + return await strapi.entityService.findOne("api::product-image.product-image", id, { + populate: { + product_cover: true, + product_pattern: true, + images: true + } + }); + } catch (error) { + return error; + } + }, + + // Update single category + updateCategory: async (id: number, data: any) => { + try { + return await strapi.entityService.update("api::product-image.product-image", id, { + data, + populate: { + product_cover: true, + product_pattern: true, + images: true + } + }); + } catch (error) { + return error; + } + }, + + // Update multiple categories using updateMany + updateCategories: async (updates: CategoryUpdate) => { + try { + const result = await strapi.db.query("api::product-image.product-image").updateMany(updates); + + // If you need the updated records with populated relations + if (result.count > 0) { + return await strapi.entityService.findMany("api::product-image.product-image", { + filters: updates.where, + populate: { + product_cover: true, + product_pattern: true, + images: true + } + }); + } + + return result; + } catch (error) { + return error; + } + } +}); diff --git a/src/api/product-cover/content-types/product-cover/lifecycles.ts b/src/api/product-cover/content-types/product-cover/lifecycles.ts new file mode 100644 index 0000000..7ac6d2e --- /dev/null +++ b/src/api/product-cover/content-types/product-cover/lifecycles.ts @@ -0,0 +1,3 @@ +import { ProductCover } from "../../../../../types"; +import { createComponentLifecycle } from "../../../../utils/createComponentLifecycle"; +export default createComponentLifecycle("cover"); diff --git a/src/api/product-cover/content-types/product-cover/schema.json b/src/api/product-cover/content-types/product-cover/schema.json new file mode 100644 index 0000000..fc6afd2 --- /dev/null +++ b/src/api/product-cover/content-types/product-cover/schema.json @@ -0,0 +1,69 @@ +{ + "kind": "collectionType", + "collectionName": "product_covers", + "info": { + "singularName": "product-cover", + "pluralName": "product-covers", + "displayName": "Product Covers", + "description": "" + }, + "options": { + "draftAndPublish": true + }, + "pluginOptions": {}, + "attributes": { + "name": { + "type": "string", + "required": true + }, + "binding": { + "type": "enumeration", + "enum": [ + "Fadenheftung", + "Steppstich", + "Wire-O-Bindung" + ] + }, + "slides": { + "type": "media", + "multiple": true, + "required": false, + "allowedTypes": [ + "images" + ] + }, + "copyText": { + "type": "json" + }, + "image": { + "type": "media", + "multiple": false, + "required": false, + "allowedTypes": [ + "images" + ] + }, + "icon": { + "type": "media", + "multiple": false, + "required": false, + "allowedTypes": [ + "images" + ] + }, + "price": { + "type": "decimal" + }, + "products": { + "type": "relation", + "relation": "oneToMany", + "target": "api::product.product", + "mappedBy": "cover" + }, + "sort": { + "type": "integer", + "default": 0, + "min": 0 + } + } +} diff --git a/src/api/product-cover/controllers/product-cover.ts b/src/api/product-cover/controllers/product-cover.ts new file mode 100644 index 0000000..f8506fc --- /dev/null +++ b/src/api/product-cover/controllers/product-cover.ts @@ -0,0 +1,7 @@ +/** + * product-cover controller + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreController("api::product-cover.product-cover"); diff --git a/src/api/product-cover/documentation/1.0.0/product-cover.json b/src/api/product-cover/documentation/1.0.0/product-cover.json new file mode 100644 index 0000000..0aa3cc2 --- /dev/null +++ b/src/api/product-cover/documentation/1.0.0/product-cover.json @@ -0,0 +1,508 @@ +{ + "/product-covers": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductCoverListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-cover" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/product-covers" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductCoverResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-cover" + ], + "parameters": [], + "operationId": "post/product-covers", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductCoverRequest" + } + } + } + } + } + }, + "/product-covers/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductCoverResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-cover" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/product-covers/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductCoverResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-cover" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/product-covers/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductCoverRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-cover" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/product-covers/{id}" + } + } +} diff --git a/src/api/product-cover/routes/product-cover.ts b/src/api/product-cover/routes/product-cover.ts new file mode 100644 index 0000000..8574674 --- /dev/null +++ b/src/api/product-cover/routes/product-cover.ts @@ -0,0 +1,7 @@ +/** + * product-cover router + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreRouter("api::product-cover.product-cover"); diff --git a/src/api/product-cover/services/product-cover.ts b/src/api/product-cover/services/product-cover.ts new file mode 100644 index 0000000..62b49a8 --- /dev/null +++ b/src/api/product-cover/services/product-cover.ts @@ -0,0 +1,7 @@ +/** + * product-cover service + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreService("api::product-cover.product-cover"); diff --git a/src/api/product-image/content-types/product-image/lifecycles.ts b/src/api/product-image/content-types/product-image/lifecycles.ts new file mode 100644 index 0000000..6755606 --- /dev/null +++ b/src/api/product-image/content-types/product-image/lifecycles.ts @@ -0,0 +1,3 @@ +import { ProductImage } from "../../../../../types"; +import { createComponentLifecycle } from "../../../../utils/createComponentLifecycle"; +export default createComponentLifecycle("image"); diff --git a/src/api/product-image/content-types/product-image/schema.json b/src/api/product-image/content-types/product-image/schema.json new file mode 100644 index 0000000..b8c76ed --- /dev/null +++ b/src/api/product-image/content-types/product-image/schema.json @@ -0,0 +1,43 @@ +{ + "kind": "collectionType", + "collectionName": "product_images", + "info": { + "singularName": "product-image", + "pluralName": "product-images", + "displayName": "Product Images", + "description": "" + }, + "options": { + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "images": { + "type": "media", + "multiple": true, + "required": false, + "allowedTypes": [ + "images" + ] + }, + "name": { + "type": "string" + }, + "products": { + "type": "relation", + "relation": "oneToMany", + "target": "api::product.product", + "mappedBy": "images" + }, + "product_cover": { + "type": "relation", + "relation": "oneToOne", + "target": "api::product-cover.product-cover" + }, + "product_pattern": { + "type": "relation", + "relation": "oneToOne", + "target": "api::product-pattern.product-pattern" + } + } +} diff --git a/src/api/product-image/controllers/product-image.ts b/src/api/product-image/controllers/product-image.ts new file mode 100644 index 0000000..866caec --- /dev/null +++ b/src/api/product-image/controllers/product-image.ts @@ -0,0 +1,7 @@ +/** + * product-image controller + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreController("api::product-image.product-image"); diff --git a/src/api/product-image/documentation/1.0.0/product-image.json b/src/api/product-image/documentation/1.0.0/product-image.json new file mode 100644 index 0000000..b52a909 --- /dev/null +++ b/src/api/product-image/documentation/1.0.0/product-image.json @@ -0,0 +1,508 @@ +{ + "/product-images": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductImageListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-image" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/product-images" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductImageResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-image" + ], + "parameters": [], + "operationId": "post/product-images", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductImageRequest" + } + } + } + } + } + }, + "/product-images/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductImageResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-image" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/product-images/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductImageResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-image" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/product-images/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductImageRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-image" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/product-images/{id}" + } + } +} diff --git a/src/api/product-image/routes/product-image.ts b/src/api/product-image/routes/product-image.ts new file mode 100644 index 0000000..6baacfb --- /dev/null +++ b/src/api/product-image/routes/product-image.ts @@ -0,0 +1,7 @@ +/** + * product-image router + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreRouter("api::product-image.product-image"); diff --git a/src/api/product-image/services/product-image.ts b/src/api/product-image/services/product-image.ts new file mode 100644 index 0000000..2d80712 --- /dev/null +++ b/src/api/product-image/services/product-image.ts @@ -0,0 +1,7 @@ +/** + * product-image service + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreService("api::product-image.product-image"); diff --git a/src/api/product-page/content-types/product-page/lifecycles.ts b/src/api/product-page/content-types/product-page/lifecycles.ts new file mode 100644 index 0000000..df39b0e --- /dev/null +++ b/src/api/product-page/content-types/product-page/lifecycles.ts @@ -0,0 +1,3 @@ +import { ProductPages } from "../../../../../types"; +import { createComponentLifecycle } from "../../../../utils/createComponentLifecycle"; +export default createComponentLifecycle("pages"); diff --git a/src/api/product-page/content-types/product-page/schema.json b/src/api/product-page/content-types/product-page/schema.json new file mode 100644 index 0000000..7fdc912 --- /dev/null +++ b/src/api/product-page/content-types/product-page/schema.json @@ -0,0 +1,42 @@ +{ + "kind": "collectionType", + "collectionName": "product_pages", + "info": { + "singularName": "product-page", + "pluralName": "product-pages", + "displayName": "Product Pages", + "description": "" + }, + "options": { + "privateAttributes": [ + "createdAt", + "updatedAt", + "created_at", + "updated_at", + "created_by", + "updated_by", + "published_at", + "publishedAt", + "published_by", + "publishedBy" + ], + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "name": { + "type": "string", + "required": true, + "default": "name" + }, + "price": { + "type": "decimal" + }, + "products": { + "type": "relation", + "relation": "oneToMany", + "target": "api::product.product", + "mappedBy": "pages" + } + } +} diff --git a/src/api/product-page/controllers/product-page.ts b/src/api/product-page/controllers/product-page.ts new file mode 100644 index 0000000..c8b4fa2 --- /dev/null +++ b/src/api/product-page/controllers/product-page.ts @@ -0,0 +1,7 @@ +/** + * product-page controller + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreController("api::product-page.product-page"); diff --git a/src/api/product-page/documentation/1.0.0/product-page.json b/src/api/product-page/documentation/1.0.0/product-page.json new file mode 100644 index 0000000..681bfd6 --- /dev/null +++ b/src/api/product-page/documentation/1.0.0/product-page.json @@ -0,0 +1,508 @@ +{ + "/product-pages": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPageListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-page" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/product-pages" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPageResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-page" + ], + "parameters": [], + "operationId": "post/product-pages", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPageRequest" + } + } + } + } + } + }, + "/product-pages/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPageResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-page" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/product-pages/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPageResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-page" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/product-pages/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPageRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-page" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/product-pages/{id}" + } + } +} diff --git a/src/api/product-page/routes/product-page.ts b/src/api/product-page/routes/product-page.ts new file mode 100644 index 0000000..c93e21e --- /dev/null +++ b/src/api/product-page/routes/product-page.ts @@ -0,0 +1,7 @@ +/** + * product-page router + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreRouter("api::product-page.product-page"); diff --git a/src/api/product-page/services/product-page.ts b/src/api/product-page/services/product-page.ts new file mode 100644 index 0000000..f4dfb07 --- /dev/null +++ b/src/api/product-page/services/product-page.ts @@ -0,0 +1,7 @@ +/** + * product-page service + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreService("api::product-page.product-page"); diff --git a/src/api/product-pattern/content-types/product-pattern/lifecycles.ts b/src/api/product-pattern/content-types/product-pattern/lifecycles.ts new file mode 100644 index 0000000..5c2cd01 --- /dev/null +++ b/src/api/product-pattern/content-types/product-pattern/lifecycles.ts @@ -0,0 +1,3 @@ +import { ProductPattern } from "../../../../../types"; +import { createComponentLifecycle } from "../../../../utils/createComponentLifecycle"; +export default createComponentLifecycle("pattern"); diff --git a/src/api/product-pattern/content-types/product-pattern/schema.json b/src/api/product-pattern/content-types/product-pattern/schema.json new file mode 100644 index 0000000..698941b --- /dev/null +++ b/src/api/product-pattern/content-types/product-pattern/schema.json @@ -0,0 +1,49 @@ +{ + "kind": "collectionType", + "collectionName": "product_patterns", + "info": { + "singularName": "product-pattern", + "pluralName": "product-patterns", + "displayName": "Product Patterns", + "description": "" + }, + "options": { + "privateAttributes": [ + "createdAt", + "updatedAt", + "created_at", + "updated_at", + "created_by", + "updated_by", + "published_at", + "publishedAt", + "published_by", + "publishedBy" + ], + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "name": { + "type": "string", + "required": true + }, + "image": { + "type": "media", + "multiple": false, + "required": false, + "allowedTypes": [ + "images" + ] + }, + "description": { + "type": "string" + }, + "products": { + "type": "relation", + "relation": "oneToMany", + "target": "api::product.product", + "mappedBy": "pattern" + } + } +} diff --git a/src/api/product-pattern/controllers/product-pattern.ts b/src/api/product-pattern/controllers/product-pattern.ts new file mode 100644 index 0000000..fd34b2f --- /dev/null +++ b/src/api/product-pattern/controllers/product-pattern.ts @@ -0,0 +1,7 @@ +/** + * product-pattern controller + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreController("api::product-pattern.product-pattern"); diff --git a/src/api/product-pattern/documentation/1.0.0/product-pattern.json b/src/api/product-pattern/documentation/1.0.0/product-pattern.json new file mode 100644 index 0000000..a0f9fc8 --- /dev/null +++ b/src/api/product-pattern/documentation/1.0.0/product-pattern.json @@ -0,0 +1,508 @@ +{ + "/product-patterns": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPatternListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-pattern" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/product-patterns" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPatternResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-pattern" + ], + "parameters": [], + "operationId": "post/product-patterns", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPatternRequest" + } + } + } + } + } + }, + "/product-patterns/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPatternResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-pattern" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/product-patterns/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPatternResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-pattern" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/product-patterns/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPatternRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-pattern" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/product-patterns/{id}" + } + } +} diff --git a/src/api/product-pattern/routes/product-pattern.ts b/src/api/product-pattern/routes/product-pattern.ts new file mode 100644 index 0000000..534776b --- /dev/null +++ b/src/api/product-pattern/routes/product-pattern.ts @@ -0,0 +1,7 @@ +/** + * product-pattern router + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreRouter("api::product-pattern.product-pattern"); diff --git a/src/api/product-pattern/services/product-pattern.ts b/src/api/product-pattern/services/product-pattern.ts new file mode 100644 index 0000000..64693bc --- /dev/null +++ b/src/api/product-pattern/services/product-pattern.ts @@ -0,0 +1,7 @@ +/** + * product-pattern service + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreService("api::product-pattern.product-pattern"); diff --git a/src/api/product-ruling/content-types/product-ruling/lifecycles.ts b/src/api/product-ruling/content-types/product-ruling/lifecycles.ts new file mode 100644 index 0000000..75f95f1 --- /dev/null +++ b/src/api/product-ruling/content-types/product-ruling/lifecycles.ts @@ -0,0 +1,3 @@ +import { ProductRuling } from "../../../../../types"; +import { createComponentLifecycle } from "../../../../utils/createComponentLifecycle"; +export default createComponentLifecycle("ruling"); diff --git a/src/api/product-ruling/content-types/product-ruling/schema.json b/src/api/product-ruling/content-types/product-ruling/schema.json new file mode 100644 index 0000000..074b416 --- /dev/null +++ b/src/api/product-ruling/content-types/product-ruling/schema.json @@ -0,0 +1,48 @@ +{ + "kind": "collectionType", + "collectionName": "product_rulings", + "info": { + "singularName": "product-ruling", + "pluralName": "product-rulings", + "displayName": "Product Ruling", + "description": "" + }, + "options": { + "privateAttributes": [ + "createdAt", + "updatedAt", + "created_at", + "updated_at", + "created_by", + "updated_by", + "published_at", + "publishedAt", + "published_by", + "publishedBy" + ], + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "name": { + "type": "string", + "required": true + }, + "price": { + "type": "decimal" + }, + "products": { + "type": "relation", + "relation": "oneToMany", + "target": "api::product.product", + "mappedBy": "ruling" + }, + "icon": { + "allowedTypes": [ + "images" + ], + "type": "media", + "multiple": false + } + } +} diff --git a/src/api/product-ruling/controllers/product-ruling.ts b/src/api/product-ruling/controllers/product-ruling.ts new file mode 100644 index 0000000..3e28c77 --- /dev/null +++ b/src/api/product-ruling/controllers/product-ruling.ts @@ -0,0 +1,7 @@ +/** + * product-ruling controller + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreController("api::product-ruling.product-ruling"); diff --git a/src/api/product-ruling/documentation/1.0.0/product-ruling.json b/src/api/product-ruling/documentation/1.0.0/product-ruling.json new file mode 100644 index 0000000..cf9885c --- /dev/null +++ b/src/api/product-ruling/documentation/1.0.0/product-ruling.json @@ -0,0 +1,508 @@ +{ + "/product-rulings": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRulingListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-ruling" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/product-rulings" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRulingResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-ruling" + ], + "parameters": [], + "operationId": "post/product-rulings", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRulingRequest" + } + } + } + } + } + }, + "/product-rulings/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRulingResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-ruling" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/product-rulings/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRulingResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-ruling" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/product-rulings/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRulingRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-ruling" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/product-rulings/{id}" + } + } +} diff --git a/src/api/product-ruling/routes/product-ruling.ts b/src/api/product-ruling/routes/product-ruling.ts new file mode 100644 index 0000000..1494082 --- /dev/null +++ b/src/api/product-ruling/routes/product-ruling.ts @@ -0,0 +1,7 @@ +/** + * product-ruling router + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreRouter("api::product-ruling.product-ruling"); diff --git a/src/api/product-ruling/services/product-ruling.ts b/src/api/product-ruling/services/product-ruling.ts new file mode 100644 index 0000000..d9587e2 --- /dev/null +++ b/src/api/product-ruling/services/product-ruling.ts @@ -0,0 +1,7 @@ +/** + * product-ruling service + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreService("api::product-ruling.product-ruling"); diff --git a/src/api/product/content-types/product/lifecycles.ts b/src/api/product/content-types/product/lifecycles.ts new file mode 100644 index 0000000..ffcfabd --- /dev/null +++ b/src/api/product/content-types/product/lifecycles.ts @@ -0,0 +1,83 @@ +import { Product } from "../../../../../types"; +import { calculateTotalProductPrice } from "../../services/product"; + +export default { + async beforeCreate(event: { + params: { + data: any; + }; + }) { + const { params } = event; + strapi.log.verbose("app:v:product-lifecycle: Before create", { + params + }); + const cover = await strapi.entityService.findOne("api::product-cover.product-cover", params.data?.cover, { fields: ["price"] }); + const pattern = await strapi.entityService.findOne("api::product-pattern.product-pattern", params.data?.pattern); + const pages = await strapi.entityService.findOne("api::product-page.product-page", params.data?.pages, { fields: ["price"] }); + const ruling = await strapi.entityService.findOne("api::product-ruling.product-ruling", params.data?.ruling, { fields: ["price"] }); + const product = { + ...params.data, + cover, + pattern, + pages, + ruling + } as Partial; + strapi.log.verbose("app:v:product-lifecycle: Created product", product); + + params.data.totalPrice = calculateTotalProductPrice(product); + }, + + async afterCreate(event: { result: Product }) { + const { result } = event; + strapi.log.verbose("app:v:product-lifecycle: Created", { + id: result.id + }); + }, + + async beforeUpdate(event: { params: any }) { + const { params } = event; + strapi.log.verbose("app:v:product-lifecycle: Before update", { + params + }); + }, + + async afterUpdate(event: { result: Product }) { + const { result } = event; + strapi.log.verbose("app:v:product-lifecycle: Updated", { + id: result.id + }); + }, + + async beforeDelete(event: { params: Product }) { + const { params } = event; + strapi.log.verbose("app:v:product-lifecycle: Before delete", { + params + }); + } + + // async afterFindOne(event: { result: any; }) { + // const { result } = event; + // strapi.log.verbose("app:v:product-lifecycle: Found one", { + // result + // }); + // }, + + // async afterFindMany(event: any) { + // strapi.log.verbose("app:v:product-lifecycle: Before found many", { + // event + // }); + // + // const resultWithTotal = event.result.map((product: Product) => { + // return { + // ...product, + // totalProductPrice: calculateTotalProductPrice(product) + // }; + // }); + // + // strapi.log.verbose("app:v:product-lifecycle: Added total product prices", resultWithTotal.map((p: Product) => p.totalProductPrice)); + // + // event.result = resultWithTotal; + // + // return event; + // } +}; diff --git a/src/api/product/content-types/product/schema.json b/src/api/product/content-types/product/schema.json new file mode 100644 index 0000000..d775540 --- /dev/null +++ b/src/api/product/content-types/product/schema.json @@ -0,0 +1,59 @@ +{ + "kind": "collectionType", + "collectionName": "products", + "info": { + "singularName": "product", + "pluralName": "products", + "displayName": "Product", + "description": "" + }, + "options": { + "draftAndPublish": true + }, + "pluginOptions": {}, + "attributes": { + "name": { + "type": "string" + }, + "description": { + "type": "text" + }, + "totalPrice": { + "type": "decimal" + }, + "cover": { + "type": "relation", + "relation": "manyToOne", + "target": "api::product-cover.product-cover", + "inversedBy": "products" + }, + "pattern": { + "type": "relation", + "relation": "manyToOne", + "target": "api::product-pattern.product-pattern", + "inversedBy": "products" + }, + "pages": { + "type": "relation", + "relation": "manyToOne", + "target": "api::product-page.product-page", + "inversedBy": "products" + }, + "ruling": { + "type": "relation", + "relation": "manyToOne", + "target": "api::product-ruling.product-ruling", + "inversedBy": "products" + }, + "slug": { + "type": "uid", + "targetField": "name" + }, + "images": { + "type": "relation", + "relation": "manyToOne", + "target": "api::product-image.product-image", + "inversedBy": "products" + } + } +} diff --git a/src/api/product/controllers/product.ts b/src/api/product/controllers/product.ts new file mode 100644 index 0000000..3e95385 --- /dev/null +++ b/src/api/product/controllers/product.ts @@ -0,0 +1,442 @@ +import { factories } from "@strapi/strapi"; +import { sanitize } from "@strapi/utils"; +import { Result, PaginatedResult } from "@strapi/types/dist/modules/entity-service/result"; +import { ID } from "@strapi/database/dist/types"; +import { Product, ProductPattern } from "../../../../types"; +import { productDefaultParams, calculateTotalProductPrice } from "../services/product"; +import { maxProductsSitemap } from "../../../../config/constants"; + +export interface ProductVariantParams { + populate: { + pattern: any; + cover: any; + ruling: any; + pages: any; + images: any; + }; + pagination: { + page: number; + pageSize: number; + }; + filters?: any; + publicationState?: "live" | "preview"; +} + +const productVariantParams: ProductVariantParams = { + populate: { + pattern: { fields: ["id"] }, + cover: { fields: ["id"] }, + ruling: { fields: ["id"] }, + pages: { fields: ["id"] }, + images: { + populate: { + images: { + fields: ["formats", "url"] + } + } + } + }, + pagination: { page: 1, pageSize: 999 }, + publicationState: "live" +}; + +/** + * Product controller with custom actions + */ +export default factories.createCoreController("api::product.product", ({ strapi }) => ({ + /** + * Find a single product by ID + */ + findOne: async (ctx) => { + const { id } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::product.product")); + const productUnsafe = await strapi.service("api::product.product").findOne(id, productDefaultParams); + const product = (await sanitize.contentAPI.output(productUnsafe, strapi.getModel("api::product.product"))) as Product; + return { + ...product, + totalProductPrice: calculateTotalProductPrice(product) + }; + }, + + /** + * Find products with the lowest price ruling and pages + */ + find: async (ctx): Promise<{ data: Result<"api::product.product">[]; meta: { pagination: any } }> => { + try { + const params = await sanitize.contentAPI.query(ctx.query, strapi.getModel("api::product.product")); + const filtersParams = (params?.filters as Record) ?? {}; + const populateParams = (params?.populate as Record) ?? {}; + const paginationParams = (params?.pagination as Record) ?? {}; + + const mergedParams = { + ...productDefaultParams, + filters: filtersParams, + populate: { + ...productDefaultParams.populate, + ...populateParams + }, + pagination: paginationParams + }; + strapi.log.debug(JSON.stringify({ mergedParams })); + + const response = await strapi.service("api::product.product").find(mergedParams); + const { pagination } = response; + const dataUnsafe = (await sanitize.contentAPI.output( + response.results, + strapi.getModel("api::product.product") + )) as Result<"api::product.product">[]; + const data = dataUnsafe.map((product: Product) => { + return { + ...product, + totalProductPrice: calculateTotalProductPrice(product) + }; + }); + + return { data, meta: { pagination } }; + } catch (error) { + strapi.log.error(error); + return ctx.badRequest("Could not fetch products"); + } + }, + + /** + * Get all variants for a product + * @returns {Promise} All variants of the product + */ + allVariants: async (ctx): Promise => { + try { + const { id } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::product.product")); + strapi.log.verbose(`Fetching variants for product ${id}`); + + const product = await getProductDetails(id as ID); + const variants = await strapi.entityService.findMany<"api::product.product", ProductVariantParams>("api::product.product", { + ...productVariantParams, + filters: { + pattern: { id: { $eq: product.pattern.id } } + } + }); + + if (!variants) { + return ctx.notFound(`Could not find variants for product ${id}`); + } + + return Promise.all(variants.map((variant) => sanitize.contentAPI.output(variant, strapi.getModel("api::product.product")))) as Promise< + Product[] + >; + } catch (error) { + strapi.log.error(error); + return ctx.badRequest("Could not fetch product variants"); + } + }, + + /** + * Get variants by pattern for a product + * @returns {Promise<{ allProductPattern: ProductPattern[], productVariants: Product[], patterns: Array }>} Variants grouped by pattern + */ + variantsByPattern: async ( + ctx + ): Promise<{ + allProductPattern: ProductPattern[]; + productVariants: Product[]; + patterns: Array; + }> => { + try { + const { id } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::product.product")); + strapi.log.verbose(`Fetching variants by pattern for product ${id}`); + + const product = await getProductDetails(id as ID); + const { pattern, cover, ruling, pages } = product; + + const productVariants = await strapi.entityService.findMany<"api::product.product", ProductVariantParams>("api::product.product", { + ...productVariantParams, + filters: { + $and: [ + { id: { $ne: id } }, + { pattern: { id: { $ne: pattern.id } } }, + { cover: { id: { $eq: cover.id } } }, + { ruling: { id: { $eq: ruling.id } } }, + { pages: { id: { $eq: pages.id } } } + ] + } + }); + + const sanitizedVariants = (await Promise.all( + productVariants.map((variant) => sanitize.contentAPI.output(variant, strapi.getModel("api::product.product"))) + )) as Product[]; + + const allProductPatternResponse = (await strapi.service("api::product-pattern.product-pattern").find({ + fields: ["id", "name", "description"], + populate: { image: { fields: ["url"] } }, + filters: { id: { $ne: pattern.id } }, + publicationState: "live" + })) as PaginatedResult<"api::product-pattern.product-pattern">; + + const allProductPattern = allProductPatternResponse.results; + + return { + allProductPattern, + productVariants: sanitizedVariants, + patterns: allProductPattern.map((pattern) => ({ + ...pattern, + productVariant: sanitizedVariants.find((variant) => variant?.pattern?.id === pattern.id) + })) + }; + } catch (error) { + strapi.log.error(error); + return ctx.badRequest("Could not fetch variants by pattern"); + } + }, + + /** + * Get variants for a product + * @returns {Promise<{ pages: any[], cover: any[], ruling: any[] }>} Variants grouped by pages, cover, and ruling + */ + variants: async ( + ctx + ): Promise<{ + pages: any; + cover: any; + ruling: any; + }> => { + try { + const { id } = await sanitize.contentAPI.query(ctx.params, strapi.getModel("api::product.product")); + strapi.log.verbose(`Fetching variants for product ${id}`); + + const product = await getProductDetails(id as ID); + + const allProductPatternVariants = await strapi.entityService.findMany<"api::product.product", ProductVariantParams>( + "api::product.product", + { + ...productVariantParams, + filters: { + $and: [{ pattern: { id: { $eq: product.pattern.id } } }, { id: { $ne: id } }] + } + } + ); + + const [allProductPages, allProductRulings, allProductCovers] = await Promise.all([ + strapi + .service("api::product-page.product-page") + .find({ fields: ["id", "name"] }) as PaginatedResult<"api::product-pattern.product-pattern">, + strapi.service("api::product-ruling.product-ruling").find({ + fields: ["id", "name"], + populate: { icon: { fields: ["url"] } } + }) as PaginatedResult<"api::product-ruling.product-ruling">, + strapi.service("api::product-cover.product-cover").find({ + fields: ["id", "name", "binding", "price"], + populate: { icon: { fields: ["url"] } } + }) as PaginatedResult<"api::product-cover.product-cover"> + ]); + + const sanitizedVariants = (await Promise.all( + allProductPatternVariants.map((variant) => sanitize.contentAPI.output(variant, strapi.getModel("api::product.product"))) + )) as Product[]; + + // For pages variants: find products with same pattern, cover, and ruling, but different pages + const pagesVariants = allProductPages.results.map((pages) => ({ + ...pages, + productVariant: sanitizedVariants.find( + (variant) => + variant.id !== product.id && + variant.pages.id === pages.id && + variant.cover.id === product.cover.id && + variant.ruling.id === product.ruling.id + ) + })); + + // For cover variants: find products with same pattern and ruling but different covers + const coverVariants = allProductCovers.results.map((cover) => { + // Find any product with this cover and the same pattern + const matchingVariant = sanitizedVariants.find( + (variant) => + variant.id !== product.id && + variant.cover.id === cover.id && + variant.pattern.id === product.pattern.id && + variant.ruling.id === product.ruling.id + ); + + return { + ...cover, + productVariant: matchingVariant + }; + }); + + // For ruling variants: find products with same pattern, cover, and pages, but different ruling + const rulingVariants = allProductRulings.results.map((ruling) => ({ + ...ruling, + productVariant: sanitizedVariants.find( + (variant) => + variant.id !== product.id && + variant.ruling.id === ruling.id && + variant.pages.id === product.pages.id && + variant.cover.id === product.cover.id + ) + })); + + return { + pages: pagesVariants, + cover: coverVariants, + ruling: rulingVariants + }; + } catch (error) { + strapi.log.error(error); + return ctx.badRequest("Could not fetch product variants"); + } + }, + + /** + * Publish or unpublish products by filter + * @returns {Promise<{published: number, dryRun: boolean}>} The number of products published/unpublished and dryRun status + */ + publishByFilter: async (ctx): Promise<{ published: number; dryRun: boolean }> => { + try { + const { filters, publish = true, dryRun = false } = ctx.request.body; + + if (!filters) { + return ctx.badRequest("Filters are required"); + } + + strapi.log.debug(`Publishing products with filters: ${JSON.stringify(filters)}, publish: ${publish}, dryRun: ${dryRun}`); + + return await strapi.service("api::product.product").publishByFilter(filters, publish, dryRun); + } catch (error) { + strapi.log.error(error); + return ctx.badRequest("Could not publish products"); + } + }, + + /** + * Find products with only the cheapest variant per cover+pattern combination + */ + findCheapest: async (ctx): Promise<{ data: Result<"api::product.product">[]; meta: { pagination: any } }> => { + try { + const params = await sanitize.contentAPI.query(ctx.query, strapi.getModel("api::product.product")); + const filtersParams = (params?.filters as Record) ?? {}; + const populateParams = (params?.populate as Record) ?? {}; + const paginationParams = (params?.pagination as Record) ?? {}; + + // First get all products + const mergedParams = { + ...productDefaultParams, + filters: filtersParams, + populate: { + ...productDefaultParams.populate, + ...populateParams + }, + pagination: { pageSize: 999 } // Temporarily get all to filter + }; + + const allProducts = await strapi.service("api::product.product").find(mergedParams); + const allProductsSanitized = (await sanitize.contentAPI.output( + allProducts.results, + strapi.getModel("api::product.product") + )) as Product[]; + + // Group products by cover+pattern combination + const productGroups = new Map(); + + allProductsSanitized.forEach((product) => { + const key = `${product.cover.id}-${product.pattern.id}`; + if (!productGroups.has(key) || calculateTotalProductPrice(product) < calculateTotalProductPrice(productGroups.get(key))) { + productGroups.set(key, product); + } + }); + + // Convert map values to array and sort by pattern.id + const cheapestProducts = Array.from(productGroups.values()).sort((a, b) => { + const idA = a.pattern?.id ?? 0; + const idB = b.pattern?.id ?? 0; + return idA - idB; + }); + + // Apply pagination manually + const page = parseInt(paginationParams.page) || 1; + const pageSize = parseInt(paginationParams.pageSize) || 24; + const total = cheapestProducts.length; + const pageCount = Math.ceil(total / pageSize); + const start = (page - 1) * pageSize; + const end = start + pageSize; + const paginatedProducts = cheapestProducts.slice(start, end); + + // Add total price to each product + const data = paginatedProducts.map((product) => ({ + ...product, + totalProductPrice: calculateTotalProductPrice(product) + })); + + return { + data, + meta: { + pagination: { + page, + pageSize, + pageCount, + total + } + } + }; + } catch (error) { + strapi.log.error(error); + return ctx.badRequest("Could not fetch cheapest products"); + } + }, + + /** + * Get all published product paths for sitemap generation + * @returns {Promise} Array of product paths + */ + sitemap: async (ctx): Promise => { + try { + strapi.log.verbose("Generating product sitemap"); + + const products = await strapi.entityService.findMany("api::product.product", { + fields: ["slug"], + filters: { + publishedAt: { $notNull: true } + }, + pagination: { + page: 1, + pageSize: maxProductsSitemap + }, + sort: { updatedAt: "desc" } + }); + + if (!products || !products.length) { + return []; + } + + const productPaths = products.map((product) => `/details/${product.slug}`); + + strapi.log.verbose(`Generated product sitemap with ${productPaths.length} entries`); + strapi.log.silly(`Product sitemap: ${JSON.stringify(productPaths)}`); + + return productPaths; + } catch (error) { + strapi.log.error(error); + return ctx.badRequest("Could not generate product sitemap"); + } + } +})); + +/** + * Helper function to get product details + * @param {ID} id - The product ID + * @returns {Promise} The product details + * @throws {Error} If the product is not found + */ +async function getProductDetails(id: ID): Promise { + const product = await strapi.entityService.findOne("api::product.product", id, { + fields: ["id", "name"], + populate: { + pattern: { fields: ["id"] }, + cover: { fields: ["id"] }, + ruling: { fields: ["id"] }, + pages: { fields: ["id"] } + } + }); + + if (!product) { + throw new Error(`Could not find product with ID ${id}`); + } + + return (await sanitize.contentAPI.output(product, strapi.getModel("api::product.product"))) as Promise; +} diff --git a/src/api/product/documentation/1.0.0/product.json b/src/api/product/documentation/1.0.0/product.json new file mode 100644 index 0000000..3d62018 --- /dev/null +++ b/src/api/product/documentation/1.0.0/product.json @@ -0,0 +1,754 @@ +{ + "/products": { + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [], + "operationId": "post/products", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRequest" + } + } + } + } + }, + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/products" + } + }, + "/products/{id}": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/products/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRequest" + } + } + } + } + }, + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/products/{id}" + } + }, + "/products/{id}/variants/all": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/products/{id}/variants/all" + } + }, + "/products/{id}/variants/pattern": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/products/{id}/variants/pattern" + } + }, + "/products/{id}/variants": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/products/{id}/variants" + } + }, + "/products/publish": { + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [], + "operationId": "post/products/publish", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRequest" + } + } + } + } + } + } +} diff --git a/src/api/product/routes/product.ts b/src/api/product/routes/product.ts new file mode 100644 index 0000000..1d8515c --- /dev/null +++ b/src/api/product/routes/product.ts @@ -0,0 +1,90 @@ +export default { + routes: [ + { + method: "POST", + path: "/products", + handler: "product.create", + config: { + policies: [] + } + }, + { + method: "GET", + path: "/products", + handler: "product.find", + config: { + policies: [] + } + }, + { + method: "GET", + path: "/promo-products", + handler: "product.findCheapest", + config: { + auth: false, + policies: [] + } + }, + { + method: "GET", + path: "/sitemap/products", + handler: "product.sitemap", + config: { + auth: false, + policies: [] + } + }, + { + method: "PUT", + path: "/products/:id", + handler: "product.update", + config: { + policies: [] + } + }, + { + method: "GET", + path: "/products/:id", + handler: "product.findOne", + config: { + auth: false, + policies: [] + } + }, + { + method: "GET", + path: "/products/:id/variants/all", + handler: "product.allVariants", + config: { + auth: false, + policies: [] + } + }, + { + method: "GET", + path: "/products/:id/variants/pattern", + handler: "product.variantsByPattern", + config: { + auth: false, + policies: [] + } + }, + { + method: "GET", + path: "/products/:id/variants", + handler: "product.variants", + config: { + auth: false, + policies: [] + } + }, + { + method: "POST", + path: "/products/publish", + handler: "product.publishByFilter", + config: { + policies: [] + } + } + ] +}; diff --git a/src/api/product/services/product.ts b/src/api/product/services/product.ts new file mode 100644 index 0000000..799b57f --- /dev/null +++ b/src/api/product/services/product.ts @@ -0,0 +1,153 @@ +/** + * This service is responsible for handling the product logic. + */ + +import { factories } from "@strapi/strapi"; +import { Product } from "../../../../types"; + +export default factories.createCoreService("api::product.product", ({ strapi }) => ({ + find: async (params: Record) => { + const filtersParams = (params?.filters as Record) ?? {}; + const populateParams = (params?.populate as Record) ?? {}; + const paginationParams = (params?.pagination as Record) ?? {}; + return strapi.entityService.findPage("api::product.product", { + ...productDefaultParams, + populate: { + ...productDefaultParams.populate, + ...populateParams + }, + filters: filtersParams, + pageSize: 30, + ...paginationParams + }); + // const resultsUnsafe = response.results; + // const results = resultsUnsafe.map((product) => { + // return { + // ...product, + // totalProductPrice: calculateTotalProductPrice(product) + // }; + // }); + // + // return { ...response, results }; + }, + + findOne: async (id: number) => { + const product = await strapi.entityService.findOne<"api::product.product", ProductParams>("api::product.product", id, productDefaultParams); + return { + ...product, + totalProductPrice: calculateTotalProductPrice(product) + }; + }, + + /** + * Publish or unpublish products by filter + * @param {Record} filters - The filters to apply + * @param {boolean} publish - Whether to publish or unpublish + * @param {boolean} dryRun - Whether to perform a dry run + * @returns {Promise<{published: number, products: number[], dryRun: boolean}>} The number of products published/unpublished and dryRun status + */ + publishByFilter: async ( + filters: Record, + publish: boolean = true, + dryRun: boolean = false + ): Promise<{ published: any; products: number[]; dryRun: boolean }> => { + const query = strapi.db.query("api::product.product"); + + // Build the filter query - complex filtering based on product relations + const dbFilters = { + $and: [ + ...Object.entries(filters).map(([key, value]) => { + // Handle relation filters + if (["pattern", "cover", "ruling", "pages"].includes(key) && typeof value === "object") { + return { + [key]: value + }; + } + // Handle direct property filters + return { + [key]: value + }; + }) + ] + }; + + // Find products matching the filters + const products = await query.findMany({ + where: dbFilters, + populate: ["pattern", "cover", "ruling", "pages"] + }); + + strapi.log.info(`Found ${products.length} products matching filters${dryRun ? " (dry run)" : ""}`); + + // If dry run, just return the count + if (dryRun) { + return { + published: products.length, + products: products.map((product) => product.id), + dryRun: true + }; + } + + // Update publication state for matching products + if (products.length > 0) { + const updatePromises = products.map((product) => { + return query.update({ + where: { id: product.id }, + data: { + publishedAt: publish ? new Date() : null + } + }); + }); + + await Promise.all(updatePromises); + } + + return { + published: products.length, + products: products.map((product) => product.id), + dryRun: false + }; + } +})); + +export const calculateTotalProductPrice = (product: Partial): number => { + return (product?.cover?.price ?? 0) + (product?.pages?.price ?? 0) + (product?.ruling?.price ?? 0); +}; + +export interface ProductParams { + populate?: { + pattern: any; + cover: any; + ruling: any; + pages: any; + images: { + populate: { + images: any; + }; + }; + }; + publicationState?: "live" | "preview"; +} + +export const productDefaultParams: ProductParams = { + populate: { + pattern: true, + cover: { + populate: { + slides: { + fields: ["formats", "url"] + } + } + }, + ruling: true, + pages: true, + images: { + populate: { + images: { + fields: ["formats", "url"] + } + } + } + }, + publicationState: "live" +}; diff --git a/src/api/vat/content-types/vat/schema.json b/src/api/vat/content-types/vat/schema.json new file mode 100644 index 0000000..3a563af --- /dev/null +++ b/src/api/vat/content-types/vat/schema.json @@ -0,0 +1,36 @@ +{ + "kind": "singleType", + "collectionName": "vats", + "info": { + "singularName": "vat", + "pluralName": "vats", + "displayName": "VAT" + }, + "options": { + "privateAttributes": [ + "createdAt", + "updatedAt", + "created_at", + "updated_at", + "created_by", + "updated_by", + "published_at", + "publishedAt", + "published_by", + "publishedBy" + ], + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "name": { + "type": "string" + }, + "percent": { + "type": "integer" + }, + "decimal": { + "type": "decimal" + } + } +} diff --git a/src/api/vat/controllers/vat.ts b/src/api/vat/controllers/vat.ts new file mode 100644 index 0000000..7dea240 --- /dev/null +++ b/src/api/vat/controllers/vat.ts @@ -0,0 +1,7 @@ +/** + * vat controller + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreController("api::vat.vat"); diff --git a/src/api/vat/documentation/1.0.0/vat.json b/src/api/vat/documentation/1.0.0/vat.json new file mode 100644 index 0000000..1809251 --- /dev/null +++ b/src/api/vat/documentation/1.0.0/vat.json @@ -0,0 +1,325 @@ +{ + "/vat": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VatResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Vat" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/vat" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VatResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Vat" + ], + "parameters": [], + "operationId": "put/vat", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VatRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Vat" + ], + "parameters": [], + "operationId": "delete/vat" + } + } +} diff --git a/src/api/vat/routes/vat.ts b/src/api/vat/routes/vat.ts new file mode 100644 index 0000000..113a80f --- /dev/null +++ b/src/api/vat/routes/vat.ts @@ -0,0 +1,7 @@ +/** + * vat router + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreRouter("api::vat.vat"); diff --git a/src/api/vat/services/vat.ts b/src/api/vat/services/vat.ts new file mode 100644 index 0000000..27a1638 --- /dev/null +++ b/src/api/vat/services/vat.ts @@ -0,0 +1,7 @@ +/** + * vat service + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreService("api::vat.vat"); diff --git a/src/api/website/content-types/website/schema.json b/src/api/website/content-types/website/schema.json new file mode 100644 index 0000000..0ec1802 --- /dev/null +++ b/src/api/website/content-types/website/schema.json @@ -0,0 +1,22 @@ +{ + "kind": "singleType", + "collectionName": "websites", + "info": { + "singularName": "website", + "pluralName": "websites", + "displayName": "Website", + "description": "" + }, + "options": { + "draftAndPublish": false + }, + "pluginOptions": {}, + "attributes": { + "website": { + "displayName": "Website in Menu", + "type": "component", + "repeatable": true, + "component": "websites.website-in-menu" + } + } +} diff --git a/src/api/website/controllers/website.ts b/src/api/website/controllers/website.ts new file mode 100644 index 0000000..88c411d --- /dev/null +++ b/src/api/website/controllers/website.ts @@ -0,0 +1,7 @@ +/** + * website controller + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreController("api::website.website"); diff --git a/src/api/website/routes/website.ts b/src/api/website/routes/website.ts new file mode 100644 index 0000000..722926b --- /dev/null +++ b/src/api/website/routes/website.ts @@ -0,0 +1,7 @@ +/** + * website router + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreRouter("api::website.website"); diff --git a/src/api/website/services/website.ts b/src/api/website/services/website.ts new file mode 100644 index 0000000..ee4d3ed --- /dev/null +++ b/src/api/website/services/website.ts @@ -0,0 +1,7 @@ +/** + * website service + */ + +import { factories } from "@strapi/strapi"; + +export default factories.createCoreService("api::website.website"); diff --git a/src/components/address/structured-address.json b/src/components/address/structured-address.json new file mode 100644 index 0000000..99d9fbb --- /dev/null +++ b/src/components/address/structured-address.json @@ -0,0 +1,28 @@ +{ + "collectionName": "components_address_structured_addresses", + "info": { + "displayName": "Structured Address", + "description": "Address fields matching HTML autocomplete attributes" + }, + "attributes": { + "givenName": { + "type": "string" + }, + "familyName": { + "type": "string" + }, + "streetAddress": { + "type": "string" + }, + "postalCode": { + "type": "string" + }, + "addressLevel2": { + "type": "string" + }, + "country": { + "type": "string", + "default": "DE" + } + } +} diff --git a/src/components/products/cart.json b/src/components/products/cart.json new file mode 100644 index 0000000..5d9874a --- /dev/null +++ b/src/components/products/cart.json @@ -0,0 +1,21 @@ +{ + "collectionName": "components_products_carts", + "info": { + "displayName": "cart", + "icon": "stack", + "description": "" + }, + "options": {}, + "attributes": { + "product": { + "type": "relation", + "relation": "oneToOne", + "target": "api::product.product" + }, + "count": { + "type": "integer", + "default": 1, + "min": 1 + } + } +} diff --git a/src/components/websites/website-in-menu.json b/src/components/websites/website-in-menu.json new file mode 100644 index 0000000..991ed82 --- /dev/null +++ b/src/components/websites/website-in-menu.json @@ -0,0 +1,26 @@ +{ + "collectionName": "components_websites_website_in_menus", + "info": { + "displayName": "Website in Menu", + "icon": "file", + "description": "" + }, + "options": {}, + "attributes": { + "menu": { + "type": "string", + "required": true + }, + "showInHeader": { + "type": "boolean", + "default": true + }, + "showInFooter": { + "type": "boolean", + "default": true + }, + "richtext": { + "type": "blocks" + } + } +} diff --git a/src/extensions/.gitkeep b/src/extensions/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/extensions/documentation/config/settings.json b/src/extensions/documentation/config/settings.json new file mode 100644 index 0000000..ac399d7 --- /dev/null +++ b/src/extensions/documentation/config/settings.json @@ -0,0 +1,30 @@ +{ + "openapi": "3.0.1", + "info": { + "version": "1.0.0", + "title": "MUELLERPTINTS. Paperwork", + "description": "API Documentation for MUELLERPRINTS. Paperwork", + "termsOfService": false, + "contact": false, + "license": false + }, + "x-strapi-config": { + "plugins": [], + "path": "/documentation" + }, + "servers": [ + { + "url": "https://localhost:8443/api", + "description": "Docker Development" + }, + { + "url": "http://localhost:5555/api", + "description": "Local Development" + } + ], + "security": [ + { + "bearerAuth": [] + } + ] +} diff --git a/src/extensions/documentation/documentation/1.0.0/full_documentation.json b/src/extensions/documentation/documentation/1.0.0/full_documentation.json new file mode 100644 index 0000000..f80bcf5 --- /dev/null +++ b/src/extensions/documentation/documentation/1.0.0/full_documentation.json @@ -0,0 +1,30776 @@ +{ + "openapi": "3.0.1", + "info": { + "version": "1.0.0", + "title": "MUELLERPTINTS. Paperwork", + "description": "API Documentation for MUELLERPRINTS. Paperwork", + "termsOfService": false, + "contact": { + "name": "Michael W. Czechowski", + "email": "mail@dailysh.it", + "url": "https://dailysh.it" + }, + "license": "Copyright (C) 2024 Michael W. Czechowski", + "externalDocs": false, + "x-generation-date": "2025-03-14T11:37:20.710Z" + }, + "x-strapi-config": { + "plugins": [ + "upload" + ], + "path": "/documentation" + }, + "servers": [ + { + "url": "/api", + "description": "Docker Container" + }, + { + "url": "http://localhost:5555/api", + "description": "Local Development" + } + ], + "security": [ + { + "bearerAuth": [] + } + ], + "externalDocs": { + "description": "Find out more", + "url": "https://docs.strapi.io/developer-docs/latest/getting-started/introduction.html" + }, + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT" + } + }, + "schemas": { + "Error": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "data": { + "nullable": true, + "oneOf": [ + { + "type": "object" + }, + { + "type": "array", + "items": { + "type": "object" + } + } + ] + }, + "error": { + "type": "object", + "properties": { + "status": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "message": { + "type": "string" + }, + "details": { + "type": "object" + } + } + } + } + }, + "ConfigRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "properties": { + "Title": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "VAT": { + "type": "number", + "format": "float" + }, + "Header": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + }, + "Footer": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + } + } + } + } + }, + "ConfigListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Config" + } + } + }, + "ConfigListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ConfigListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "Config": { + "type": "object", + "properties": { + "Title": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "VAT": { + "type": "number", + "format": "float" + }, + "Header": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "prefix": { + "type": "string" + }, + "suffix": { + "type": "string" + }, + "images": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "images": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "pathId": { + "type": "integer" + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "children": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "files": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "path": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "name": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "totalPrice": { + "type": "number", + "format": "float" + }, + "cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "binding": { + "type": "string", + "enum": [ + "Fadenheftung", + "Steppstich" + ] + }, + "slides": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "copyText": {}, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "sort": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "description": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pages": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "ruling": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "slug": { + "type": "string" + }, + "images": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "product_cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "product_pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "rulings": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "pages": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "Footer": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "ConfigResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Config" + } + } + }, + "ConfigResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ConfigResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "ContentRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "properties": { + "production": {} + } + } + } + }, + "ContentListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Content" + } + } + }, + "ContentListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "Content": { + "type": "object", + "properties": { + "production": {}, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "ContentResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Content" + } + } + }, + "ContentResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ContentResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "CustomerRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "address": { + "type": "string" + } + } + } + } + }, + "CustomerListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Customer" + } + } + }, + "CustomerListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomerListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "Customer": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "address": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "CustomerResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Customer" + } + } + }, + "CustomerResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/CustomerResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "DeliveryRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "description": { + "type": "string" + } + } + } + } + }, + "DeliveryListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Delivery" + } + } + }, + "DeliveryListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DeliveryListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "Delivery": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "description": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "DeliveryResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Delivery" + } + } + }, + "DeliveryResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/DeliveryResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "LegalRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "properties": { + "imprint": { + "type": "string" + }, + "contact": { + "type": "string" + }, + "terms": { + "type": "string" + }, + "delivery": { + "type": "string" + }, + "payment": { + "type": "string" + }, + "privacy": { + "type": "string" + } + } + } + } + }, + "LegalListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Legal" + } + } + }, + "LegalListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LegalListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "Legal": { + "type": "object", + "properties": { + "imprint": { + "type": "string" + }, + "contact": { + "type": "string" + }, + "terms": { + "type": "string" + }, + "delivery": { + "type": "string" + }, + "payment": { + "type": "string" + }, + "privacy": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "LegalResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Legal" + } + } + }, + "LegalResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/LegalResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "OrderRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "properties": { + "date": { + "type": "string", + "format": "date" + }, + "customer": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "invoice": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "deliveryNote": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "hash": { + "type": "string" + }, + "email": { + "type": "string" + }, + "delivery": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "payment": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "VAT": { + "type": "number", + "format": "float" + }, + "subtotal": { + "type": "number", + "format": "float" + }, + "total": { + "type": "number", + "format": "float" + }, + "uuid": { + "type": "string" + }, + "cart": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProductsCartComponent" + } + }, + "paymentAuthorised": { + "type": "boolean" + }, + "paymentStatus": { + "type": "string" + }, + "emailSent": { + "type": "boolean" + }, + "acceptedTermsAndConditionsAt": { + "type": "string", + "format": "date-time" + }, + "invoiceSent": { + "type": "boolean" + }, + "deliveryNoteSent": { + "type": "boolean" + }, + "invoiceNumber": { + "type": "string" + }, + "deliveryNoteNumber": { + "type": "string" + }, + "deliveryTrackingNumber": { + "type": "string" + }, + "deliveryAddress": { + "type": "string" + }, + "invoiceAddress": { + "type": "string" + } + } + } + } + }, + "OrderListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Order" + } + } + }, + "OrderListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OrderListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "Order": { + "type": "object", + "properties": { + "date": { + "type": "string", + "format": "date" + }, + "customer": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "address": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "invoice": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "pathId": { + "type": "integer" + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "children": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "files": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "path": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "deliveryNote": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "hash": { + "type": "string" + }, + "email": { + "type": "string" + }, + "delivery": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "description": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "payment": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "description": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "VAT": { + "type": "number", + "format": "float" + }, + "subtotal": { + "type": "number", + "format": "float" + }, + "total": { + "type": "number", + "format": "float" + }, + "uuid": { + "type": "string" + }, + "cart": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProductsCartComponent" + } + }, + "paymentAuthorised": { + "type": "boolean" + }, + "paymentStatus": { + "type": "string" + }, + "emailSent": { + "type": "boolean" + }, + "acceptedTermsAndConditionsAt": { + "type": "string", + "format": "date-time" + }, + "invoiceSent": { + "type": "boolean" + }, + "deliveryNoteSent": { + "type": "boolean" + }, + "invoiceNumber": { + "type": "string" + }, + "deliveryNoteNumber": { + "type": "string" + }, + "deliveryTrackingNumber": { + "type": "string" + }, + "deliveryAddress": { + "type": "string" + }, + "invoiceAddress": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "OrderResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Order" + } + } + }, + "OrderResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/OrderResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "ProductsCartComponent": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "product": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "totalPrice": { + "type": "number", + "format": "float" + }, + "cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "binding": { + "type": "string", + "enum": [ + "Fadenheftung", + "Steppstich" + ] + }, + "slides": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "copyText": {}, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "sort": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "description": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pages": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "ruling": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "slug": { + "type": "string" + }, + "images": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "images": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "name": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "product_cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "product_pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "count": { + "type": "integer" + } + } + }, + "PaymentRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "description": { + "type": "string" + } + } + } + } + }, + "PaymentListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Payment" + } + } + }, + "PaymentListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PaymentListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "Payment": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "description": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "PaymentResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Payment" + } + } + }, + "PaymentResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/PaymentResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "ProductRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "totalPrice": { + "type": "number", + "format": "float" + }, + "cover": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "pattern": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "pages": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "ruling": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "slug": { + "type": "string" + }, + "images": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + } + } + } + }, + "ProductListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Product" + } + } + }, + "ProductListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProductListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "Product": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "totalPrice": { + "type": "number", + "format": "float" + }, + "cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "binding": { + "type": "string", + "enum": [ + "Fadenheftung", + "Steppstich" + ] + }, + "slides": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "pathId": { + "type": "integer" + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "children": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "files": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "path": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "copyText": {}, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "totalPrice": { + "type": "number", + "format": "float" + }, + "cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "description": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pages": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "ruling": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "slug": { + "type": "string" + }, + "images": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "images": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "name": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "product_cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "product_pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "sort": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "pages": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "ruling": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "slug": { + "type": "string" + }, + "images": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "ProductResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Product" + } + } + }, + "ProductResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ProductResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "ProductConfigRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "properties": { + "prefix": { + "type": "string" + }, + "suffix": { + "type": "string" + }, + "images": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + }, + "rulings": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + }, + "pages": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + } + } + } + } + }, + "ProductConfigListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/ProductConfig" + } + } + }, + "ProductConfigListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProductConfigListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "ProductConfig": { + "type": "object", + "properties": { + "prefix": { + "type": "string" + }, + "suffix": { + "type": "string" + }, + "images": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "images": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "pathId": { + "type": "integer" + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "children": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "files": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "path": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "name": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "totalPrice": { + "type": "number", + "format": "float" + }, + "cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "binding": { + "type": "string", + "enum": [ + "Fadenheftung", + "Steppstich" + ] + }, + "slides": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "copyText": {}, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "sort": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "description": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pages": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "ruling": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "slug": { + "type": "string" + }, + "images": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "product_cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "product_pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "rulings": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "pages": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "ProductConfigResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/ProductConfig" + } + } + }, + "ProductConfigResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ProductConfigResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "ProductCoverRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "binding": { + "type": "string", + "enum": [ + "Fadenheftung", + "Steppstich" + ] + }, + "slides": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + }, + "copyText": {}, + "image": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "icon": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + }, + "sort": { + "type": "integer" + } + } + } + } + }, + "ProductCoverListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/ProductCover" + } + } + }, + "ProductCoverListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProductCoverListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "ProductCover": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "binding": { + "type": "string", + "enum": [ + "Fadenheftung", + "Steppstich" + ] + }, + "slides": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "pathId": { + "type": "integer" + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "children": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "files": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "path": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "copyText": {}, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "totalPrice": { + "type": "number", + "format": "float" + }, + "cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "binding": { + "type": "string", + "enum": [ + "Fadenheftung", + "Steppstich" + ] + }, + "slides": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "copyText": {}, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "sort": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "description": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pages": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "ruling": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "slug": { + "type": "string" + }, + "images": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "images": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "name": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "product_cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "product_pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "sort": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "ProductCoverResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/ProductCover" + } + } + }, + "ProductCoverResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ProductCoverResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "ProductImageRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "properties": { + "images": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + }, + "name": { + "type": "string" + }, + "products": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + }, + "product_cover": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "product_pattern": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + } + } + } + }, + "ProductImageListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/ProductImage" + } + } + }, + "ProductImageListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProductImageListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "ProductImage": { + "type": "object", + "properties": { + "images": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "pathId": { + "type": "integer" + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "children": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "files": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "path": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "name": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "totalPrice": { + "type": "number", + "format": "float" + }, + "cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "binding": { + "type": "string", + "enum": [ + "Fadenheftung", + "Steppstich" + ] + }, + "slides": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "copyText": {}, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "sort": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "description": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pages": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "ruling": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "slug": { + "type": "string" + }, + "images": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "images": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "name": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "product_cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "product_pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "product_cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "product_pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "ProductImageResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/ProductImage" + } + } + }, + "ProductImageResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ProductImageResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "ProductPageRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + } + } + } + } + }, + "ProductPageListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/ProductPage" + } + } + }, + "ProductPageListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProductPageListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "ProductPage": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "totalPrice": { + "type": "number", + "format": "float" + }, + "cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "binding": { + "type": "string", + "enum": [ + "Fadenheftung", + "Steppstich" + ] + }, + "slides": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "pathId": { + "type": "integer" + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "children": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "files": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "path": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "copyText": {}, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "sort": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "description": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pages": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "ruling": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "slug": { + "type": "string" + }, + "images": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "images": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "name": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "product_cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "product_pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "ProductPageResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/ProductPage" + } + } + }, + "ProductPageResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ProductPageResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "ProductPatternRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + }, + "description": { + "type": "string" + }, + "products": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + } + } + } + } + }, + "ProductPatternListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/ProductPattern" + } + } + }, + "ProductPatternListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProductPatternListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "ProductPattern": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "pathId": { + "type": "integer" + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "children": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "files": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "path": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "description": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "totalPrice": { + "type": "number", + "format": "float" + }, + "cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "binding": { + "type": "string", + "enum": [ + "Fadenheftung", + "Steppstich" + ] + }, + "slides": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "copyText": {}, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "sort": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "description": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pages": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "ruling": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "slug": { + "type": "string" + }, + "images": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "images": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "name": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "product_cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "product_pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "ProductPatternResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/ProductPattern" + } + } + }, + "ProductPatternResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ProductPatternResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "ProductRulingRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + }, + "icon": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + } + } + } + }, + "ProductRulingListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/ProductRuling" + } + } + }, + "ProductRulingListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProductRulingListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "ProductRuling": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "totalPrice": { + "type": "number", + "format": "float" + }, + "cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "binding": { + "type": "string", + "enum": [ + "Fadenheftung", + "Steppstich" + ] + }, + "slides": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "pathId": { + "type": "integer" + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "children": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "files": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "path": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "copyText": {}, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "sort": { + "type": "integer" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "description": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "pages": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "ruling": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "price": { + "type": "number", + "format": "float" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "slug": { + "type": "string" + }, + "images": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "images": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "name": { + "type": "string" + }, + "products": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "product_cover": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "product_pattern": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "icon": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "ProductRulingResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/ProductRuling" + } + } + }, + "ProductRulingResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ProductRulingResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "VatRequest": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "percent": { + "type": "integer" + }, + "decimal": { + "type": "number", + "format": "float" + } + } + } + } + }, + "VatListResponseDataItem": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Vat" + } + } + }, + "VatListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VatListResponseDataItem" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer", + "minimum": 25 + }, + "pageCount": { + "type": "integer", + "maximum": 1 + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "Vat": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "percent": { + "type": "integer" + }, + "decimal": { + "type": "number", + "format": "float" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "firstname": { + "type": "string" + }, + "lastname": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "resetPasswordToken": { + "type": "string" + }, + "registrationToken": { + "type": "string" + }, + "isActive": { + "type": "boolean" + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + }, + "users": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "actionParameters": {}, + "subject": { + "type": "string" + }, + "properties": {}, + "conditions": {}, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + } + }, + "blocked": { + "type": "boolean" + }, + "preferedLanguage": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + } + } + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "type": "object", + "properties": {} + } + } + } + } + } + } + }, + "VatResponseDataObject": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "attributes": { + "$ref": "#/components/schemas/Vat" + } + } + }, + "VatResponse": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/VatResponseDataObject" + }, + "meta": { + "type": "object" + } + } + }, + "UploadFile": { + "properties": { + "id": { + "type": "number" + }, + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "number", + "format": "integer" + }, + "height": { + "type": "number", + "format": "integer" + }, + "formats": { + "type": "number" + }, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "double" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": { + "type": "object" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + } + } + }, + "paths": { + "/config": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Config" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/config" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Config" + ], + "parameters": [], + "operationId": "put/config", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Config" + ], + "parameters": [], + "operationId": "delete/config" + } + }, + "/content": { + "get": { + "responses": { + "200": { + "description": "Returns all content entries", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Content" + } + } + } + } + } + }, + "tags": [ + "Content" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/content", + "description": "Get all content entries" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Content" + ], + "parameters": [], + "operationId": "put/content", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContentRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Content" + ], + "parameters": [], + "operationId": "delete/content" + } + }, + "/customers": { + "get": { + "responses": { + "200": { + "description": "Returns all customers", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Customer" + } + } + } + } + } + }, + "tags": [ + "Customer" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/customers", + "description": "Get all customers" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Customer" + ], + "parameters": [], + "operationId": "post/customers", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerRequest" + } + } + } + } + } + }, + "/customers/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Customer" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/customers/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Customer" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/customers/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Customer" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/customers/{id}" + } + }, + "/deliveries": { + "get": { + "responses": { + "200": { + "description": "Returns all deliveries", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Delivery" + } + } + } + } + } + }, + "tags": [ + "Delivery" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/deliveries", + "description": "Get all deliveries" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeliveryResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Delivery" + ], + "parameters": [], + "operationId": "post/deliveries", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeliveryRequest" + } + } + } + } + } + }, + "/deliveries/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeliveryResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Delivery" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/deliveries/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeliveryResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Delivery" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/deliveries/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeliveryRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Delivery" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/deliveries/{id}" + } + }, + "/legal": { + "get": { + "responses": { + "200": { + "description": "Returns all legal documents", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Legal" + } + } + } + } + } + }, + "tags": [ + "Legal" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/legal", + "description": "Get all legal documents" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LegalResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Legal" + ], + "parameters": [], + "operationId": "put/legal", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LegalRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Legal" + ], + "parameters": [], + "operationId": "delete/legal" + } + }, + "/orders": { + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [], + "operationId": "post/orders", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + }, + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/orders" + } + }, + "/orders/webhook": { + "post": { + "responses": { + "200": { + "description": "Webhook processed successfully" + }, + "500": { + "description": "Internal server error" + } + }, + "tags": [ + "Order" + ], + "parameters": [], + "operationId": "post/orders/webhook", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "PayPal webhook event payload" + } + } + } + }, + "description": "Handle PayPal webhook events" + } + }, + "/orders/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/orders/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/orders/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{uuid}/cart": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/orders/{uuid}/cart" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "string" + } + } + ], + "operationId": "put/orders/{uuid}/cart" + } + }, + "/orders/{uuid}/add-product/{productId}": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "productId", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/orders/{uuid}/add-product/{productId}" + } + }, + "/orders/{uuid}/remove-product/{productId}": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "productId", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/orders/{uuid}/remove-product/{productId}" + } + }, + "/orders/{uuid}/checkout": { + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "string" + } + } + ], + "operationId": "post/orders/{uuid}/checkout" + } + }, + "/orders/{uuid}/generate-invoice": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "string" + } + } + ], + "operationId": "put/orders/{uuid}/generate-invoice", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{uuid}/generate-delivery-note": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "string" + } + } + ], + "operationId": "put/orders/{uuid}/generate-delivery-note", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{uuid}/send-invoice": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "string" + } + } + ], + "operationId": "put/orders/{uuid}/send-invoice", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/orders/{uuid}/send-delivery-note": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Order" + ], + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "string" + } + } + ], + "operationId": "put/orders/{uuid}/send-delivery-note", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderRequest" + } + } + } + } + } + }, + "/payments": { + "get": { + "responses": { + "200": { + "description": "Returns all payments", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Payment" + } + } + } + } + } + }, + "tags": [ + "Payment" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/payments", + "description": "Get all payments" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Payment" + ], + "parameters": [], + "operationId": "post/payments", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + } + } + } + } + }, + "/payments/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Payment" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/payments/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Payment" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/payments/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Payment" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/payments/{id}" + } + }, + "/products": { + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [], + "operationId": "post/products", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRequest" + } + } + } + } + }, + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/products" + } + }, + "/products/{id}": { + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/products/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRequest" + } + } + } + } + }, + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/products/{id}" + } + }, + "/products/{id}/variants/all": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/products/{id}/variants/all" + } + }, + "/products/{id}/variants/pattern": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/products/{id}/variants/pattern" + } + }, + "/products/{id}/variants": { + "get": { + "responses": { + "200": { + "description": "Returns product variants grouped by pages, cover, and ruling", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "pages": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "productVariant": { + "oneOf": [ + { + "$ref": "#/components/schemas/Product" + }, + { + "type": "null" + } + ] + } + } + } + }, + "cover": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "binding": { + "type": "string" + }, + "price": { + "type": "number" + }, + "productVariant": { + "oneOf": [ + { + "$ref": "#/components/schemas/Product" + }, + { + "type": "null" + } + ] + } + } + } + }, + "ruling": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "productVariant": { + "oneOf": [ + { + "$ref": "#/components/schemas/Product" + }, + { + "type": "null" + } + ] + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "Error message" + } + } + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/products/{id}/variants", + "description": "Get product variants grouped by pages, cover, and ruling" + } + }, + "/products/publish": { + "post": { + "responses": { + "200": { + "description": "Successfully published/unpublished products", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "published": { + "type": "integer", + "description": "Number of products published/unpublished" + }, + "dryRun": { + "type": "boolean", + "description": "Whether this was a dry run" + } + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "Error message" + } + } + } + } + } + } + }, + "tags": [ + "Product" + ], + "parameters": [], + "operationId": "post/products/publish", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "filters" + ], + "properties": { + "filters": { + "type": "object", + "description": "Filters to select products (supports pattern, cover, ruling, pages)" + }, + "publish": { + "type": "boolean", + "description": "Whether to publish (true) or unpublish (false)", + "default": true + }, + "dryRun": { + "type": "boolean", + "description": "If true, no changes will be made but count will be returned", + "default": false + } + } + } + } + } + }, + "description": "Publish or unpublish products by filter" + } + }, + "/product-configs": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductConfigListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-config" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/product-configs" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductConfigResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-config" + ], + "parameters": [], + "operationId": "post/product-configs", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductConfigRequest" + } + } + } + } + } + }, + "/product-configs/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductConfigResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-config" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/product-configs/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductConfigResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-config" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/product-configs/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductConfigRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-config" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/product-configs/{id}" + } + }, + "/product-covers": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductCoverListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-cover" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/product-covers" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductCoverResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-cover" + ], + "parameters": [], + "operationId": "post/product-covers", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductCoverRequest" + } + } + } + } + } + }, + "/product-covers/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductCoverResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-cover" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/product-covers/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductCoverResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-cover" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/product-covers/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductCoverRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-cover" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/product-covers/{id}" + } + }, + "/product-images": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductImageListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-image" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/product-images" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductImageResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-image" + ], + "parameters": [], + "operationId": "post/product-images", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductImageRequest" + } + } + } + } + } + }, + "/product-images/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductImageResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-image" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/product-images/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductImageResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-image" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/product-images/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductImageRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-image" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/product-images/{id}" + } + }, + "/product-pages": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPageListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-page" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/product-pages" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPageResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-page" + ], + "parameters": [], + "operationId": "post/product-pages", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPageRequest" + } + } + } + } + } + }, + "/product-pages/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPageResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-page" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/product-pages/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPageResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-page" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/product-pages/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPageRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-page" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/product-pages/{id}" + } + }, + "/product-patterns": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPatternListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-pattern" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/product-patterns" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPatternResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-pattern" + ], + "parameters": [], + "operationId": "post/product-patterns", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPatternRequest" + } + } + } + } + } + }, + "/product-patterns/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPatternResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-pattern" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/product-patterns/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPatternResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-pattern" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/product-patterns/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductPatternRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-pattern" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/product-patterns/{id}" + } + }, + "/product-rulings": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRulingListResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-ruling" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/product-rulings" + }, + "post": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRulingResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-ruling" + ], + "parameters": [], + "operationId": "post/product-rulings", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRulingRequest" + } + } + } + } + } + }, + "/product-rulings/{id}": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRulingResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-ruling" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "get/product-rulings/{id}" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRulingResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-ruling" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "put/product-rulings/{id}", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductRulingRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Product-ruling" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "number" + } + } + ], + "operationId": "delete/product-rulings/{id}" + } + }, + "/vat": { + "get": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VatResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Vat" + ], + "parameters": [ + { + "name": "sort", + "in": "query", + "description": "Sort by attributes ascending (asc) or descending (desc)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "pagination[withCount]", + "in": "query", + "description": "Return page/pageSize (default: true)", + "deprecated": false, + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pagination[page]", + "in": "query", + "description": "Page number (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[pageSize]", + "in": "query", + "description": "Page size (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[start]", + "in": "query", + "description": "Offset value (default: 0)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "pagination[limit]", + "in": "query", + "description": "Number of entities to return (default: 25)", + "deprecated": false, + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "fields", + "in": "query", + "description": "Fields to return (ex: title,author)", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "populate", + "in": "query", + "description": "Relations to return", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filters", + "in": "query", + "description": "Filters to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "object", + "additionalProperties": true + }, + "style": "deepObject" + }, + { + "name": "locale", + "in": "query", + "description": "Locale to apply", + "deprecated": false, + "required": false, + "schema": { + "type": "string" + } + } + ], + "operationId": "get/vat" + }, + "put": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VatResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Vat" + ], + "parameters": [], + "operationId": "put/vat", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VatRequest" + } + } + } + } + }, + "delete": { + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int64" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "tags": [ + "Vat" + ], + "parameters": [], + "operationId": "delete/vat" + } + }, + "/upload": { + "post": { + "description": "Upload files", + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UploadFile" + } + } + } + } + } + }, + "summary": "", + "tags": [ + "Upload - File" + ], + "requestBody": { + "description": "Upload files", + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "required": [ + "files" + ], + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "The folder where the file(s) will be uploaded to (only supported on strapi-provider-upload-aws-s3)." + }, + "refId": { + "type": "string", + "description": "The ID of the entry which the file(s) will be linked to" + }, + "ref": { + "type": "string", + "description": "The unique ID (uid) of the model which the file(s) will be linked to (api::restaurant.restaurant)." + }, + "field": { + "type": "string", + "description": "The field of the entry which the file(s) will be precisely linked to." + }, + "files": { + "type": "array", + "items": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + } + } + }, + "/upload?id={id}": { + "post": { + "parameters": [ + { + "name": "id", + "in": "query", + "description": "File id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "description": "Upload file information", + "responses": { + "200": { + "description": "response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UploadFile" + } + } + } + } + } + }, + "summary": "", + "tags": [ + "Upload - File" + ], + "requestBody": { + "description": "Upload files", + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "fileInfo": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + } + } + }, + "files": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + } + }, + "/upload/files": { + "get": { + "tags": [ + "Upload - File" + ], + "responses": { + "200": { + "description": "Get a list of files", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UploadFile" + } + } + } + } + } + } + } + }, + "/upload/files/{id}": { + "get": { + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "string" + } + } + ], + "tags": [ + "Upload - File" + ], + "responses": { + "200": { + "description": "Get a specific file", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UploadFile" + } + } + } + } + } + }, + "delete": { + "parameters": [ + { + "name": "id", + "in": "path", + "description": "", + "deprecated": false, + "required": true, + "schema": { + "type": "string" + } + } + ], + "tags": [ + "Upload - File" + ], + "responses": { + "200": { + "description": "Delete a file", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UploadFile" + } + } + } + } + } + } + } + } +} diff --git a/src/extensions/documentation/public/index.html b/src/extensions/documentation/public/index.html new file mode 100644 index 0000000..606375b --- /dev/null +++ b/src/extensions/documentation/public/index.html @@ -0,0 +1,70 @@ + + + + + Swagger UI + + + + + + + +
+ + + + + + diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..fa273e6 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,18 @@ +export default { + /** + * An asynchronous register function that runs before + * your application is initialized. + * + * This gives you an opportunity to extend code. + */ + register(/*{ strapi }*/) {}, + + /** + * An asynchronous bootstrap function that runs before + * your application gets started. + * + * This gives you an opportunity to set up your data model, + * run jobs, or perform some special logic. + */ + bootstrap(/*{ strapi }*/) {} +}; diff --git a/src/services/MailApi.ts b/src/services/MailApi.ts new file mode 100644 index 0000000..6a2b1ed --- /dev/null +++ b/src/services/MailApi.ts @@ -0,0 +1,92 @@ +import { mailApiUrl } from "../../config/constants"; +import type { Response } from "node-fetch"; +import FormData from "form-data"; + +const logger = strapi.log.info; +const verbose = strapi.log.verbose; +const debug = strapi.log.verbose; + +class MailApi { + baseUrl: string; + headers: Headers; + + constructor(options: MailApiOptions) { + this.baseUrl = options.baseUrl; + this.headers = options.defaultHeaders ?? {}; + } + + async sendTextMessage(body: MessageBody): Promise { + strapi.log.debug(`app:d:mail-api: Sending text message`); + try { + await this.postRequest("/v1/send/message", body); + } catch (error) { + throw error; + } + } + + async sendPdf(body: PdfMessageBody): Promise { + strapi.log.debug(`app:d:mail-api: Sending PDF`); + try { + await this.postPdfRequest("/v1/send/pdf", body); + } catch (error) { + throw error; + } + } + + private async postRequest(endpoint: string, body: Record): Promise { + const response = (await strapi.fetch(`${this.baseUrl}${endpoint}`, { + method: "POST", + headers: { + ...this.headers, + "content-type": "application/json" + }, + body: JSON.stringify(body) + })) as Response; + + if (!response.ok) { + throw new Error(`Failed to send text message: ${response.statusText}`); + } + } + + private async postPdfRequest(endpoint: string, body: PdfMessageBody): Promise { + const formData = new FormData(); + formData.append("subject", body.subject); + formData.append("message", body.message); + formData.append("to_email", body.to_email); + formData.append("pdf_blob", body.pdf_blob); + + const response = (await strapi.fetch(`${this.baseUrl}${endpoint}`, { + method: "POST", + headers: { + ...this.headers + }, + body: formData + })) as Response; + + if (!response.ok) { + throw new Error(`Failed to send PDF: ${response.statusText}`); + } + } +} + +interface MailApiOptions { + baseUrl: string; + defaultHeaders?: Headers; +} + +export interface MessageBody { + subject: string; + message: string; + html?: string; + to_email: string; +} + +export interface PdfMessageBody extends MessageBody { + pdf_blob: Blob; +} + +type Headers = Record; + +export const mailApi = new MailApi({ + baseUrl: mailApiUrl +}); diff --git a/src/services/PayPalApi.ts b/src/services/PayPalApi.ts new file mode 100644 index 0000000..c121839 --- /dev/null +++ b/src/services/PayPalApi.ts @@ -0,0 +1,165 @@ +import { + Client, + Environment, + LogLevel, + OrdersController, + CheckoutPaymentIntent, + OrderRequest, + OrderApplicationContextShippingPreference, + Item +} from "@paypal/paypal-server-sdk"; +import { paypalClientId, paypalClientSecret, paypalEnvironment, vatIncludedDecimal, vatDecimalExcluded } from "../../config/constants"; +import { Order } from "../../types"; +import { calculateTotalProductPrice } from "../api/product/services/product"; + +class PayPalApi { + private readonly client: Client; + private readonly ordersController: OrdersController; + + constructor(clientId: string, clientSecret: string, environment: Environment) { + this.client = new Client({ + clientCredentialsAuthCredentials: { + oAuthClientId: clientId, + oAuthClientSecret: clientSecret + }, + timeout: 0, + environment, + logging: { + logLevel: LogLevel.Info, + logRequest: { logBody: true }, + logResponse: { logHeaders: true } + } + }); + this.ordersController = new OrdersController(this.client); + } + + async createSessionOrThrow(returnUrl: string, order: Order) { + if (!order.total) throw new Error("Cart is empty or has no total"); + + const items = order.cart.map((item) => { + const totalProductPrice = calculateTotalProductPrice(item.product); + const amount = totalProductPrice / vatIncludedDecimal; + const tax = totalProductPrice - amount; + + return { + name: item.product.name, + unitAmount: { + currencyCode: "EUR", + value: amount.toFixed(2) + }, + tax: { + currencyCode: "EUR", + value: tax.toFixed(2) + }, + quantity: item.count.toString() + } as Item; + }); + + try { + const collect = { + body: { + intent: CheckoutPaymentIntent.Capture, + purchaseUnits: [ + { + // items, + referenceId: order.uuid, + amount: { + currencyCode: "EUR", + value: order.total.toFixed(2), + breakdown: { + itemTotal: { + currencyCode: "EUR", + value: (Math.round((order.subtotal / vatIncludedDecimal) * 100) / 100).toFixed(2) + }, + taxTotal: { + currencyCode: "EUR", + value: order.VAT.toFixed(2) + }, + shipping: order.delivery + ? { + currencyCode: "EUR", + value: order.delivery.price.toFixed(2) + } + : undefined + } + }, + shipping: { + name: { + fullName: order.deliveryAddress.split("\n")[0] + }, + address: { + addressLine1: order.deliveryAddress.split("\n")[1], + postalCode: order.deliveryAddress.split("\n")[2].slice(0, 5), + adminArea2: order.deliveryAddress.split("\n")[2].slice(6), + countryCode: "DE" + } + }, + customId: order.uuid, + invoiceId: order.invoiceNumber + } + ], + applicationContext: { + returnUrl: returnUrl, + cancelUrl: returnUrl, + shippingPreference: OrderApplicationContextShippingPreference.SetProvidedAddress + } + } as OrderRequest, + prefer: "return=minimal" + }; + + strapi.log.silly("app:d:paypal-api: Creating PayPal order " + JSON.stringify({ collect })); + + const { body, ...httpResponse } = await this.ordersController.ordersCreate(collect); + const sessionData = JSON.parse(body as string); + + strapi.log.info("app:i:paypal-api: " + JSON.stringify({ session: sessionData })); + + return { + id: sessionData.id, + links: sessionData.links + }; + } catch (error) { + strapi.log.error("app:e:paypal-api: " + JSON.stringify({ error })); + throw error; + } + } + + async checkPaymentStatus(redirect: { orderID: string }) { + try { + const collect = { + id: redirect.orderID, + prefer: "return=minimal" + }; + + const { body } = await this.ordersController.ordersCapture(collect); + const captureResult = JSON.parse(body as string); + strapi.log.info("app:i:paypal-api: " + JSON.stringify({ captureResult })); + + return captureResult; + } catch (error) { + return "/result/error"; + } + } + + async handleWebhook(req: any) { + // Implement PayPal webhook validation and processing + strapi.log.verbose("app:i:paypal-api: " + JSON.stringify({ req })); + + // Note: PayPal webhook handling requires specific implementation + // This is a placeholder and should be replaced with actual PayPal webhook validation + return { message: "Webhook received" }; + } + + getClientKey() { + // PayPal doesn't use a client key like Adyen, so we'll return the client ID + return paypalClientId; + } +} + +export const paypalApi = new PayPalApi(paypalClientId, paypalClientSecret, paypalEnvironment); + +export type PayPalApiOptions = { + clientId: string; + clientSecret: string; + environment: Environment; +}; diff --git a/src/services/PdfApi.ts b/src/services/PdfApi.ts new file mode 100644 index 0000000..da159b3 --- /dev/null +++ b/src/services/PdfApi.ts @@ -0,0 +1,56 @@ +import type { Response } from "node-fetch"; +import { pdfApiUrl } from "../../config/constants"; +import { PdfBody } from "../../types"; + +const logger = strapi.log.info; +const verbose = strapi.log.verbose; +const debug = strapi.log.verbose; + +class PdfApi { + baseUrl: string; + headers: Headers; + + constructor(options: PdfApiOptions) { + this.baseUrl = options.baseUrl; + this.headers = options.defaultHeaders ?? {}; + } + + async generateInvoice(body: PdfBody) { + try { + return await this.postRequest("/v1/invoice", body); + } catch (error) { + throw error; + } + } + + async generateDeliveryNote(body: PdfBody) { + try { + return await this.postRequest("/v1/shipping", body); + } catch (error) { + throw error; + } + } + + private async postRequest(endpoint: string, body: Record) { + const response = (await strapi.fetch(`${this.baseUrl}${endpoint}`, { + method: "POST", + headers: this.headers, + body: JSON.stringify(body) + })) as Response; + return await response.arrayBuffer(); + } +} + +interface PdfApiOptions { + baseUrl: string; + defaultHeaders?: Headers; +} + +type Headers = Record; + +export const pdfApi = new PdfApi({ + baseUrl: pdfApiUrl, + defaultHeaders: { + "content-type": "application/json" + } +}); diff --git a/src/templates/emailTemplates.ts b/src/templates/emailTemplates.ts new file mode 100644 index 0000000..4dff953 --- /dev/null +++ b/src/templates/emailTemplates.ts @@ -0,0 +1,441 @@ +export const invoiceEmailTemplate = { + subject: "MUELLERPRINTS Rechnungsnummer <%= invoiceNumber %>", + text: `Rechnungsnummer: <%= invoiceNumber %> +Ausstellungsdatum: <%= new Date(acceptedTermsAndConditionsAt).toLocaleDateString("de-DE") %> + +------------- + +Hallo <%= invoiceAddressStructured.givenName %>, + +vielen Dank für deinen Einkauf bei MUELLERPRINTS. + +Deine Bestellnummer: <%= id %> +Zur Bestellübersicht: <%= baseUrl %>/checkout/result/<%= uuid %> + + +Bestellte Artikel: +------------- +<% cart.forEach(function(item) { %> + <%= item.product.name %> + <% if (item.product.images && item.product.images.images && item.product.images.images.length > 0) { %> + Bild: <%= baseUrl %><%= item.product.images.images[0].formats.thumbnail.url %> + <% } %> + Menge: <%= item.count %> + Einzelpreis: <%= item.product.totalProductPrice.toFixed(2) %> EUR + Gesamtpreis: <%= (item.count * item.product.totalProductPrice).toFixed(2) %> EUR +<% }); %> + +<% if (deliveryAddressStructured) { %> +Lieferadresse: +<%= deliveryAddressStructured.givenName %> <%= deliveryAddressStructured.familyName %> +<%= deliveryAddressStructured.streetAddress %> +<%= deliveryAddressStructured.postalCode %> <%= deliveryAddressStructured.addressLevel2 %> +<% } %> + +Rechnung und Zahlung: +------------- + +Rechnungsadresse: +<%= invoiceAddressStructured.givenName %> <%= invoiceAddressStructured.familyName %> +<%= invoiceAddressStructured.streetAddress %> +<%= invoiceAddressStructured.postalCode %> <%= invoiceAddressStructured.addressLevel2 %> + +Zwischensumme: <%= subtotal.toFixed(2) %> EUR +Versandkosten: <%= delivery && delivery.price > 0 ? delivery.price.toFixed(2) + " EUR" : "KOSTENFREI" %> +Gesamtbetrag: <%= total.toFixed(2) %> EUR +inkl. MwSt. (19%): <%= VAT.toFixed(2) %> EUR + +<% if (baseUrl && invoice.url) { %> +Deine Rechnung kannst du jederzeit über diesen Link herunterladen: <%= baseUrl %><%= invoice.url %> +<% } %> + +Vielen Dank, dass du dich für MUELLERPRINTS entschieden hast. + +------------------ +MUELLERPRINTS +Max Müller +Rotenbergstraße 39, 70190 Stuttgart +T +49 (0)711/262 49 64 +paperwork@muellerprints.de`, + html: ` + + + + + Rechnung für Bestellung <%= invoiceNumber %> + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ MUELLERPRINTS PAPERWORK +
+ +

+ Vielen Dank für deinen Einkauf bei MUELLERPRINTS. +

+ + +
+

+ Rechnungsnummer: <%= invoiceNumber %> +

+

+ Ausstellungsdatum: <%= new Date(acceptedTermsAndConditionsAt).toLocaleDateString("de-DE") %> +

+

+ Deine Bestellnummer: <%= id %> +

+ <% if (deliveryTrackingNumber) { %> +

+ Sendungsverfolgung: <%= deliveryTrackingNumber %> +

+ <% } %> +
+ + + + + + <% if (deliveryAddress) { %> + + <% } %> + +
+

Rechnungsadresse:

+

+ <%= invoiceAddressStructured.givenName %> <%= invoiceAddressStructured.familyName %> + <%= invoiceAddressStructured.streetAddress %> + <%= invoiceAddressStructured.postalCode %> <%= invoiceAddressStructured.addressLevel2 %> +

+
+

Lieferadresse:

+

+ <%= deliveryAddress %> +

+
+ + +

Bestellte Artikel:

+ + + + + + + + + + + + <% cart.forEach(function(item) { %> + + + + + + + + <% }); %> + +
ArtikelMengeEinzelpreisGesamtpreis
+ <% if (item.product.images && item.product.images.images && item.product.images.images.length > 0) { %> + <%= item.product.name %> + <% } else { %> +
+ <% } %> +
<%= item.product.name %><%= item.count %><%= item.product.totalProductPrice.toFixed(2) %> EUR<%= (item.count * item.product.totalProductPrice).toFixed(2) %> EUR
+ + +

Rechnung und Zahlung:

+ + + + + + + + + + + + + +
+ Zwischensumme: + <%= subtotal.toFixed(2) %> EUR +
+ Versandkosten: + <%= delivery && delivery.price > 0 ? delivery.price.toFixed(2) + " EUR" : "KOSTENFREI" %> +
+ Gesamtbetrag: + <%= total.toFixed(2) %> EUR +
+ inkl. MwSt. (19%): + <%= VAT.toFixed(2) %> EUR +
+ + <% if (baseUrl && invoice.url) { %> + +
+

+ Deine Rechnung kannst du jederzeit über diesen Link herunterladen: + Rechnung <%= invoiceNumber %> herunterladen +

+
+ <% } %> + +

+ Vielen Dank, dass du dich für MUELLERPRINTS entschieden hast. +

+
+ + + + + +
+

+ MUELLERPRINTS
+ Max Müller
+ Rotenbergstraße 39, 70190 Stuttgart
+ T +49 (0)711/262 49 64
+ paperwork@muellerprints.de +

+
+ MUELLERPRINTS +
+
+ + + + + + +
+

+ Diese E-Mail wurde gesendet an <%= email %> +

+
+
+ + ` +}; + +export const deliveryNoteEmailTemplate = { + subject: "Your Delivery Note <%= deliveryNoteNumber %> from MUELLERPRINTS", + text: `Dear Customer, + +Thank you for your Your delivery note <%= deliveryNoteNumber %> is attached to this email. + +Delivery Details: +---------------- +<% if (deliveryTrackingNumber) { %>Tracking Number: <%= deliveryTrackingNumber %><% } %> + +Ordered Items: +---------------- +<% cart.forEach(function(item) { %> + <%= item.product.name %> + <% if (item.product.images && item.product.images.images && item.product.images.images.length > 0) { %> + Image: <%= baseUrl %><%= item.product.images.images[0].formats.thumbnail.url %> + <% } %> + Quantity: <%= item.count %> + Price: <%= item.product.totalProductPrice.toFixed(2) %> EUR + Total: <%= (item.count * item.product.totalProductPrice).toFixed(2) %> EUR +<% }); %> + +Delivery Address: +<%= deliveryAddressStructured.givenName %> <%= deliveryAddressStructured.familyName %> +<%= deliveryAddressStructured.streetAddress %> +<%= deliveryAddressStructured.postalCode %> <%= deliveryAddressStructured.addressLevel2 %> + +If you have any questions about your delivery, please don't hesitate to contact us. + +Best regards, +MUELLERPRINTS PAPERWORK + +------------------ +MUELLERPRINTS PAPERWORK +Max Müller +Rotenbergstraße 39, 70190 Stuttgart +T +49 (0)711/262 49 64 +paperwork@muellerprints.de`, + html: ` + + + + + Delivery Note #<%= deliveryNoteNumber %> + + + + + + +
+ + + + + + + + + + + + + + + +
+ MUELLERPRINTS PAPERWORK +
+

+ Your Delivery Information +

+ +
+

+ Delivery Note #<%= deliveryNoteNumber %> +

+ <% if (deliveryTrackingNumber) { %> +

+ Tracking Number: <%= deliveryTrackingNumber %> +

+ <% } %> +
+ + + + + + <% if (deliveryAddress && deliveryAddress !== invoiceAddress) { %> + + <% } %> + +
+

Billing Address:

+

+ <%= invoiceAddressStructured.givenName %> <%= invoiceAddressStructured.familyName %> + <%= invoiceAddressStructured.streetAddress %> + <%= invoiceAddressStructured.postalCode %> <%= invoiceAddressStructured.addressLevel2 %> +

+
+

Delivery Address:

+

+ <%= deliveryAddress %> +

+
+ + + + + + + + + + + + + + <% cart.forEach(function(item) { %> + + + + + + + + <% }); %> + +
ItemQuantityPriceTotal
+ <% if (item.product.images && item.product.images.images && item.product.images.images.length > 0) { %> + <%= item.product.name %> + <% } else { %> +
+ <% } %> +
<%= item.product.name %><%= item.count %><%= item.product.totalProductPrice.toFixed(2) %> EUR<%= (item.count * item.product.totalProductPrice).toFixed(2) %> EUR
+ + + + + + + + + + + + +
+ Subtotal: + <%= subtotal.toFixed(2) %> EUR +
+ VAT (19%): + <%= VAT.toFixed(2) %> EUR +
+ Total: + <%= total.toFixed(2) %> EUR +
+ + +
+

+ Your invoice is attached to this email. Please keep it for your records. +

+
+
+ + + + + +
+

+ MUELLERPRINTS PAPERWORK
+ Max Müller
+ Rotenbergstraße 39, 70190 Stuttgart
+ T +49 (0)711/262 49 64
+ paperwork@muellerprints.de +

+
+ MUELLERPRINTS +
+
+ + + + + + +
+

+ This email was sent to <%= email %> +

+
+
+ + ` +}; diff --git a/src/utils/createComponentLifecycle.ts b/src/utils/createComponentLifecycle.ts new file mode 100644 index 0000000..c8fb329 --- /dev/null +++ b/src/utils/createComponentLifecycle.ts @@ -0,0 +1,273 @@ +import { Strapi } from "@strapi/strapi"; +import { productDefaultParams } from "../api/product/services/product"; +import { ProductCover, ProductImage, ProductPages, ProductPattern, ProductRuling } from "../../types"; +import { formatSlug } from "./formatSlug"; +import { ID } from "@strapi/database/dist/types"; + +type ComponentEvent = { + action: "create" | "update" | "delete"; + params: { + data?: T; + where?: { id: number }; + select?: string[]; + populate?: string[]; + }; + state?: { + attribute?: string; + }; + result?: T; +}; + +export const createComponentLifecycle = ( + componentType: "cover" | "pattern" | "pages" | "ruling" | "image" +) => ({ + async afterCreate(event: ComponentEvent) { + const { result } = event; + strapi.log.verbose(`app:v:${componentType}-lifecycle: Created ${JSON.stringify({ componentType, id: result.id })}`); + + if (componentType === "image") { + return; + } + + try { + await generateNewProducts(strapi, componentType, parseInt(result.id as string)); + } catch (error) { + strapi.log.error(`app:e:${componentType}-lifecycle: Error generating products ${JSON.stringify({ error, componentId: result.id })}`); + } + }, + + async afterUpdate(event: ComponentEvent) { + const { result, params } = event; + + // Only update products if price changed + try { + await updateRelatedProducts(strapi, componentType, parseInt(result.id as string)); + } catch (error) { + strapi.log.error( + `app:e:${componentType}-lifecycle: Error updating products + ${JSON.stringify({ + error, + componentId: result.id + })}` + ); + } + }, + + async beforeDelete(event: ComponentEvent) { + const { id } = event.params.where; + try { + // Find all products using this component + strapi.log.debug( + `app:d:${componentType}-lifecycle: Deleting related products`, + JSON.stringify({ + filters: { + [componentType]: { id } + } + }) + ); + const products = await strapi.entityService.findMany("api::product.product", { + filters: { + [componentType]: { id } + } + }); + + // Delete related products + // TODO: Deleting too many products + if (products.length) { + for (const product of products) { + await strapi.entityService.delete("api::product.product", product.id); + } + } + } catch (error) { + strapi.log.error( + `app:e:${componentType}-lifecycle: Error deleting related products`, + JSON.stringify({ + error, + componentId: id + }) + ); + throw error; // Propagate error to prevent component deletion if products can't be deleted + } + } +}); + +async function generateNewProducts(strapi: Strapi, componentType: string, componentId: number) { + // Fetch all necessary components + const [covers, patterns, pages, rulings] = await Promise.all([ + componentType === "cover" + ? [await strapi.entityService.findOne("api::product-cover.product-cover", componentId)] + : strapi.entityService.findMany("api::product-cover.product-cover"), + componentType === "pattern" + ? [await strapi.entityService.findOne("api::product-pattern.product-pattern", componentId)] + : strapi.entityService.findMany("api::product-pattern.product-pattern"), + componentType === "pages" + ? [await strapi.entityService.findOne("api::product-page.product-page", componentId)] + : strapi.entityService.findMany("api::product-page.product-page"), + componentType === "ruling" + ? [await strapi.entityService.findOne("api::product-ruling.product-ruling", componentId)] + : strapi.entityService.findMany("api::product-ruling.product-ruling") + ]); + + strapi.log.debug(`app:d:lifecycle-factory ${JSON.stringify({ covers, patterns, pages, rulings })}`); + + // Generate new combinations + for (const cover of covers) { + for (const pattern of patterns) { + for (const page of pages) { + for (const ruling of rulings) { + const name = `${pattern.name} ${cover.name} · ${page.name} · ${ruling.name}`; + const slug = formatSlug(name); + const existing = await strapi.entityService.findMany("api::product.product", { + filters: { slug } + }); + + if (existing.length) { + strapi.log.warn(`app:w:lifecycle-factory: Product "${name}" already exists with ID ${existing[0]?.id}`); + strapi.log.debug(`app:d:lifecycle-factory: ${JSON.stringify({ existing })}`); + continue; + } + + const categoriesFilter = { + filters: { + product_cover: cover.id, + product_pattern: pattern.id + } + }; + const categories = await strapi.service("api::product-category.product-category").categories(categoriesFilter); + + if (categories) { + strapi.log.debug(`app:d:lifecycle-factory: Attaching product-image with ID ${categories[0]?.id}`); + } else { + strapi.log.warn("app:w:lifecycle-factory: Product-image not found"); + } + + const images = categories ? categories[0]?.id : null; + const data = { + name, + slug, + images, + cover: cover.id, + pattern: pattern.id, + pages: page.id, + ruling: ruling.id, + // TODO: Might be strapi v5 syntax + // https://docs.strapi.io/cms/migration/v4-to-v5/breaking-changes/publication-state-removed + status: "draft", + publishedAt: null + }; + await strapi.entityService.create("api::product.product", { + data + }); + } + } + } + } +} + +async function updateRelatedProducts(strapi: Strapi, componentType: string, componentId: number) { + // Find all related products with full population + const products = await strapi.entityService.findMany("api::product.product", { + filters: { + [componentType === "image" ? "images" : componentType]: { id: componentId } + }, + ...productDefaultParams, + publicationState: "preview" + }); + + // @ts-expect-error + const parent = await strapi.entityService.findOne(`api::product-${componentType}.product-${componentType}`, componentId); + + strapi.log.info(`app:i:lifecycle-factory: Updating ${products.length} products related to ${componentType} with ID ${componentId}`); + + for (const product of products) { + try { + // Get the current components for this product + const cover = product.cover?.id; + const pattern = product.pattern?.id; + const pages = product.pages?.id; + const ruling = product.ruling?.id; + + // Determine if this product should still exist based on component availability + const componentsExist = await validateComponents(strapi, cover, pattern, pages, ruling); + + if (!componentsExist) { + // Delete products with missing components + strapi.log.info(`app:i:lifecycle-factory: Deleting product ${product.id} due to missing components`); + await strapi.entityService.delete("api::product.product", product.id); + continue; + } + + // Regenerate product name and slug based on current components + const [coverData, patternData, pagesData, rulingData] = await Promise.all([ + strapi.entityService.findOne("api::product-cover.product-cover", cover), + strapi.entityService.findOne("api::product-pattern.product-pattern", pattern), + strapi.entityService.findOne("api::product-page.product-page", pages), + strapi.entityService.findOne("api::product-ruling.product-ruling", ruling) + ]); + + const name = `${patternData.name} ${coverData.name} · ${pagesData.name} · ${rulingData.name}`; + const slug = formatSlug(name); + + // Find the correct category/product-image + const categoriesFilter = { + filters: { + product_cover: cover, + product_pattern: pattern + } + }; + const categories = await strapi.service("api::product-category.product-category").categories(categoriesFilter); + const images = categories?.length ? categories[0]?.id : null; + + // Check if a product with this name already exists (but is not this one) + const existing = await strapi.entityService.findMany("api::product.product", { + filters: { + slug, + id: { $ne: product.id } + } + }); + + if (existing.length) { + // Duplicate found - delete this one if it's newer + if (new Date(product.createdAt) > new Date(existing[0].createdAt)) { + strapi.log.warn(`app:w:lifecycle-factory: Deleting duplicate product ${product.id} in favor of existing ${existing[0].id}`); + await strapi.entityService.delete("api::product.product", product.id); + } + continue; + } + + // Update the product with refreshed data + const updateData = { + name, + slug, + images + // Don't update the publishedAt status here, as it's handled by updateRelatedProductsStatus + }; + + strapi.log.verbose(`app:v:lifecycle-factory: Updating product ${product.id} with ${JSON.stringify(updateData)}`); + await strapi.entityService.update("api::product.product", product.id, { + data: updateData + }); + } catch (error) { + strapi.log.error(`app:e:lifecycle-factory: Error updating product ${product.id}`, error); + } + } + + strapi.log.info(`app:i:lifecycle-factory: ✔ Finished updating products related to ${componentType} ${componentId}`); +} + +// Helper function to validate that all components of a product exist +async function validateComponents(strapi: Strapi, coverId: ID, patternId: ID, pagesId: ID, rulingId: ID): Promise { + try { + const [cover, pattern, pages, ruling] = await Promise.all([ + coverId ? strapi.entityService.findOne("api::product-cover.product-cover", coverId) : null, + patternId ? strapi.entityService.findOne("api::product-pattern.product-pattern", patternId) : null, + pagesId ? strapi.entityService.findOne("api::product-page.product-page", pagesId) : null, + rulingId ? strapi.entityService.findOne("api::product-ruling.product-ruling", rulingId) : null + ]); + + return !!(cover && pattern && pages && ruling); + } catch (error) { + strapi.log.error(`app:e:lifecycle-factory: Error validating components`, error); + return false; + } +} diff --git a/src/utils/formatSlug.ts b/src/utils/formatSlug.ts new file mode 100644 index 0000000..6f63272 --- /dev/null +++ b/src/utils/formatSlug.ts @@ -0,0 +1,18 @@ +export const formatSlug = (str: string): string => { + str = str.replace(/^\s+|\s+$/g, ""); // trim + str = str.toLowerCase(); + + // remove accents, swap ñ for n, etc + var from = "àáäâèéëêìíïîòóöôùúüûñç·/_,:;"; + var to = "aaaaeeeeiiiioooouuuunc------"; + for (var i = 0, l = from.length; i < l; i++) { + str = str.replace(new RegExp(from.charAt(i), "g"), to.charAt(i)); + } + + str = str + .replace(/[^a-z0-9 -]/g, "") // remove invalid chars + .replace(/\s+/g, "-") // collapse whitespace and replace by - + .replace(/-+/g, "-"); // collapse dashes + + return str; +}; diff --git a/tests/parallel-stress-test-add-to-cart.sh b/tests/parallel-stress-test-add-to-cart.sh new file mode 100755 index 0000000..9156646 --- /dev/null +++ b/tests/parallel-stress-test-add-to-cart.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# Configuration variables +METHOD="PUT" +BASE_URL="https://localhost:8443" +API_URL="/api/order/a00ad9d9-fa7b-4989-a37c-5ef5051325fe/add-product/11521?count=4" +BEARER_TOKEN="b5739bfdb5267e51533de07dc3726aecfa8063fd5fe3d903bdef7d9f614cd99e5ee8fe227587edb29df6be2a2bf8849cd713d1e8a82b3ff2d27244a10deb849559d573e4662de0ad5844e32afbfed5f82b22d7cbd57a01b5fcc7ca251abf0bf2a5d2a050745d81f0c47a9358d58f0f9b44b66d8649f7e9f5df10b9a2fcce58bd" +NUM_JOBS=5 +TOTAL_REQUESTS=100 +RESULTS_FILE=$(mktemp) + +# Export configuration variables +export METHOD BASE_URL API_URL BEARER_TOKEN RESULTS_FILE + +# Create a function for the curl command +curl_command() { + local id=$1 + local output=$(curl --request "${METHOD}" \ + --url "${BASE_URL}${API_URL}" \ + --header "Authorization: Bearer ${BEARER_TOKEN}" \ + --header 'content-type: application/json' \ + --header 'cache-control: no-cache' \ + --header 'pragma: no-cache' \ + --compressed \ + --insecure -s -o /dev/null -w "%{http_code} %{time_total}") + + local status_code=$(echo $output | cut -d' ' -f1) + local time_total=$(echo $output | cut -d' ' -f2) + + # Convert time to milliseconds and round to 3 decimal places using awk + local time_ms=$(awk -v time="$time_total" 'BEGIN {printf "%.3f", time * 1000}') + + echo "Request $id: Status Code: $status_code, Time: ${time_ms}ms" + + # Append results to the temporary file + echo "$id $status_code $time_ms" >> "$RESULTS_FILE" +} + +export -f curl_command + +echo "Debug: ${METHOD} ${BASE_URL}${API_URL}" +echo "Debug: ${TOTAL_REQUESTS} Total Requests in Chunks of ${NUM_JOBS}" + +# Use parallel to run the stress test +seq 1 $TOTAL_REQUESTS | parallel -j $NUM_JOBS curl_command {} + +echo "Stress test completed." + +# Calculate and display statistics +echo "Calculating statistics..." + +awk ' + BEGIN {total_requests = 0; total_time = 0; success_count = 0; min_time = 1e10; max_time = 0} + { + total_requests++; + total_time += $3; + if ($2 >= 200 && $2 < 300) success_count++; + if ($3 < min_time) min_time = $3; + if ($3 > max_time) max_time = $3; + } + END { + printf "Overall Statistics:\n"; + printf "Total Requests: %d\n", total_requests; + printf "Total Time: %.3fms\n", total_time; + printf "Average Response Time: %.3fms\n", total_time / total_requests; + printf "Success Rate: %.2f%%\n", (success_count / total_requests) * 100; + printf "Fastest Response: %.3fms\n", min_time; + printf "Slowest Response: %.3fms\n", max_time; + } +' "$RESULTS_FILE" + +# Clean up the temporary file +rm "$RESULTS_FILE" diff --git a/tests/parallel-stress-test-finalize-order.sh b/tests/parallel-stress-test-finalize-order.sh new file mode 100755 index 0000000..f0224f3 --- /dev/null +++ b/tests/parallel-stress-test-finalize-order.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# Configuration variables +METHOD="PUT" +BASE_URL="https://localhost:8443" +API_URL="/api/order/a00ad9d9-fa7b-4989-a37c-5ef5051325fe/finalize" +BEARER_TOKEN="b5739bfdb5267e51533de07dc3726aecfa8063fd5fe3d903bdef7d9f614cd99e5ee8fe227587edb29df6be2a2bf8849cd713d1e8a82b3ff2d27244a10deb849559d573e4662de0ad5844e32afbfed5f82b22d7cbd57a01b5fcc7ca251abf0bf2a5d2a050745d81f0c47a9358d58f0f9b44b66d8649f7e9f5df10b9a2fcce58bd" +NUM_JOBS=5 +TOTAL_REQUESTS=100 +RESULTS_FILE=$(mktemp) + +# Export configuration variables +export METHOD BASE_URL API_URL BEARER_TOKEN RESULTS_FILE + +# Create a function for the curl command +curl_command() { + local id=$1 + local output=$(curl --request "${METHOD}" \ + --url "${BASE_URL}${API_URL}" \ + --header "Authorization: Bearer ${BEARER_TOKEN}" \ + --header 'content-type: application/json' \ + --header 'cache-control: no-cache' \ + --header 'pragma: no-cache' \ + --compressed \ + --insecure -s -o /dev/null -w "%{http_code} %{time_total}") + + local status_code=$(echo $output | cut -d' ' -f1) + local time_total=$(echo $output | cut -d' ' -f2) + + # Convert time to milliseconds and round to 3 decimal places using awk + local time_ms=$(awk -v time="$time_total" 'BEGIN {printf "%.3f", time * 1000}') + + echo "Request $id: Status Code: $status_code, Time: ${time_ms}ms" + + # Append results to the temporary file + echo "$id $status_code $time_ms" >> "$RESULTS_FILE" +} + +export -f curl_command + +echo "Debug: ${METHOD} ${BASE_URL}${API_URL}" +echo "Debug: ${TOTAL_REQUESTS} Total Requests in Chunks of ${NUM_JOBS}" + +# Use parallel to run the stress test +seq 1 $TOTAL_REQUESTS | parallel -j $NUM_JOBS curl_command {} + +echo "Stress test completed." + +# Calculate and display statistics +echo "Calculating statistics..." + +awk ' + BEGIN {total_requests = 0; total_time = 0; success_count = 0; min_time = 1e10; max_time = 0} + { + total_requests++; + total_time += $3; + if ($2 >= 200 && $2 < 300) success_count++; + if ($3 < min_time) min_time = $3; + if ($3 > max_time) max_time = $3; + } + END { + printf "Overall Statistics:\n"; + printf "Total Requests: %d\n", total_requests; + printf "Total Time: %.3fms\n", total_time; + printf "Average Response Time: %.3fms\n", total_time / total_requests; + printf "Success Rate: %.2f%%\n", (success_count / total_requests) * 100; + printf "Fastest Response: %.3fms\n", min_time; + printf "Slowest Response: %.3fms\n", max_time; + } +' "$RESULTS_FILE" + +# Clean up the temporary file +rm "$RESULTS_FILE" diff --git a/tests/parallel-stress-test-generate-delivery-note.sh b/tests/parallel-stress-test-generate-delivery-note.sh new file mode 100755 index 0000000..88d747b --- /dev/null +++ b/tests/parallel-stress-test-generate-delivery-note.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# Configuration variables +METHOD="PUT" +BASE_URL="https://localhost:8443" +API_URL="/api/order/a00ad9d9-fa7b-4989-a37c-5ef5051325fe/generate-delivery-note" +BEARER_TOKEN="b5739bfdb5267e51533de07dc3726aecfa8063fd5fe3d903bdef7d9f614cd99e5ee8fe227587edb29df6be2a2bf8849cd713d1e8a82b3ff2d27244a10deb849559d573e4662de0ad5844e32afbfed5f82b22d7cbd57a01b5fcc7ca251abf0bf2a5d2a050745d81f0c47a9358d58f0f9b44b66d8649f7e9f5df10b9a2fcce58bd" +NUM_JOBS=2 +TOTAL_REQUESTS=10 +RESULTS_FILE=$(mktemp) + +# Export configuration variables +export METHOD BASE_URL API_URL BEARER_TOKEN RESULTS_FILE + +# Create a function for the curl command +curl_command() { + local id=$1 + local output=$(curl --request "${METHOD}" \ + --url "${BASE_URL}${API_URL}" \ + --header "Authorization: Bearer ${BEARER_TOKEN}" \ + --header 'content-type: application/json' \ + --header 'cache-control: no-cache' \ + --header 'pragma: no-cache' \ + --compressed \ + --insecure -s -o /dev/null -w "%{http_code} %{time_total}") + + local status_code=$(echo $output | cut -d' ' -f1) + local time_total=$(echo $output | cut -d' ' -f2) + + # Convert time to milliseconds and round to 3 decimal places using awk + local time_ms=$(awk -v time="$time_total" 'BEGIN {printf "%.3f", time * 1000}') + + echo "Request $id: Status Code: $status_code, Time: ${time_ms}ms" + + # Append results to the temporary file + echo "$id $status_code $time_ms" >> "$RESULTS_FILE" +} + +export -f curl_command + +echo "Debug: ${METHOD} ${BASE_URL}${API_URL}" +echo "Debug: ${TOTAL_REQUESTS} Total Requests in Chunks of ${NUM_JOBS}" + +# Use parallel to run the stress test +seq 1 $TOTAL_REQUESTS | parallel -j $NUM_JOBS curl_command {} + +echo "Stress test completed." + +# Calculate and display statistics +echo "Calculating statistics..." + +awk ' + BEGIN {total_requests = 0; total_time = 0; success_count = 0; min_time = 1e10; max_time = 0} + { + total_requests++; + total_time += $3; + if ($2 >= 200 && $2 < 300) success_count++; + if ($3 < min_time) min_time = $3; + if ($3 > max_time) max_time = $3; + } + END { + printf "Overall Statistics:\n"; + printf "Total Requests: %d\n", total_requests; + printf "Total Time: %.3fms\n", total_time; + printf "Average Response Time: %.3fms\n", total_time / total_requests; + printf "Success Rate: %.2f%%\n", (success_count / total_requests) * 100; + printf "Fastest Response: %.3fms\n", min_time; + printf "Slowest Response: %.3fms\n", max_time; + } +' "$RESULTS_FILE" + +# Clean up the temporary file +rm "$RESULTS_FILE" diff --git a/tests/parallel-stress-test-get-products.sh b/tests/parallel-stress-test-get-products.sh new file mode 100755 index 0000000..f6df3de --- /dev/null +++ b/tests/parallel-stress-test-get-products.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# Configuration variables +METHOD="GET" +BASE_URL="https://localhost:8443" +API_URL="/api/product" +BEARER_TOKEN="b5739bfdb5267e51533de07dc3726aecfa8063fd5fe3d903bdef7d9f614cd99e5ee8fe227587edb29df6be2a2bf8849cd713d1e8a82b3ff2d27244a10deb849559d573e4662de0ad5844e32afbfed5f82b22d7cbd57a01b5fcc7ca251abf0bf2a5d2a050745d81f0c47a9358d58f0f9b44b66d8649f7e9f5df10b9a2fcce58bd" +NUM_JOBS=2 +TOTAL_REQUESTS=100 +RESULTS_FILE=$(mktemp) + +# Export configuration variables +export METHOD BASE_URL API_URL BEARER_TOKEN RESULTS_FILE + +# Create a function for the curl command +curl_command() { + local id=$1 + local output=$(curl --request "${METHOD}" \ + --url "${BASE_URL}${API_URL}" \ + --header "Authorization: Bearer ${BEARER_TOKEN}" \ + --header 'content-type: application/json' \ + --header 'cache-control: no-cache' \ + --header 'pragma: no-cache' \ + --compressed \ + --insecure -s -o /dev/null -w "%{http_code} %{time_total}") + + local status_code=$(echo $output | cut -d' ' -f1) + local time_total=$(echo $output | cut -d' ' -f2) + + # Convert time to milliseconds and round to 3 decimal places using awk + local time_ms=$(awk -v time="$time_total" 'BEGIN {printf "%.3f", time * 1000}') + + echo "Request $id: Status Code: $status_code, Time: ${time_ms}ms" + + # Append results to the temporary file + echo "$id $status_code $time_ms" >> "$RESULTS_FILE" +} + +export -f curl_command + +echo "Debug: ${METHOD} ${BASE_URL}${API_URL}" +echo "Debug: ${TOTAL_REQUESTS} Total Requests in Chunks of ${NUM_JOBS}" + +# Use parallel to run the stress test +seq 1 $TOTAL_REQUESTS | parallel -j $NUM_JOBS curl_command {} + +echo "Stress test completed." + +# Calculate and display statistics +echo "Calculating statistics..." + +awk ' + BEGIN {total_requests = 0; total_time = 0; success_count = 0; min_time = 1e10; max_time = 0} + { + total_requests++; + total_time += $3; + if ($2 >= 200 && $2 < 300) success_count++; + if ($3 < min_time) min_time = $3; + if ($3 > max_time) max_time = $3; + } + END { + printf "Overall Statistics:\n"; + printf "Total Requests: %d\n", total_requests; + printf "Total Time: %.3fms\n", total_time; + printf "Average Response Time: %.3fms\n", total_time / total_requests; + printf "Success Rate: %.2f%%\n", (success_count / total_requests) * 100; + printf "Fastest Response: %.3fms\n", min_time; + printf "Slowest Response: %.3fms\n", max_time; + } +' "$RESULTS_FILE" + +# Clean up the temporary file +rm "$RESULTS_FILE" diff --git a/tests/stress-test-add-to-cart.sh b/tests/stress-test-add-to-cart.sh new file mode 100644 index 0000000..1824d90 --- /dev/null +++ b/tests/stress-test-add-to-cart.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +for i in {1..100}; do curl --request PUT \ + --url 'http://localhost:5555/api/order/a00ad9d9-fa7b-4989-a37c-5ef5051325fe/add-product/11521?count=4' \ + --header 'Authorization: Bearer b5739bfdb5267e51533de07dc3726aecfa8063fd5fe3d903bdef7d9f614cd99e5ee8fe227587edb29df6be2a2bf8849cd713d1e8a82b3ff2d27244a10deb849559d573e4662de0ad5844e32afbfed5f82b22d7cbd57a01b5fcc7ca251abf0bf2a5d2a050745d81f0c47a9358d58f0f9b44b66d8649f7e9f5df10b9a2fcce58bd' \ + --header 'content-type: application/json' \ + --header 'cache-control: no-cache' \ + --header 'pragma: no-cache' \ + --data '{ + "cart": [ + { + "count": 10, + "product": 789 + } + ] + }' \ + --compressed \ + --insecure -s -o /dev/null -w '%{time_total}s\n'; +done diff --git a/tests/stress-test-generate-invoice.sh b/tests/stress-test-generate-invoice.sh new file mode 100644 index 0000000..87589b5 --- /dev/null +++ b/tests/stress-test-generate-invoice.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +BEARER='b5739bfdb5267e51533de07dc3726aecfa8063fd5fe3d903bdef7d9f614cd99e5ee8fe227587edb29df6be2a2bf8849cd713d1e8a82b3ff2d27244a10deb849559d573e4662de0ad5844e32afbfed5f82b22d7cbd57a01b5fcc7ca251abf0bf2a5d2a050745d81f0c47a9358d58f0f9b44b66d8649f7e9f5df10b9a2fcce58bd' + + +# Function to run a single curl command +run_curl() { + curl --request PUT \ + --url 'https://localhost:8443/api/order/a00ad9d9-fa7b-4989-a37c-5ef5051325fe/generate-delivery-note' \ + --header "Authorization: Bearer ${BEARER}" \ + --header 'content-type: application/json' \ + --header 'cache-control: no-cache' \ + --header 'pragma: no-cache' \ + --compressed \ + --output /dev/null \ + --insecure -s -o /dev/null -w '%{time_total}s\n' +} + +# Number of parallel jobs to run +NUM_JOBS=5 + +# Number of requests per job +NUM_REQUESTS=100 + +# Function to run a batch of requests +run_batch() { + for i in $(seq 1 $NUM_REQUESTS); do + run_curl + done +} + +# Run the stress test using background jobs +for i in $(seq 1 $NUM_JOBS); do + run_batch & +done + +# Wait for all background jobs to finish +wait + +echo "Stress test completed." diff --git a/tests/stress-test-get-products.sh b/tests/stress-test-get-products.sh new file mode 100644 index 0000000..0591d0a --- /dev/null +++ b/tests/stress-test-get-products.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +for i in {1..100}; do curl --request GET \ + --url http://localhost:5555/api/product \ + --header 'Authorization: Bearer b5739bfdb5267e51533de07dc3726aecfa8063fd5fe3d903bdef7d9f614cd99e5ee8fe227587edb29df6be2a2bf8849cd713d1e8a82b3ff2d27244a10deb849559d573e4662de0ad5844e32afbfed5f82b22d7cbd57a01b5fcc7ca251abf0bf2a5d2a050745d81f0c47a9358d58f0f9b44b66d8649f7e9f5df10b9a2fcce58bd' \ + --header 'content-type: application/json' \ + --header 'cache-control: no-cache' \ + --header 'pragma: no-cache' \ + --compressed \ + --insecure -s -o /dev/null -w '%{time_total}s\n'; +done diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..0445ec0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,24 @@ +{ + "extends": "@strapi/typescript-utils/tsconfigs/server", + "compilerOptions": { + "outDir": "dist", + "module": "CommonJS", + "rootDir": "." + }, + "include": [ + "./", + "./**/*.ts", + "./**/*.js", + "src/**/*.json" + ], + "exclude": [ + "node_modules/", + "build/", + "dist/", + ".cache/", + ".tmp/", + "src/admin/", + "**/*.test.*", + "src/plugins/**" + ] +} diff --git a/types/generated/components.d.ts b/types/generated/components.d.ts new file mode 100644 index 0000000..c255e7e --- /dev/null +++ b/types/generated/components.d.ts @@ -0,0 +1,62 @@ +import type { Attribute, Schema } from "@strapi/strapi"; + +export interface AddressStructuredAddress extends Schema.Component { + collectionName: "components_address_structured_addresses"; + info: { + description: "Address fields matching HTML autocomplete attributes"; + displayName: "Structured Address"; + }; + attributes: { + addressLevel2: Attribute.String; + country: Attribute.String & Attribute.DefaultTo<"DE">; + familyName: Attribute.String; + givenName: Attribute.String; + postalCode: Attribute.String; + streetAddress: Attribute.String; + }; +} + +export interface ProductsCart extends Schema.Component { + collectionName: "components_products_carts"; + info: { + description: ""; + displayName: "cart"; + icon: "stack"; + }; + attributes: { + count: Attribute.Integer & + Attribute.SetMinMax< + { + min: 1; + }, + number + > & + Attribute.DefaultTo<1>; + product: Attribute.Relation<"products.cart", "oneToOne", "api::product.product">; + }; +} + +export interface WebsitesWebsiteInMenu extends Schema.Component { + collectionName: "components_websites_website_in_menus"; + info: { + description: ""; + displayName: "Website in Menu"; + icon: "file"; + }; + attributes: { + menu: Attribute.String & Attribute.Required; + richtext: Attribute.Blocks; + showInFooter: Attribute.Boolean & Attribute.DefaultTo; + showInHeader: Attribute.Boolean & Attribute.DefaultTo; + }; +} + +declare module "@strapi/types" { + export module Shared { + export interface Components { + "address.structured-address": AddressStructuredAddress; + "products.cart": ProductsCart; + "websites.website-in-menu": WebsitesWebsiteInMenu; + } + } +} diff --git a/types/generated/contentTypes.d.ts b/types/generated/contentTypes.d.ts new file mode 100644 index 0000000..43704eb --- /dev/null +++ b/types/generated/contentTypes.d.ts @@ -0,0 +1,1001 @@ +import type { Attribute, Schema } from "@strapi/strapi"; + +export interface AdminApiToken extends Schema.CollectionType { + collectionName: "strapi_api_tokens"; + info: { + description: ""; + displayName: "Api Token"; + name: "Api Token"; + pluralName: "api-tokens"; + singularName: "api-token"; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + accessKey: Attribute.String & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"admin::api-token", "oneToOne", "admin::user"> & Attribute.Private; + description: Attribute.String & + Attribute.SetMinMaxLength<{ + minLength: 1; + }> & + Attribute.DefaultTo<"">; + expiresAt: Attribute.DateTime; + lastUsedAt: Attribute.DateTime; + lifespan: Attribute.BigInteger; + name: Attribute.String & + Attribute.Required & + Attribute.Unique & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + permissions: Attribute.Relation<"admin::api-token", "oneToMany", "admin::api-token-permission">; + type: Attribute.Enumeration<["read-only", "full-access", "custom"]> & Attribute.Required & Attribute.DefaultTo<"read-only">; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"admin::api-token", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface AdminApiTokenPermission extends Schema.CollectionType { + collectionName: "strapi_api_token_permissions"; + info: { + description: ""; + displayName: "API Token Permission"; + name: "API Token Permission"; + pluralName: "api-token-permissions"; + singularName: "api-token-permission"; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + action: Attribute.String & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"admin::api-token-permission", "oneToOne", "admin::user"> & Attribute.Private; + token: Attribute.Relation<"admin::api-token-permission", "manyToOne", "admin::api-token">; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"admin::api-token-permission", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface AdminPermission extends Schema.CollectionType { + collectionName: "admin_permissions"; + info: { + description: ""; + displayName: "Permission"; + name: "Permission"; + pluralName: "permissions"; + singularName: "permission"; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + action: Attribute.String & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + actionParameters: Attribute.JSON & Attribute.DefaultTo<{}>; + conditions: Attribute.JSON & Attribute.DefaultTo<[]>; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"admin::permission", "oneToOne", "admin::user"> & Attribute.Private; + properties: Attribute.JSON & Attribute.DefaultTo<{}>; + role: Attribute.Relation<"admin::permission", "manyToOne", "admin::role">; + subject: Attribute.String & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"admin::permission", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface AdminRole extends Schema.CollectionType { + collectionName: "admin_roles"; + info: { + description: ""; + displayName: "Role"; + name: "Role"; + pluralName: "roles"; + singularName: "role"; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + code: Attribute.String & + Attribute.Required & + Attribute.Unique & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"admin::role", "oneToOne", "admin::user"> & Attribute.Private; + description: Attribute.String; + name: Attribute.String & + Attribute.Required & + Attribute.Unique & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + permissions: Attribute.Relation<"admin::role", "oneToMany", "admin::permission">; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"admin::role", "oneToOne", "admin::user"> & Attribute.Private; + users: Attribute.Relation<"admin::role", "manyToMany", "admin::user">; + }; +} + +export interface AdminTransferToken extends Schema.CollectionType { + collectionName: "strapi_transfer_tokens"; + info: { + description: ""; + displayName: "Transfer Token"; + name: "Transfer Token"; + pluralName: "transfer-tokens"; + singularName: "transfer-token"; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + accessKey: Attribute.String & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"admin::transfer-token", "oneToOne", "admin::user"> & Attribute.Private; + description: Attribute.String & + Attribute.SetMinMaxLength<{ + minLength: 1; + }> & + Attribute.DefaultTo<"">; + expiresAt: Attribute.DateTime; + lastUsedAt: Attribute.DateTime; + lifespan: Attribute.BigInteger; + name: Attribute.String & + Attribute.Required & + Attribute.Unique & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + permissions: Attribute.Relation<"admin::transfer-token", "oneToMany", "admin::transfer-token-permission">; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"admin::transfer-token", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface AdminTransferTokenPermission extends Schema.CollectionType { + collectionName: "strapi_transfer_token_permissions"; + info: { + description: ""; + displayName: "Transfer Token Permission"; + name: "Transfer Token Permission"; + pluralName: "transfer-token-permissions"; + singularName: "transfer-token-permission"; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + action: Attribute.String & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"admin::transfer-token-permission", "oneToOne", "admin::user"> & Attribute.Private; + token: Attribute.Relation<"admin::transfer-token-permission", "manyToOne", "admin::transfer-token">; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"admin::transfer-token-permission", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface AdminUser extends Schema.CollectionType { + collectionName: "admin_users"; + info: { + description: ""; + displayName: "User"; + name: "User"; + pluralName: "users"; + singularName: "user"; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + blocked: Attribute.Boolean & Attribute.Private & Attribute.DefaultTo; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"admin::user", "oneToOne", "admin::user"> & Attribute.Private; + email: Attribute.Email & + Attribute.Required & + Attribute.Private & + Attribute.Unique & + Attribute.SetMinMaxLength<{ + minLength: 6; + }>; + firstname: Attribute.String & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + isActive: Attribute.Boolean & Attribute.Private & Attribute.DefaultTo; + lastname: Attribute.String & + Attribute.SetMinMaxLength<{ + minLength: 1; + }>; + password: Attribute.Password & + Attribute.Private & + Attribute.SetMinMaxLength<{ + minLength: 6; + }>; + preferedLanguage: Attribute.String; + registrationToken: Attribute.String & Attribute.Private; + resetPasswordToken: Attribute.String & Attribute.Private; + roles: Attribute.Relation<"admin::user", "manyToMany", "admin::role"> & Attribute.Private; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"admin::user", "oneToOne", "admin::user"> & Attribute.Private; + username: Attribute.String; + }; +} + +export interface ApiCustomerCustomer extends Schema.CollectionType { + collectionName: "customers"; + info: { + description: ""; + displayName: "Customer"; + pluralName: "customers"; + singularName: "customer"; + }; + options: { + draftAndPublish: false; + }; + attributes: { + address: Attribute.Text; + addressStructured: Attribute.Component<"address.structured-address">; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::customer.customer", "oneToOne", "admin::user"> & Attribute.Private; + name: Attribute.String & Attribute.Required; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::customer.customer", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface ApiDeliveryDelivery extends Schema.CollectionType { + collectionName: "deliveries"; + info: { + description: ""; + displayName: "Delivery"; + pluralName: "deliveries"; + singularName: "delivery"; + }; + options: { + draftAndPublish: false; + privateAttributes: ["created_at", "updated_at", "created_by", "updated_by", "createdAt", "updatedAt"]; + }; + attributes: { + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::delivery.delivery", "oneToOne", "admin::user"> & Attribute.Private; + description: Attribute.Text; + name: Attribute.String & Attribute.Required; + price: Attribute.Decimal; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::delivery.delivery", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface ApiLegalLegal extends Schema.SingleType { + collectionName: "legals"; + info: { + description: ""; + displayName: "Legal"; + pluralName: "legals"; + singularName: "legal"; + }; + options: { + draftAndPublish: false; + privateAttributes: ["created_at", "updated_at", "created_by", "updated_by"]; + }; + attributes: { + contact: Attribute.RichText; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::legal.legal", "oneToOne", "admin::user"> & Attribute.Private; + delivery: Attribute.RichText; + imprint: Attribute.RichText; + payment: Attribute.RichText; + privacy: Attribute.RichText; + terms: Attribute.RichText; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::legal.legal", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface ApiOrderOrder extends Schema.CollectionType { + collectionName: "orders"; + info: { + description: ""; + displayName: "Order"; + pluralName: "orders"; + singularName: "order"; + }; + options: { + draftAndPublish: false; + }; + attributes: { + acceptedTermsAndConditionsAt: Attribute.DateTime; + cart: Attribute.Component<"products.cart", true>; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::order.order", "oneToOne", "admin::user"> & Attribute.Private; + customer: Attribute.Relation<"api::order.order", "oneToOne", "api::customer.customer">; + date: Attribute.Date; + delivery: Attribute.Relation<"api::order.order", "oneToOne", "api::delivery.delivery">; + deliveryAddress: Attribute.Text; + deliveryAddressStructured: Attribute.Component<"address.structured-address">; + deliveryNote: Attribute.Media<"images" | "files" | "videos" | "audios">; + deliveryNoteNumber: Attribute.String; + deliveryNoteSent: Attribute.Boolean; + deliveryTrackingNumber: Attribute.String; + email: Attribute.String; + emailSent: Attribute.Boolean & Attribute.DefaultTo; + hash: Attribute.Text & Attribute.Private & Attribute.Unique; + invoice: Attribute.Media<"files">; + invoiceAddress: Attribute.Text; + invoiceAddressStructured: Attribute.Component<"address.structured-address">; + invoiceNumber: Attribute.String & Attribute.Unique; + invoiceSent: Attribute.Boolean & Attribute.DefaultTo; + payment: Attribute.Relation<"api::order.order", "oneToOne", "api::payment.payment">; + paymentAuthorised: Attribute.Boolean & Attribute.DefaultTo; + paymentStatus: Attribute.String; + subtotal: Attribute.Decimal; + total: Attribute.Decimal; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::order.order", "oneToOne", "admin::user"> & Attribute.Private; + uuid: Attribute.String & Attribute.Unique; + VAT: Attribute.Decimal; + }; +} + +export interface ApiPaymentPayment extends Schema.CollectionType { + collectionName: "payments"; + info: { + description: ""; + displayName: "Payment"; + pluralName: "payments"; + singularName: "payment"; + }; + options: { + draftAndPublish: false; + privateAttributes: ["created_at", "updated_at", "created_by", "updated_by", "createdAt", "updatedAt"]; + }; + attributes: { + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::payment.payment", "oneToOne", "admin::user"> & Attribute.Private; + description: Attribute.Text; + name: Attribute.String; + price: Attribute.Decimal; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::payment.payment", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface ApiProductCoverProductCover extends Schema.CollectionType { + collectionName: "product_covers"; + info: { + description: ""; + displayName: "Product Covers"; + pluralName: "product-covers"; + singularName: "product-cover"; + }; + options: { + draftAndPublish: true; + }; + attributes: { + binding: Attribute.Enumeration<["Fadenheftung", "Steppstich", "Wire-O-Bindung"]>; + copyText: Attribute.JSON; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::product-cover.product-cover", "oneToOne", "admin::user"> & Attribute.Private; + icon: Attribute.Media<"images">; + image: Attribute.Media<"images">; + name: Attribute.String & Attribute.Required; + price: Attribute.Decimal; + products: Attribute.Relation<"api::product-cover.product-cover", "oneToMany", "api::product.product">; + publishedAt: Attribute.DateTime; + slides: Attribute.Media<"images", true>; + sort: Attribute.Integer & + Attribute.SetMinMax< + { + min: 0; + }, + number + > & + Attribute.DefaultTo<0>; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::product-cover.product-cover", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface ApiProductImageProductImage extends Schema.CollectionType { + collectionName: "product_images"; + info: { + description: ""; + displayName: "Product Images"; + pluralName: "product-images"; + singularName: "product-image"; + }; + options: { + draftAndPublish: false; + }; + attributes: { + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::product-image.product-image", "oneToOne", "admin::user"> & Attribute.Private; + images: Attribute.Media<"images", true>; + name: Attribute.String; + product_cover: Attribute.Relation<"api::product-image.product-image", "oneToOne", "api::product-cover.product-cover">; + product_pattern: Attribute.Relation<"api::product-image.product-image", "oneToOne", "api::product-pattern.product-pattern">; + products: Attribute.Relation<"api::product-image.product-image", "oneToMany", "api::product.product">; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::product-image.product-image", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface ApiProductPageProductPage extends Schema.CollectionType { + collectionName: "product_pages"; + info: { + description: ""; + displayName: "Product Pages"; + pluralName: "product-pages"; + singularName: "product-page"; + }; + options: { + draftAndPublish: false; + privateAttributes: [ + "createdAt", + "updatedAt", + "created_at", + "updated_at", + "created_by", + "updated_by", + "published_at", + "publishedAt", + "published_by", + "publishedBy" + ]; + }; + attributes: { + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::product-page.product-page", "oneToOne", "admin::user"> & Attribute.Private; + name: Attribute.String & Attribute.Required & Attribute.DefaultTo<"name">; + price: Attribute.Decimal; + products: Attribute.Relation<"api::product-page.product-page", "oneToMany", "api::product.product">; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::product-page.product-page", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface ApiProductPatternProductPattern extends Schema.CollectionType { + collectionName: "product_patterns"; + info: { + description: ""; + displayName: "Product Patterns"; + pluralName: "product-patterns"; + singularName: "product-pattern"; + }; + options: { + draftAndPublish: false; + privateAttributes: [ + "createdAt", + "updatedAt", + "created_at", + "updated_at", + "created_by", + "updated_by", + "published_at", + "publishedAt", + "published_by", + "publishedBy" + ]; + }; + attributes: { + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::product-pattern.product-pattern", "oneToOne", "admin::user"> & Attribute.Private; + description: Attribute.String; + image: Attribute.Media<"images">; + name: Attribute.String & Attribute.Required; + products: Attribute.Relation<"api::product-pattern.product-pattern", "oneToMany", "api::product.product">; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::product-pattern.product-pattern", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface ApiProductRulingProductRuling extends Schema.CollectionType { + collectionName: "product_rulings"; + info: { + description: ""; + displayName: "Product Ruling"; + pluralName: "product-rulings"; + singularName: "product-ruling"; + }; + options: { + draftAndPublish: false; + privateAttributes: [ + "createdAt", + "updatedAt", + "created_at", + "updated_at", + "created_by", + "updated_by", + "published_at", + "publishedAt", + "published_by", + "publishedBy" + ]; + }; + attributes: { + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::product-ruling.product-ruling", "oneToOne", "admin::user"> & Attribute.Private; + icon: Attribute.Media<"images">; + name: Attribute.String & Attribute.Required; + price: Attribute.Decimal; + products: Attribute.Relation<"api::product-ruling.product-ruling", "oneToMany", "api::product.product">; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::product-ruling.product-ruling", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface ApiProductProduct extends Schema.CollectionType { + collectionName: "products"; + info: { + description: ""; + displayName: "Product"; + pluralName: "products"; + singularName: "product"; + }; + options: { + draftAndPublish: true; + }; + attributes: { + cover: Attribute.Relation<"api::product.product", "manyToOne", "api::product-cover.product-cover">; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::product.product", "oneToOne", "admin::user"> & Attribute.Private; + description: Attribute.Text; + images: Attribute.Relation<"api::product.product", "manyToOne", "api::product-image.product-image">; + name: Attribute.String; + pages: Attribute.Relation<"api::product.product", "manyToOne", "api::product-page.product-page">; + pattern: Attribute.Relation<"api::product.product", "manyToOne", "api::product-pattern.product-pattern">; + publishedAt: Attribute.DateTime; + ruling: Attribute.Relation<"api::product.product", "manyToOne", "api::product-ruling.product-ruling">; + slug: Attribute.UID<"api::product.product", "name">; + totalPrice: Attribute.Decimal; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::product.product", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface ApiVatVat extends Schema.SingleType { + collectionName: "vats"; + info: { + displayName: "VAT"; + pluralName: "vats"; + singularName: "vat"; + }; + options: { + draftAndPublish: false; + privateAttributes: [ + "createdAt", + "updatedAt", + "created_at", + "updated_at", + "created_by", + "updated_by", + "published_at", + "publishedAt", + "published_by", + "publishedBy" + ]; + }; + attributes: { + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::vat.vat", "oneToOne", "admin::user"> & Attribute.Private; + decimal: Attribute.Decimal; + name: Attribute.String; + percent: Attribute.Integer; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::vat.vat", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface ApiWebsiteWebsite extends Schema.SingleType { + collectionName: "websites"; + info: { + description: ""; + displayName: "Website"; + pluralName: "websites"; + singularName: "website"; + }; + options: { + draftAndPublish: false; + }; + attributes: { + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"api::website.website", "oneToOne", "admin::user"> & Attribute.Private; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"api::website.website", "oneToOne", "admin::user"> & Attribute.Private; + website: Attribute.Component<"websites.website-in-menu", true>; + }; +} + +export interface PluginContentReleasesRelease extends Schema.CollectionType { + collectionName: "strapi_releases"; + info: { + displayName: "Release"; + pluralName: "releases"; + singularName: "release"; + }; + options: { + draftAndPublish: false; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + actions: Attribute.Relation<"plugin::content-releases.release", "oneToMany", "plugin::content-releases.release-action">; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"plugin::content-releases.release", "oneToOne", "admin::user"> & Attribute.Private; + name: Attribute.String & Attribute.Required; + releasedAt: Attribute.DateTime; + scheduledAt: Attribute.DateTime; + status: Attribute.Enumeration<["ready", "blocked", "failed", "done", "empty"]> & Attribute.Required; + timezone: Attribute.String; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"plugin::content-releases.release", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface PluginContentReleasesReleaseAction extends Schema.CollectionType { + collectionName: "strapi_release_actions"; + info: { + displayName: "Release Action"; + pluralName: "release-actions"; + singularName: "release-action"; + }; + options: { + draftAndPublish: false; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + contentType: Attribute.String & Attribute.Required; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"plugin::content-releases.release-action", "oneToOne", "admin::user"> & Attribute.Private; + entry: Attribute.Relation<"plugin::content-releases.release-action", "morphToOne">; + isEntryValid: Attribute.Boolean; + locale: Attribute.String; + release: Attribute.Relation<"plugin::content-releases.release-action", "manyToOne", "plugin::content-releases.release">; + type: Attribute.Enumeration<["publish", "unpublish"]> & Attribute.Required; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"plugin::content-releases.release-action", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface PluginI18NLocale extends Schema.CollectionType { + collectionName: "i18n_locale"; + info: { + collectionName: "locales"; + description: ""; + displayName: "Locale"; + pluralName: "locales"; + singularName: "locale"; + }; + options: { + draftAndPublish: false; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + code: Attribute.String & Attribute.Unique; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"plugin::i18n.locale", "oneToOne", "admin::user"> & Attribute.Private; + name: Attribute.String & + Attribute.SetMinMax< + { + max: 50; + min: 1; + }, + number + >; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"plugin::i18n.locale", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface PluginUploadFile extends Schema.CollectionType { + collectionName: "files"; + info: { + description: ""; + displayName: "File"; + pluralName: "files"; + singularName: "file"; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + alternativeText: Attribute.String; + caption: Attribute.String; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"plugin::upload.file", "oneToOne", "admin::user"> & Attribute.Private; + ext: Attribute.String; + folder: Attribute.Relation<"plugin::upload.file", "manyToOne", "plugin::upload.folder"> & Attribute.Private; + folderPath: Attribute.String & + Attribute.Required & + Attribute.Private & + Attribute.SetMinMax< + { + min: 1; + }, + number + >; + formats: Attribute.JSON; + hash: Attribute.String & Attribute.Required; + height: Attribute.Integer; + mime: Attribute.String & Attribute.Required; + name: Attribute.String & Attribute.Required; + previewUrl: Attribute.String; + provider: Attribute.String & Attribute.Required; + provider_metadata: Attribute.JSON; + related: Attribute.Relation<"plugin::upload.file", "morphToMany">; + size: Attribute.Decimal & Attribute.Required; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"plugin::upload.file", "oneToOne", "admin::user"> & Attribute.Private; + url: Attribute.String & Attribute.Required; + width: Attribute.Integer; + }; +} + +export interface PluginUploadFolder extends Schema.CollectionType { + collectionName: "upload_folders"; + info: { + displayName: "Folder"; + pluralName: "folders"; + singularName: "folder"; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + children: Attribute.Relation<"plugin::upload.folder", "oneToMany", "plugin::upload.folder">; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"plugin::upload.folder", "oneToOne", "admin::user"> & Attribute.Private; + files: Attribute.Relation<"plugin::upload.folder", "oneToMany", "plugin::upload.file">; + name: Attribute.String & + Attribute.Required & + Attribute.SetMinMax< + { + min: 1; + }, + number + >; + parent: Attribute.Relation<"plugin::upload.folder", "manyToOne", "plugin::upload.folder">; + path: Attribute.String & + Attribute.Required & + Attribute.SetMinMax< + { + min: 1; + }, + number + >; + pathId: Attribute.Integer & Attribute.Required & Attribute.Unique; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"plugin::upload.folder", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface PluginUsersPermissionsPermission extends Schema.CollectionType { + collectionName: "up_permissions"; + info: { + description: ""; + displayName: "Permission"; + name: "permission"; + pluralName: "permissions"; + singularName: "permission"; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + action: Attribute.String & Attribute.Required; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"plugin::users-permissions.permission", "oneToOne", "admin::user"> & Attribute.Private; + role: Attribute.Relation<"plugin::users-permissions.permission", "manyToOne", "plugin::users-permissions.role">; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"plugin::users-permissions.permission", "oneToOne", "admin::user"> & Attribute.Private; + }; +} + +export interface PluginUsersPermissionsRole extends Schema.CollectionType { + collectionName: "up_roles"; + info: { + description: ""; + displayName: "Role"; + name: "role"; + pluralName: "roles"; + singularName: "role"; + }; + pluginOptions: { + "content-manager": { + visible: false; + }; + "content-type-builder": { + visible: false; + }; + }; + attributes: { + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"plugin::users-permissions.role", "oneToOne", "admin::user"> & Attribute.Private; + description: Attribute.String; + name: Attribute.String & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 3; + }>; + permissions: Attribute.Relation<"plugin::users-permissions.role", "oneToMany", "plugin::users-permissions.permission">; + type: Attribute.String & Attribute.Unique; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"plugin::users-permissions.role", "oneToOne", "admin::user"> & Attribute.Private; + users: Attribute.Relation<"plugin::users-permissions.role", "oneToMany", "plugin::users-permissions.user">; + }; +} + +export interface PluginUsersPermissionsUser extends Schema.CollectionType { + collectionName: "up_users"; + info: { + description: ""; + displayName: "User"; + name: "user"; + pluralName: "users"; + singularName: "user"; + }; + options: { + draftAndPublish: false; + timestamps: true; + }; + attributes: { + blocked: Attribute.Boolean & Attribute.DefaultTo; + confirmationToken: Attribute.String & Attribute.Private; + confirmed: Attribute.Boolean & Attribute.DefaultTo; + createdAt: Attribute.DateTime; + createdBy: Attribute.Relation<"plugin::users-permissions.user", "oneToOne", "admin::user"> & Attribute.Private; + email: Attribute.Email & + Attribute.Required & + Attribute.SetMinMaxLength<{ + minLength: 6; + }>; + password: Attribute.Password & + Attribute.Private & + Attribute.SetMinMaxLength<{ + minLength: 6; + }>; + provider: Attribute.String; + resetPasswordToken: Attribute.String & Attribute.Private; + role: Attribute.Relation<"plugin::users-permissions.user", "manyToOne", "plugin::users-permissions.role">; + updatedAt: Attribute.DateTime; + updatedBy: Attribute.Relation<"plugin::users-permissions.user", "oneToOne", "admin::user"> & Attribute.Private; + username: Attribute.String & + Attribute.Required & + Attribute.Unique & + Attribute.SetMinMaxLength<{ + minLength: 3; + }>; + }; +} + +declare module "@strapi/types" { + export module Shared { + export interface ContentTypes { + "admin::api-token": AdminApiToken; + "admin::api-token-permission": AdminApiTokenPermission; + "admin::permission": AdminPermission; + "admin::role": AdminRole; + "admin::transfer-token": AdminTransferToken; + "admin::transfer-token-permission": AdminTransferTokenPermission; + "admin::user": AdminUser; + "api::customer.customer": ApiCustomerCustomer; + "api::delivery.delivery": ApiDeliveryDelivery; + "api::legal.legal": ApiLegalLegal; + "api::order.order": ApiOrderOrder; + "api::payment.payment": ApiPaymentPayment; + "api::product-cover.product-cover": ApiProductCoverProductCover; + "api::product-image.product-image": ApiProductImageProductImage; + "api::product-page.product-page": ApiProductPageProductPage; + "api::product-pattern.product-pattern": ApiProductPatternProductPattern; + "api::product-ruling.product-ruling": ApiProductRulingProductRuling; + "api::product.product": ApiProductProduct; + "api::vat.vat": ApiVatVat; + "api::website.website": ApiWebsiteWebsite; + "plugin::content-releases.release": PluginContentReleasesRelease; + "plugin::content-releases.release-action": PluginContentReleasesReleaseAction; + "plugin::i18n.locale": PluginI18NLocale; + "plugin::upload.file": PluginUploadFile; + "plugin::upload.folder": PluginUploadFolder; + "plugin::users-permissions.permission": PluginUsersPermissionsPermission; + "plugin::users-permissions.role": PluginUsersPermissionsRole; + "plugin::users-permissions.user": PluginUsersPermissionsUser; + } + } +} diff --git a/types/index.ts b/types/index.ts new file mode 100644 index 0000000..42b1a42 --- /dev/null +++ b/types/index.ts @@ -0,0 +1,72 @@ +import { GetValues, GetPopulatableKeys, GetNonPopulatableKeys } from "@strapi/types/dist/types/core/attributes"; + +export type Order = GetValues<"api::order.order", GetNonPopulatableKeys<"api::order.order"> | GetPopulatableKeys<"api::order.order">>; +export type OrderSafe = GetValues<"api::order.order", GetPopulatableKeys<"api::order.order">>; +export type Product = GetValues< + "api::product.product", + GetNonPopulatableKeys<"api::product.product"> | GetPopulatableKeys<"api::product.product"> +> & { totalProductPrice?: number }; +export type ProductPattern = GetValues< + "api::product-pattern.product-pattern", + GetNonPopulatableKeys<"api::product-pattern.product-pattern"> | GetPopulatableKeys<"api::product-pattern.product-pattern"> +>; +export type ProductPages = GetValues< + "api::product-page.product-page", + GetNonPopulatableKeys<"api::product-page.product-page"> | GetPopulatableKeys<"api::product-page.product-page"> +>; +export type ProductRuling = GetValues< + "api::product-ruling.product-ruling", + GetNonPopulatableKeys<"api::product-ruling.product-ruling"> | GetPopulatableKeys<"api::product-ruling.product-ruling"> +>; +export type ProductCover = GetValues< + "api::product-cover.product-cover", + GetNonPopulatableKeys<"api::product-cover.product-cover"> | GetPopulatableKeys<"api::product-cover.product-cover"> +>; +export type ProductImage = GetValues< + "api::product-image.product-image", + GetNonPopulatableKeys<"api::product-image.product-image"> | GetPopulatableKeys<"api::product-image.product-image"> +>; +export type CartProduct = GetValues<"products.cart", GetNonPopulatableKeys<"products.cart"> | GetPopulatableKeys<"products.cart">>; +export type ProductCategory = ProductImage; + +export type PdfBody = { + subject: string; + date: string; + to: { + name: string; + address: string[]; + }; + nr: { + customer: string; + order: string; + shipping?: string; + invoice?: string; + }; + service: { + description: string; + price: { + per_unit: number; + total: number; + }; + count: number; + nr: string; + }[]; + currency: "\\euro"; + body?: string; + total: number; + subtotal: number; + VAT: { + rate: number; + amount: number; + }; + shipping: number; +}; + +export type StructuredAddress = { + givenName: string; + familyName: string; + streetAddress: string; + postalCode: string; + addressLevel2: string; // city + country?: string; +};