---
title: "eCommerce"
description: "Tienda en línea. Cada aplicación es un módulo sobre un único modelo de datos."
canonical: "https://obop.dev/es/apps/ecommerce/"
lang: "es"
---

# eCommerce

## Para qué sirve

Store the data of an online shop: listings, shipping methods, discount codes and web orders with a fulfilment flow. Refunds need a manager and an approval. A storefront or other client reads and writes this data through the API.

## Qué hace y qué no hace el paquete

An online shop: categories, product listings with translations, shipping methods, discount codes, web orders with lines and a fulfilment flow of pending, paid, shipped, delivered, cancelled and refunded. When the instance runs with the public site enabled, visitors browse the published listings and place orders without an account; the server prices every order from the published listing and never trusts the browser. There is no payment provider: an order starts as pending and the shop contacts the buyer. Refunds need a human approval from a manager; agents may only propose them. Customer name, email and addresses are personal data and are never public. Needs the Products package.

## Modelos

### `ecommerce_category`

A group of listings shown together in the shop

Grupo de lectura: `ecommerce.user`. Grupo de escritura: `ecommerce.manager`.

| Campo | Tipo | Clase de datos | Datos personales | Grupo | Los agentes ven | Descripción |
|---|---|---|---|---|---|---|
| `name` | text | `none` | no | `ecommerce.user` | en claro | Category name shown in the shop |
| `slug` | text | `none` | no | `ecommerce.user` | en claro | URL part of the category, lowercase with dashes |
| `description` | text | `none` | no | `ecommerce.user` | en claro | Short text about the category |
| `sequence` | number | `none` | no | `ecommerce.user` | en claro | Order among categories, lowest first |
| `published` | bool | `none` | no | `ecommerce.user` | en claro | Whether the category is visible to shoppers |

### `ecommerce_listing`

A product as it appears in the online shop

Grupo de lectura: `ecommerce.user`. Grupo de escritura: `ecommerce.manager`.

| Campo | Tipo | Clase de datos | Datos personales | Grupo | Los agentes ven | Descripción |
|---|---|---|---|---|---|---|
| `product_id` | ref → product | `none` | no | `ecommerce.user` | en claro | The product being sold online |
| `title` | text | `none` | no | `ecommerce.user` | en claro | Title shown in the shop |
| `slug` | text | `none` | no | `ecommerce.user` | en claro | URL part of the product page, lowercase with dashes |
| `summary` | text | `none` | no | `ecommerce.user` | en claro | One or two sentences shown on product cards |
| `description` | longtext | `none` | no | `ecommerce.user` | en claro | Description shown on the product page, in Markdown |
| `category_id` | ref → ecommerce_category | `none` | no | `ecommerce.user` | en claro | The category the listing is shown under |
| `price` | money | `none` | no | `ecommerce.user` | en claro | Shop price including tax (minor currency units, e.g. cents) |
| `compare_at_price` | money | `none` | no | `ecommerce.user` | en claro | Previous price shown crossed out (minor currency units) |
| `currency` | text | `none` | no | `ecommerce.user` | en claro | ISO 4217 currency code of the prices, for example EUR; empty means the shop currency from the instance settings |
| `sku` | text | `none` | no | `ecommerce.user` | en claro | Stock keeping unit shown on the product page |
| `stock_policy` | select (always_available, block_when_out, allow_backorder) | `none` | no | `ecommerce.user` | en claro | What happens when stock runs out: always_available, block_when_out, allow_backorder |
| `stock_quantity` | number | `none` | no | `ecommerce.user` | en claro | Units on hand, used with the stock policy. Orders do not reduce it: adjust it by hand |
| `published` | bool | `none` | no | `ecommerce.user` | en claro | Whether the listing is visible to shoppers |

### `ecommerce_listing_translation`

A listing translated into another language

Grupo de lectura: `ecommerce.user`. Grupo de escritura: `ecommerce.manager`.

| Campo | Tipo | Clase de datos | Datos personales | Grupo | Los agentes ven | Descripción |
|---|---|---|---|---|---|---|
| `listing_id` | ref → ecommerce_listing | `none` | no | `ecommerce.user` | en claro | The listing this translates |
| `lang` | select (en, de, fr, pl, fi, sv, es) | `none` | no | `ecommerce.user` | en claro | Language of the translation: en, de, fr, pl, fi, sv or es |
| `title` | text | `none` | no | `ecommerce.user` | en claro | Translated title |
| `summary` | text | `none` | no | `ecommerce.user` | en claro | Translated card text |
| `description` | longtext | `none` | no | `ecommerce.user` | en claro | Translated description in Markdown |
| `published` | bool | `none` | no | `ecommerce.user` | en claro | Whether the translation is shown; it is only reachable while its listing is published |

### `ecommerce_shipping_method`

A way of delivering orders with its price

Grupo de lectura: `ecommerce.user`. Grupo de escritura: `ecommerce.manager`.

| Campo | Tipo | Clase de datos | Datos personales | Grupo | Los agentes ven | Descripción |
|---|---|---|---|---|---|---|
| `name` | text | `none` | no | `ecommerce.user` | en claro | Name shown at checkout, for example Standard delivery |
| `carrier` | text | `none` | no | `ecommerce.user` | en claro | Carrier that delivers, for example DHL |
| `price` | money | `none` | no | `ecommerce.user` | en claro | Delivery price (minor currency units) |
| `free_over` | money | `none` | no | `ecommerce.user` | en claro | Order total above which delivery is free (minor currency units); empty means never |
| `delivery_days` | number | `none` | no | `ecommerce.user` | en claro | Usual number of days until delivery |
| `active` | bool | `none` | no | `ecommerce.user` | en claro | Whether shoppers can choose it |

### `ecommerce_discount_code`

A code a shopper enters at checkout for a reduction

Grupo de lectura: `ecommerce.user`. Grupo de escritura: `ecommerce.manager`.

| Campo | Tipo | Clase de datos | Datos personales | Grupo | Los agentes ven | Descripción |
|---|---|---|---|---|---|---|
| `code` | text | `none` | no | `ecommerce.user` | en claro | The code shoppers type, for example SPRING10 |
| `kind` | select (percent, fixed) | `none` | no | `ecommerce.user` | en claro | Type of reduction: percent or fixed |
| `value` | number | `none` | no | `ecommerce.user` | en claro | Reduction: basis points for percent (1000 is 10.00 percent), minor currency units for fixed |
| `starts_on` | date | `none` | no | `ecommerce.user` | en claro | First day the code works (YYYY-MM-DD) |
| `ends_on` | date | `none` | no | `ecommerce.user` | en claro | Last day the code works (YYYY-MM-DD) |
| `max_uses` | number | `none` | no | `ecommerce.user` | en claro | How many times the code may be used in total; empty means unlimited |
| `used_count` | number | `none` | no | `ecommerce.user` | en claro | How many times it has been used (kept up to date by hand) |
| `minimum_order` | money | `none` | no | `ecommerce.user` | en claro | Smallest order total the code applies to (minor currency units) |
| `active` | bool | `none` | no | `ecommerce.user` | en claro | Whether the code can be used |

### `ecommerce_order`

An order placed online

Grupo de lectura: `ecommerce.user`. Grupo de escritura: `ecommerce.user`.

| Campo | Tipo | Clase de datos | Datos personales | Grupo | Los agentes ven | Descripción |
|---|---|---|---|---|---|---|
| `number` | text | `none` | no | `ecommerce.user` | en claro | Order number shown to the shopper. Free text: packages cannot generate sequences; the public checkout makes a random one |
| `customer_email` | text | `internal` | sí | `ecommerce.user` | enmascarado | Email address of the shopper |
| `customer_name` | text | `internal` | sí | `ecommerce.user` | enmascarado | Name of the shopper |
| `customer_id` | ref → party | `none` | no | `ecommerce.user` | en claro | The matching contact, once the shopper is known |
| `shipping_address` | longtext | `internal` | sí | `ecommerce.user` | enmascarado | Delivery address |
| `billing_address` | longtext | `internal` | sí | `ecommerce.user` | enmascarado | Billing address when different from delivery |
| `shipping_method_id` | ref → ecommerce_shipping_method | `none` | no | `ecommerce.user` | en claro | The chosen way of delivery |
| `discount_code_id` | ref → ecommerce_discount_code | `none` | no | `ecommerce.user` | en claro | The discount code used, if any |
| `placed_on` | date | `none` | no | `ecommerce.user` | en claro | Day the order was placed (YYYY-MM-DD) |
| `currency` | text | `none` | no | `ecommerce.user` | en claro | ISO 4217 currency code, for example EUR |
| `subtotal` | money | `none` | no | `ecommerce.user` | en claro | Sum of the lines (minor currency units, entered not computed) |
| `discount_total` | money | `none` | no | `ecommerce.user` | en claro | Reduction from the discount code (minor currency units) |
| `shipping_total` | money | `none` | no | `ecommerce.user` | en claro | Delivery charge (minor currency units) |
| `tax_total` | money | `none` | no | `ecommerce.user` | en claro | Tax included in the total (minor currency units) |
| `total` | money | `none` | no | `ecommerce.user` | en claro | Amount the shopper pays (minor currency units) |
| `payment_reference` | text | `financial` | sí | `ecommerce.user` | retenido | Reference from the payment provider; never a card number |
| `tracking_reference` | text | `none` | no | `ecommerce.user` | en claro | Carrier tracking number |
| `access_token` | text | `secret` | no | `ecommerce.user` | retenido | Secret link token that lets the shopper who placed a public order see its confirmation page. Nobody can read it back |
| `state` | select (pending, paid, shipped, delivered, cancelled, refunded) | `none` | no | `ecommerce.user` | en claro | Fulfilment status: pending, paid, shipped, delivered, cancelled, refunded |

### `ecommerce_order_line`

One product line of a web order

Grupo de lectura: `ecommerce.user`. Grupo de escritura: `ecommerce.user`.

| Campo | Tipo | Clase de datos | Datos personales | Grupo | Los agentes ven | Descripción |
|---|---|---|---|---|---|---|
| `order_id` | ref → ecommerce_order | `none` | no | `ecommerce.user` | en claro | The order the line belongs to |
| `product_id` | ref → product | `none` | no | `ecommerce.user` | en claro | The product ordered |
| `listing_id` | ref → ecommerce_listing | `none` | no | `ecommerce.user` | en claro | The shop listing the line was ordered from |
| `description` | text | `none` | no | `ecommerce.user` | en claro | Product text as it was when ordered |
| `quantity` | number | `none` | no | `ecommerce.user` | en claro | Units ordered |
| `unit_price` | money | `none` | no | `ecommerce.user` | en claro | Price per unit including tax (minor currency units) |
| `subtotal` | money | `none` | no | `ecommerce.user` | en claro | Line total (minor currency units, entered not computed) |

## Flujos de trabajo

### `ecommerce_order`

| Acción | Mueve | Quién puede ejecutarla | Aprobación |
|---|---|---|---|
| `ecommerce_order.mark_paid` | state: pending → paid | `ecommerce.user` | no |
| `ecommerce_order.ship` | state: paid → shipped | `ecommerce.user` | no |
| `ecommerce_order.deliver` | state: shipped → delivered | `ecommerce.user` | no |
| `ecommerce_order.cancel` | state: pending → cancelled | `ecommerce.user` | no |
| `ecommerce_order.refund` | state: paid → refunded | `ecommerce.manager` | sí |
| `ecommerce_order.refund_delivered` | state: delivered → refunded | `ecommerce.manager` | sí |

## Grupos de permisos

Grupos que usa esta aplicación:

- `ecommerce.manager`
- `ecommerce.user`

## Pasos con aprobación

Pasos que un agente solo puede proponer:

- `ecommerce_order.refund`
- `ecommerce_order.refund_delivered`

## Qué pueden y qué no pueden hacer los agentes

Un agente puede leer, buscar, crear y actualizar registros de esta aplicación, y ejecutar las acciones que no requieren aprobación, dentro de los grupos de permisos de su token.

Solo puede proponer estos pasos, y una persona debe aprobarlos: `ecommerce_order.refund`, `ecommerce_order.refund_delivered`, `ecommerce_category.delete`, `ecommerce_listing.delete`, `ecommerce_listing_translation.delete`, `ecommerce_shipping_method.delete`, `ecommerce_discount_code.delete`, `ecommerce_order.delete`, `ecommerce_order_line.delete`.

Los datos personales se enmascaran como tokens marcadores: `ecommerce_order.customer_email`, `ecommerce_order.customer_name`, `ecommerce_order.shipping_address`, `ecommerce_order.billing_address`.

Estos campos se retienen por completo y los agentes no los ven: `ecommerce_order.payment_reference`, `ecommerce_order.access_token`.

## Dependencias

- `base`
- `product`

## Instalación

Instálala desde la aplicación Customize (Marketplace) o desde la línea de comandos:

```bash
obop modules install-from ecommerce
```

Requiere una base de datos y derechos de administrador.

## Crea la tuya

[La guía de módulos explica cómo se escriben aplicaciones como esta](/es/docs/reference/module-manifest/)
