BranchGood


La oferta de un Good en una Branch: es lo que un comercio realmente lista y vende. Mientras el Good define qué es el producto, el BranchGood agrega el precio de venta, el stock y la disponibilidad de esa sucursal, además del precio personalizado según el cliente que consulta (ver BranchPriceList). Al asociar un Good a un Branch se copian en cascada sus propiedades (GoodProperty) con sus valores por defecto.

Precio

  • min_price_e2 — precio de venta del producto (× 100) en la moneda local del comercio. El nombre quedó así por retro-compatibilidad: no es un precio mínimo. Cuando un admin edita el precio de venta, edita este atributo.
  • custom_data (solo lectura) — objeto con los distintos precios ya calculados, incluido el monto formateado:
    • display_price — precio a mostrar (visual).
    • list_price — precio original; mostrar tachado si difiere de display_price (suele indicar descuento).
    • price_e2 — precio efectivo para sumar al carrito.
    • prefijo unit_ — monto por unidad (p. ej. el precio por Kg en productos por peso).
    • prefijo extras_ — monto mínimo según los extras obligatorios del producto.
    • currency — moneda local del comercio.
    • conversion — los mismos montos convertidos a otra moneda. Se elige con el header X-Currency: <ISO> (debe ser una moneda soportada por la Company); por defecto, la moneda local.
    • real_prices — precios reales en la moneda local del comercio, para uso del administrador.

Stock y disponibilidad

  • quantity_real — inventario disponible, o null si es ilimitado.
  • has_stock_for_selling — false si el stock no alcanza para vender.
  • available — lo habilitó/deshabilitó un administrador.
  • available_for_selling — false si available es false o no hay stock. Para mostrar un producto agotado, evaluar available_for_selling === false.

Unidad de venta (unit_config)

Configuración para vender por fracción/peso:

  • enabled — si la configuración de unidad está activa.
  • display_mode — cómo mostrarla en pantalla.
  • fraction — unidades de división por cada unidad de stock. Ej. 1000 = 1 unidad equivale a 1000 Gr; cada venta de 1000 reduce el stock en 1.
  • min_quantity / max_quantity / step_quantity — mínimo, máximo e incremento a vender, en fraction.
  • unit_name — la unidad que representa fraction (ej. Gr). Nota: la unidad "grande" (Kg) va en Good.unit; quedaría Good.unit = 'Kg', unit_name = 'Gr', fraction = 1000.
  • weight_per_unit — peso estimado por unidad (ej. una manzana ≈ 205 Gr). Sirve para armar interfaces de venta por unidad en productos por peso; se puede usar aun con enabled = false.

weight_per_unit (atributo del BranchGood) equivale a ese unit_config.weight_per_unit.

Otros

  • notes_enabled — pedir instrucciones especiales (opcionales) al ordenar.
  • tags — etiquetas del producto; $Hot es una etiqueta gestionada por el sistema para los más vendidos 🔥.
  • promo_id / promo_info — promoción activa sobre este producto en la sucursal (mismo formato de promo_info que en Branch).
  • featured_good_config / featured_in_order — configuración y orden del producto cuando está destacado.
  • discount_info — detalle del descuento aplicado.
  • list_order — orden del producto dentro de su categoría en la sucursal.
  • tax / sale_tax — cálculo de impuestos (AmountWithTax) sobre el precio de lista y sobre el precio de venta. price_before_tax_e2 / price_after_tax_e2 y applied_tax_e2 son los montos resultantes.

Estructura de Datos

Atributo Tipo Descripción
id int
min_price_e2 int Precio de venta del producto en la moneda local del comercio (× 100). No es un precio mínimo (nombre por retro-compatibilidad)
rating_e2 int Rating del producto en la sucursal (× 100)
rating_sum int Suma de calificaciones recibidas
rating_count int Cantidad de calificaciones recibidas
available bool El administrador habilitó el producto para la venta
provider_fee_e2 int Comisión del proveedor por vender este producto, monto fijo (× 100)
provider_fee_prc float Comisión del proveedor, porcentaje (fracción 0–1)
created_at datetime\|null
updated_at datetime\|null
branch_id int Sucursal que ofrece el producto
good_id int {@link Good} ofertado
branch_group_id int\|null Comercio (marca) de la sucursal
eta string\|null Tiempo estimado de preparación del producto en esta sucursal
promo_id int\|null {@link Coupon} de la promoción activa sobre este producto
promo_info string\|null Etiqueta de la promoción (ver formato en {@link Branch})
last_sync_id int\|null Referencia de la última sincronización de catálogo
quantity_real float\|null Inventario disponible; null = ilimitado
extras_price_e2 int\|null Monto mínimo por los extras obligatorios (× 100)
list_order int Orden del producto dentro de su categoría en la sucursal
computed array Caché interno de valores derivados (oculto)
featured_good_config FeaturedGoodConfig\|null Configuración del producto cuando está destacado
discount_info DiscountInfo\|null Detalle del descuento aplicado
materials_stock float\|null Stock derivado de los insumos del producto
tax AmountWithTax Cálculo de impuestos sobre el precio de lista
sale_tax AmountWithTax Cálculo de impuestos sobre el precio de venta
allLogs ApiLog>
applied_tax_e2 int Impuesto aplicado al precio de venta (× 100)
available_for_selling bool El producto se puede comprar (habilitado y con stock)
barcodes array\|null Códigos de barras del producto
base_unit_sale_price_e2 int Precio de venta por unidad base, sin extras (× 100)
branch Branch
branchGoodProperties BranchGoodProperty> Propiedades/variantes del producto en la sucursal
branchGroup BranchGroup\|null
calculated_eta int\|null ETA calculado del producto (minutos)
categories Category> Categorías del producto en la sucursal
custom_data array Precios ya calculados del producto (ver "Precio")
featured_in_order int\|null Orden del producto cuando está destacado
details mixed Descripción larga (heredado del {@link Good})
eta_config EtaConfig\|null Configuración de ETA (heredado del {@link Good})
good_type_id mixed {@link GoodType} (heredado del {@link Good})
limit_type mixed Ventana del límite de compra (heredado del {@link Good})
max_quantity mixed Límite de compra por cliente (heredado del {@link Good})
name mixed Nombre del producto (heredado del {@link Good})
notes_enabled mixed Pedir instrucciones especiales al ordenar (heredado del {@link Good})
picture_urls mixed Imágenes horizontales (heredado del {@link Good})
short_details mixed Descripción corta (heredado del {@link Good})
sku mixed Código SKU (heredado del {@link Good})
tags array\|null Etiquetas del producto; $Hot = más vendidos, gestionada por el sistema
type mixed Bitmask de tipo (heredado del {@link Good})
unit mixed Unidad de venta (heredado del {@link Good})
vertical_picture_urls mixed Imágenes verticales (heredado del {@link Good})
weight_per_unit string\|null Peso estimado por unidad (= unit_config.weight_per_unit)
good Good
goodCategories GoodCategory>
goodProperties GoodProperty>
has_fixed_stock bool El producto maneja stock fijo (quantity_real no es null)
has_stock_for_selling bool Hay stock suficiente para vender
is_combo bool\|null El producto es un combo (heredado del {@link Good})
is_service bool El producto es un servicio (heredado del {@link Good})
label string\|null Etiqueta destacada del producto (heredado del {@link Good})
logs ApiLog>
materials GoodMaterial>
presentation string\|null Texto de presentación para mostrar (heredado del {@link Good})
price_after_tax Money Precio de venta con impuesto incluido
price_after_tax_e2 int Precio de venta con impuesto, monto (× 100)
price_before_tax Money Precio de venta sin impuesto
price_before_tax_e2 int Precio de venta sin impuesto, monto (× 100)
promo Coupon\|null Cupón de la promoción activa
properties Property>
quantity int\|null Cantidad disponible en unidades de stock
quantity_real_available float\|null Inventario realmente disponible (descuenta reservas); null = ilimitado
sales OrderedGood> Ventas del producto en la sucursal
unit_config SellingUnit\|null Configuración de venta por peso/fracción (ver "Unidad de venta")
{
    "id": 92,
    "min_price_e2": 1200,
    "rating_e2": 0,
    "rating_sum": 0,
    "rating_count": 0,
    "available": false,
    "provider_fee_e2": 0,
    "provider_fee_prc": 0,
    "created_at": "2020-04-20 20:37:52",
    "updated_at": "2025-08-20 15:02:58",
    "branch_id": 22,
    "good_id": 105,
    "branch_group_id": 42,
    "eta": null,
    "promo_id": null,
    "promo_info": null,
    "last_sync_id": 639,
    "quantity_real": 0,
    "extras_price_e2": 0,
    "list_order": 65535,
    "featured_good_config": null,
    "good_type_id": null,
    "sku": null,
    "type": 0,
    "name": "Prueba2",
    "unit": "und",
    "presentation": "per_unit",
    "max_quantity": null,
    "limit_type": null,
    "details": "Aaaa",
    "short_details": "n/a",
    "picture_urls": [
        "http://127.0.0.1:8000/storage/static/default/product_category_logo.png"
    ],
    "vertical_picture_urls": [
        "http://127.0.0.1:8000/storage/static/default/product_category_logo_portrait.jpg"
    ],
    "notes_enabled": true,
    "custom_data": {
        "list_price_e2": 1200,
        "display_price_e2": 1200,
        "price_e2": 1200,
        "extras_list_price_e2": 0,
        "extras_display_price_e2": 0,
        "extras_price_e2": 0,
        "client_id": null,
        "branch_price_list_id": 426,
        "currency": {
            "id": 476,
            "enabled": true,
            "iso": "USD",
            "symbol": "$",
            "conversion_factor": 1,
            "related_iso": "USD",
            "decimals_count": 2,
            "format": "0.00$",
            "decimal_point": ".",
            "use_thousands_separator": true,
            "thousands_separator": ",",
            "is_local": true,
            "is_international": true,
            "created_at": "2021-07-15 19:22:15",
            "updated_at": "2025-11-25 13:45:57",
            "company_id": 116,
            "is_custom": false,
            "branch_id": 22,
            "auto_sync": true,
            "auto_sync_provider": "legacy",
            "use_conversion": false,
            "available": true,
            "related_iso_expected": "USD",
            "related_iso_error": false
        },
        "conversion": {
            "list_price_e2": 1200,
            "display_price_e2": 1200,
            "price_e2": 1200,
            "extras_list_price_e2": 0,
            "extras_display_price_e2": 0,
            "extras_price_e2": 0,
            "currency": {
                "id": 476,
                "enabled": true,
                "iso": "USD",
                "symbol": "$",
                "conversion_factor": 1,
                "related_iso": "USD",
                "decimals_count": 2,
                "format": "0.00$",
                "decimal_point": ".",
                "use_thousands_separator": true,
                "thousands_separator": ",",
                "is_local": true,
                "is_international": true,
                "created_at": "2021-07-15 19:22:15",
                "updated_at": "2025-11-25 13:45:57",
                "company_id": 116,
                "is_custom": false,
                "branch_id": 22,
                "auto_sync": true,
                "auto_sync_provider": "legacy",
                "use_conversion": false,
                "available": true,
                "related_iso_expected": "USD",
                "related_iso_error": false
            },
            "list_price": "12.00$",
            "display_price": "12.00$"
        },
        "real_prices": {
            "list_price_e2": 1200,
            "display_price_e2": 1200,
            "price_e2": 1200,
            "extras_list_price_e2": 0,
            "extras_display_price_e2": 0,
            "extras_price_e2": 0
        },
        "list_price": "12.00$",
        "display_price": "12.00$",
        "unit_list_price": "12.00$",
        "unit_display_price": "12.00$"
    },
    "quantity_real_available": 0,
    "quantity": 0,
    "unit_config": null,
    "weight_per_unit": null,
    "has_stock_for_selling": false,
    "available_for_selling": false,
    "calculated_eta": null,
    "eta_config": null,
    "tags": [],
    "is_service": false,
    "is_combo": false,
    "barcodes": [],
    "label": null,
    "discount_info": null,
    "featured_in_order": null
}

Endpoints

Insertar BranchGood

Insertar BranchGood

Asocia un Good con un Branch. Cuando un BranchGood es insertado, el API automáticamente asocia las GoodProperties del producto asociado y crea los registros de BranchProperty para manejar el stock y precios.

{info} Si no se especifica algún atributo, se usa el valor del Good. En caso de min_price_e2 se utiliza el atributo price_e2 del Good.

{warning} Endpoint deprecado. Gestionar el catálogo desde el branch_group (marca).

Método URI Cabeceras
PUT /companies/{companyId}/branches/{branchId}/goods/{goodId} Authorization
{
    "eta": "string|max:32",
    "min_price_e2": "integer|min:0",
    "provider_fee_e2": "integer",
    "provider_fee_prc": "numeric|between:0.0000,1.0000",
    "quantity": "integer",
    "quantity_real": "numeric",
    "list_order": "integer",
    "featured_good_config": {
        "is_enabled": "nullable|boolean",
        "in_order": "nullable|integer|min:1",
        "blocks": [
            {
                "day_sunday": "nullable|boolean",
                "day_monday": "nullable|boolean",
                "day_tuesday": "nullable|boolean",
                "day_wednesday": "nullable|boolean",
                "day_thursday": "nullable|boolean",
                "day_friday": "nullable|boolean",
                "day_saturday": "nullable|boolean",
                "hour_beg": {
                    "nullable": true,
                    "string": true,
                    "regex": "/^([0-1][0-9]|2[0-3]):[0-5][0-9]$/"
                },
                "hour_end": {
                    "nullable": true,
                    "string": true,
                    "regex": "/^([0-1][0-9]|2[0-3]):[0-5][0-9]$/"
                }
            }
        ]
    }
}

Listar BranchGood

Listar BranchGood de Branch

{info} Soporta: Paginación Filters Carga dinámica

Listar productos de una sucursal

Lista los BranchGood de la sucursal: productos con precio, stock y disponibilidad. El header X-Currency: <ISO> convierte los montos.

Método URI Cabeceras
GET /companies/{companyId}/branches/{branchId}/branch-goods N/A

Muestra las categorías que están siendo usadas por los BranchGoods. Si alguna Category no tiene Goods asociados

a la Branch actual, esa Category no se mostrará.

{info} Soporta: Paginación Filters

Método URI Cabeceras
GET /companies/{companyId}/branches/{branchId}/branch-goods/categories N/A

Listar BranchGood de Category

{info} Soporta: Paginación Filters Carga dinámica

Listar productos de una categoría en una sucursal

Lista los BranchGood de la sucursal que pertenecen a la Category indicada, con precio y stock.

Método URI Cabeceras
GET /companies/{companyId}/branches/{branchId}/categories/{categoryId}/branch-goods N/A

Mostrar BranchGood

{info} Soporta: Carga dinámica

Mostrar producto de sucursal

Devuelve el BranchGood por su id: producto con precio, stock y disponibilidad de esa sucursal. El header X-Currency: <ISO> convierte los montos de custom_data.

Método URI Cabeceras
GET /companies/{companyId}/branch-goods/{branchGoodId} N/A

Mostrar producto de una sucursal por good_id

{info} Soporta: Carga dinámica

Devuelve el BranchGood de la sucursal para el Good indicado.

Método URI Cabeceras
GET /companies/{companyId}/branches/{branchId}/goods/{goodId} N/A

Actualizar BranchGood

Actualizar producto de sucursal

Actualiza el BranchGood: precio de venta (min_price_e2), stock (quantity_real), ETA, orden en la lista, promoción, etc. Cambiar el tipo del Good subyacente tiene las mismas restricciones que en el endpoint de productos.

Método URI Cabeceras
PATCH /companies/{companyId}/branch-goods/{branchGoodId} Authorization
{
    "eta": "string|max:32",
    "min_price_e2": "integer|min:0",
    "provider_fee_e2": "integer",
    "provider_fee_prc": "numeric|between:0.0000,1.0000",
    "quantity": "integer",
    "quantity_real": "numeric",
    "list_order": "integer",
    "featured_good_config": {
        "is_enabled": "nullable|boolean",
        "in_order": "nullable|integer|min:1",
        "blocks": [
            {
                "day_sunday": "nullable|boolean",
                "day_monday": "nullable|boolean",
                "day_tuesday": "nullable|boolean",
                "day_wednesday": "nullable|boolean",
                "day_thursday": "nullable|boolean",
                "day_friday": "nullable|boolean",
                "day_saturday": "nullable|boolean",
                "hour_beg": {
                    "nullable": true,
                    "string": true,
                    "regex": "/^([0-1][0-9]|2[0-3]):[0-5][0-9]$/"
                },
                "hour_end": {
                    "nullable": true,
                    "string": true,
                    "regex": "/^([0-1][0-9]|2[0-3]):[0-5][0-9]$/"
                }
            }
        ]
    }
}

Actualizar producto de una sucursal por good_id (deprecado)

{warning} Endpoint deprecado. Usar PATCH branch-goods/{branchGoodId}.

Actualiza el BranchGood de la sucursal para el Good indicado.

Método URI Cabeceras
PATCH /companies/{companyId}/branches/{branchId}/goods/{goodId} Authorization
{
    "eta": "string|max:32",
    "min_price_e2": "integer|min:0",
    "provider_fee_e2": "integer",
    "provider_fee_prc": "numeric|between:0.0000,1.0000",
    "quantity": "integer",
    "quantity_real": "numeric",
    "list_order": "integer",
    "featured_good_config": {
        "is_enabled": "nullable|boolean",
        "in_order": "nullable|integer|min:1",
        "blocks": [
            {
                "day_sunday": "nullable|boolean",
                "day_monday": "nullable|boolean",
                "day_tuesday": "nullable|boolean",
                "day_wednesday": "nullable|boolean",
                "day_thursday": "nullable|boolean",
                "day_friday": "nullable|boolean",
                "day_saturday": "nullable|boolean",
                "hour_beg": {
                    "nullable": true,
                    "string": true,
                    "regex": "/^([0-1][0-9]|2[0-3]):[0-5][0-9]$/"
                },
                "hour_end": {
                    "nullable": true,
                    "string": true,
                    "regex": "/^([0-1][0-9]|2[0-3]):[0-5][0-9]$/"
                }
            }
        ]
    }
}

Eliminar BranchGood

Eliminar BranchGood

Desvincula un Good de un Branch. Cuando un BranchGood es eliminado, el API automáticamente elimina los GoodProperties del producto desvinculado y elimina los registros huérfanos de BranchProperty.

Método URI Cabeceras
DELETE /companies/{companyId}/branches/{branchId}/goods/{goodId} Authorization

Acciones de BranchGood

Acción en lote sobre productos de sucursal

Ejecuta una acción sobre varios BranchGood a la vez (campo ids). El parámetro de ruta action acepta: set-available, set-unavailable, update, delete. Cada BranchGood se procesa como si se llamara al endpoint individual; la respuesta detalla el resultado por ítem. Los errores de negocio son los del endpoint de la acción elegida.

Método URI Cabeceras
POST /companies/{companyId}/branch-goods/batch-action/{action} Authorization
{
    "ids": [
        "integer|min:1"
    ],
    "payload": ""
}

Buscar productos de sucursal

{info} Soporta: Paginación Filters Carga dinámica

Búsqueda global de BranchGood por texto (search) en toda la company, con precio y stock por sucursal.

Método URI Cabeceras
GET /companies/{companyId}/branch-goods/search N/A
{
    "q": "required|string",
    "paginate": "nullable|boolean",
    "results_mode": "string|in:goods,branch",
    "limit": "nullable|integer",
    "latitude_e6": "nullable|integer|between:-90000000,90000000",
    "longitude_e6": "nullable|integer|between:-180000000,180000000",
    "client_id": "nullable|integer",
    "category_id": "nullable|integer"
}

Habilitar producto de sucursal

Marca el BranchGood como disponible para la venta (available = true). Requiere stock y al menos una categoría asignada.

Método URI Cabeceras
POST /companies/{companyId}/branch-goods/{branchGoodId}/set-available Authorization

Errores de negocio

Código HTTP Cuándo ocurre
EA211 400 El producto ya está disponible.
EA212 400 El producto no tiene stock.
EA213 400 El producto no tiene ninguna categoría asignada.

Deshabilitar producto de sucursal

Marca el BranchGood como no disponible para la venta (available = false).

Método URI Cabeceras
POST /companies/{companyId}/branch-goods/{branchGoodId}/set-unavailable Authorization

Errores de negocio

Código HTTP Cuándo ocurre
EA210 400 El producto no está disponible.

Eliminar producto de sucursal por id

Desvincula el BranchGood (por su id) de la sucursal: elimina sus GoodProperty y los BranchProperty huérfanos. Si la sucursal queda inválida para operar, se oculta automáticamente.

Método URI Cabeceras
DELETE /companies/{companyId}/branch-goods/{branchGoodId} Authorization

Productos destacados de una sucursal

{info} Soporta: Paginación Filters Carga dinámica

Devuelve los BranchGood destacados de la sucursal, según su featured_good_config.

Método URI Cabeceras
GET /companies/{companyId}/branches/{branchId}/branch-goods/featured N/A

Buscar productos de una sucursal

{info} Soporta: Paginación Filters Carga dinámica

Búsqueda por texto (search) entre los BranchGood de la sucursal.

Método URI Cabeceras
GET /companies/{companyId}/branches/{branchId}/branch-goods/search N/A
{
    "q": "required|string",
    "paginate": "nullable|boolean",
    "results_mode": "string|in:goods,branch",
    "limit": "nullable|integer",
    "latitude_e6": "nullable|integer|between:-90000000,90000000",
    "longitude_e6": "nullable|integer|between:-180000000,180000000",
    "client_id": "nullable|integer",
    "category_id": "nullable|integer"
}

Relaciones