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

@@ -594,7 +594,7 @@ export async function getRecoRulesByProductIds({ tenant_id, product_ids = [] })
export async function getRecoRuleByKey({ tenant_id, rule_key }) {
const sql = `
select id, tenant_id, rule_key, trigger, queries, boosts, ask_slots, active, priority,
trigger_product_ids, recommended_product_ids, created_at, updated_at
trigger_product_ids, recommended_product_ids, rule_type, trigger_event, created_at, updated_at
from product_reco_rules
where tenant_id=$1 and rule_key=$2
limit 1
@@ -603,6 +603,95 @@ export async function getRecoRuleByKey({ tenant_id, rule_key }) {
return rows[0] || null;
}
/**
* Obtener reglas de qty_per_person por tipo de evento (asado, horno, etc.)
* DEPRECATED: Usar getProductQtyRulesByEvent en su lugar
*/
export async function getQtyPerPersonRules({ tenant_id, event_type }) {
const sql = `
select r.id, r.rule_key, r.rule_type, r.trigger_event, r.priority,
json_agg(json_build_object(
'woo_product_id', i.woo_product_id,
'audience_type', i.audience_type,
'qty_per_person', i.qty_per_person,
'unit', i.unit,
'reason', i.reason,
'display_order', i.display_order
) order by i.display_order) as items
from product_reco_rules r
inner join reco_rule_items i on i.rule_id = r.id
where r.tenant_id = $1
and r.active = true
and r.rule_type = 'qty_per_person'
and (r.trigger_event = $2 or r.trigger_event is null)
group by r.id, r.rule_key, r.rule_type, r.trigger_event, r.priority
order by
case when r.trigger_event = $2 then 0 else 1 end,
r.priority asc
`;
const { rows } = await pool.query(sql, [tenant_id, event_type]);
return rows;
}
/**
* Obtener reglas de cantidad por evento desde la nueva tabla product_qty_rules
*/
export async function getProductQtyRulesByEvent({ tenant_id, event_type }) {
const sql = `
select woo_product_id, event_type, person_type, qty_per_person, unit
from product_qty_rules
where tenant_id = $1 and event_type = $2
order by woo_product_id, person_type
`;
const { rows } = await pool.query(sql, [tenant_id, event_type]);
return rows;
}
/**
* Obtener items de una regla específica con detalles
*/
export async function getRecoRuleItems({ rule_id }) {
const sql = `
select id, rule_id, woo_product_id, audience_type, qty_per_person, unit, reason, display_order
from reco_rule_items
where rule_id = $1
order by display_order asc
`;
const { rows } = await pool.query(sql, [rule_id]);
return rows;
}
/**
* Obtener productos mapeados a un alias con scores
*/
export async function getAliasProductMappings({ tenant_id, alias }) {
const normalizedAlias = String(alias || "").toLowerCase().trim();
if (!normalizedAlias) return [];
const sql = `
select woo_product_id, score
from alias_product_mappings
where tenant_id = $1 and alias = $2
order by score desc
`;
const { rows } = await pool.query(sql, [tenant_id, normalizedAlias]);
return rows;
}
/**
* Obtener todos los mappings de alias para un tenant (para búsqueda)
*/
export async function getAllAliasProductMappings({ tenant_id }) {
const sql = `
select alias, woo_product_id, score
from alias_product_mappings
where tenant_id = $1
order by alias, score desc
`;
const { rows } = await pool.query(sql, [tenant_id]);
return rows;
}
export async function getProductEmbedding({ tenant_id, content_hash }) {
const sql = `
select tenant_id, content_hash, content_text, embedding, model, updated_at