productos, equivalencias, cross-sell y cantidades

This commit is contained in:
Lucas Tettamanti
2026-01-18 18:28:28 -03:00
parent 8cc4744c49
commit c7c56ddbfc
32 changed files with 4083 additions and 2073 deletions

View File

@@ -0,0 +1,39 @@
-- migrate:up
-- Nueva tabla para items de reglas de recomendación con qty/unit
create table if not exists reco_rule_items (
id bigserial primary key,
rule_id bigint not null references product_reco_rules(id) on delete cascade,
woo_product_id integer not null,
qty_per_person numeric(6,3), -- ej: 0.200 = 200g por persona
unit text, -- kg | g | unidad
reason text, -- razón opcional (ej: "base del asado")
display_order integer not null default 0,
unique (rule_id, woo_product_id)
);
create index if not exists reco_rule_items_rule_idx on reco_rule_items(rule_id);
-- Agregar tipo de regla y evento trigger a product_reco_rules
alter table product_reco_rules
add column if not exists rule_type text not null default 'crosssell',
add column if not exists trigger_event text;
-- Índice para búsqueda por tipo y evento
create index if not exists product_reco_rules_type_event_idx
on product_reco_rules(tenant_id, rule_type, trigger_event)
where active = true;
-- Migrar datos existentes: copiar recommended_product_ids a reco_rule_items
insert into reco_rule_items (rule_id, woo_product_id, display_order)
select r.id, unnest(r.recommended_product_ids), row_number() over (partition by r.id)
from product_reco_rules r
where array_length(r.recommended_product_ids, 1) > 0
on conflict (rule_id, woo_product_id) do nothing;
-- migrate:down
drop index if exists product_reco_rules_type_event_idx;
alter table product_reco_rules
drop column if exists rule_type,
drop column if exists trigger_event;
drop table if exists reco_rule_items;

View File

@@ -0,0 +1,24 @@
-- migrate:up
-- Nueva tabla para mapeos alias -> múltiples productos con score
create table if not exists alias_product_mappings (
tenant_id uuid not null references tenants(id) on delete cascade,
alias text not null,
woo_product_id integer not null,
score numeric(4,2) not null default 1.0,
created_at timestamptz not null default now(),
primary key (tenant_id, alias, woo_product_id)
);
create index if not exists alias_product_mappings_alias_idx
on alias_product_mappings(tenant_id, alias);
-- Migrar datos existentes: copiar woo_product_id de product_aliases
insert into alias_product_mappings (tenant_id, alias, woo_product_id, score)
select tenant_id, alias, woo_product_id, coalesce(boost, 1.0)
from product_aliases
where woo_product_id is not null
on conflict (tenant_id, alias, woo_product_id) do nothing;
-- migrate:down
drop table if exists alias_product_mappings;

View File

@@ -0,0 +1,12 @@
-- migrate:up
-- Agregar campo para distinguir adulto/niño
alter table reco_rule_items
add column if not exists audience_type text not null default 'adult';
-- Valores válidos: 'adult', 'child', 'all'
comment on column reco_rule_items.audience_type is 'Tipo de audiencia: adult, child, all';
-- migrate:down
alter table reco_rule_items
drop column if exists audience_type;

View File

@@ -0,0 +1,41 @@
-- migrate:up
-- Nueva tabla simplificada para cantidades por producto/evento/persona
create table if not exists product_qty_rules (
id bigserial primary key,
tenant_id uuid not null references tenants(id) on delete cascade,
woo_product_id integer not null,
event_type text not null, -- 'asado' | 'horno' | 'cumple' | 'almuerzo'
person_type text not null, -- 'adult' | 'child'
qty_per_person numeric(6,3), -- cantidad por persona
unit text not null default 'kg', -- 'kg' | 'g' | 'unidad'
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
unique (tenant_id, woo_product_id, event_type, person_type)
);
create index if not exists product_qty_rules_tenant_idx on product_qty_rules(tenant_id);
create index if not exists product_qty_rules_product_idx on product_qty_rules(tenant_id, woo_product_id);
create index if not exists product_qty_rules_event_idx on product_qty_rules(tenant_id, event_type);
-- Migrar datos existentes de reco_rule_items (donde la regla es tipo qty_per_person)
insert into product_qty_rules (tenant_id, woo_product_id, event_type, person_type, qty_per_person, unit)
select
r.tenant_id,
i.woo_product_id,
coalesce(r.trigger_event, 'asado') as event_type,
coalesce(i.audience_type, 'adult') as person_type,
i.qty_per_person,
coalesce(i.unit, 'kg') as unit
from reco_rule_items i
inner join product_reco_rules r on r.id = i.rule_id
where r.rule_type = 'qty_per_person'
and i.qty_per_person is not null
on conflict (tenant_id, woo_product_id, event_type, person_type)
do update set
qty_per_person = excluded.qty_per_person,
unit = excluded.unit,
updated_at = now();
-- migrate:down
drop table if exists product_qty_rules;