mejoras en el modelo de clarificacion de productos
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { handleSearchProducts, handleListProducts, handleGetProduct, handleSyncProducts } from "../handlers/products.js";
|
||||
import { handleSearchProducts, handleListProducts, handleGetProduct, handleSyncProducts, handleUpdateProductUnit, handleBulkUpdateProductUnit, handleUpdateProduct } from "../handlers/products.js";
|
||||
|
||||
export const makeSearchProducts = (tenantIdOrFn) => async (req, res) => {
|
||||
try {
|
||||
@@ -54,3 +54,60 @@ export const makeSyncProducts = (tenantIdOrFn) => async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const makeUpdateProductUnit = (tenantIdOrFn) => async (req, res) => {
|
||||
try {
|
||||
const tenantId = typeof tenantIdOrFn === "function" ? tenantIdOrFn() : tenantIdOrFn;
|
||||
const wooProductId = req.params.id;
|
||||
const { sell_unit } = req.body || {};
|
||||
|
||||
if (!sell_unit || !["kg", "unit"].includes(sell_unit)) {
|
||||
return res.status(400).json({ ok: false, error: "invalid_sell_unit" });
|
||||
}
|
||||
|
||||
const result = await handleUpdateProductUnit({ tenantId, wooProductId, sell_unit });
|
||||
res.json(result);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ ok: false, error: "internal_error" });
|
||||
}
|
||||
};
|
||||
|
||||
export const makeBulkUpdateProductUnit = (tenantIdOrFn) => async (req, res) => {
|
||||
try {
|
||||
const tenantId = typeof tenantIdOrFn === "function" ? tenantIdOrFn() : tenantIdOrFn;
|
||||
const { woo_product_ids, sell_unit } = req.body || {};
|
||||
|
||||
if (!sell_unit || !["kg", "unit"].includes(sell_unit)) {
|
||||
return res.status(400).json({ ok: false, error: "invalid_sell_unit" });
|
||||
}
|
||||
|
||||
if (!Array.isArray(woo_product_ids) || !woo_product_ids.length) {
|
||||
return res.status(400).json({ ok: false, error: "invalid_woo_product_ids" });
|
||||
}
|
||||
|
||||
const result = await handleBulkUpdateProductUnit({ tenantId, wooProductIds: woo_product_ids, sell_unit });
|
||||
res.json(result);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ ok: false, error: "internal_error" });
|
||||
}
|
||||
};
|
||||
|
||||
export const makeUpdateProduct = (tenantIdOrFn) => async (req, res) => {
|
||||
try {
|
||||
const tenantId = typeof tenantIdOrFn === "function" ? tenantIdOrFn() : tenantIdOrFn;
|
||||
const wooProductId = req.params.id;
|
||||
const { sell_unit, categories } = req.body || {};
|
||||
|
||||
if (sell_unit && !["kg", "unit"].includes(sell_unit)) {
|
||||
return res.status(400).json({ ok: false, error: "invalid_sell_unit" });
|
||||
}
|
||||
|
||||
const result = await handleUpdateProduct({ tenantId, wooProductId, sell_unit, categories });
|
||||
res.json(result);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ ok: false, error: "internal_error" });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ export async function listProducts({ tenantId, q = "", limit = 2000, offset = 0
|
||||
categories,
|
||||
attributes_normalized,
|
||||
updated_at as refreshed_at,
|
||||
raw as payload
|
||||
raw as payload,
|
||||
raw->>'_sell_unit_override' as sell_unit
|
||||
from woo_products_snapshot
|
||||
where tenant_id = $1
|
||||
and (name ilike $2 or coalesce(slug,'') ilike $2)
|
||||
@@ -41,7 +42,8 @@ export async function listProducts({ tenantId, q = "", limit = 2000, offset = 0
|
||||
categories,
|
||||
attributes_normalized,
|
||||
updated_at as refreshed_at,
|
||||
raw as payload
|
||||
raw as payload,
|
||||
raw->>'_sell_unit_override' as sell_unit
|
||||
from woo_products_snapshot
|
||||
where tenant_id = $1
|
||||
order by name asc
|
||||
@@ -65,7 +67,8 @@ export async function getProductByWooId({ tenantId, wooProductId }) {
|
||||
categories,
|
||||
attributes_normalized,
|
||||
updated_at as refreshed_at,
|
||||
raw as payload
|
||||
raw as payload,
|
||||
raw->>'_sell_unit_override' as sell_unit
|
||||
from woo_products_snapshot
|
||||
where tenant_id = $1 and woo_id = $2
|
||||
limit 1
|
||||
@@ -74,6 +77,66 @@ export async function getProductByWooId({ tenantId, wooProductId }) {
|
||||
return rows[0] || null;
|
||||
}
|
||||
|
||||
export async function updateProductSellUnit({ tenantId, wooProductId, sell_unit }) {
|
||||
const sql = `
|
||||
update woo_products_snapshot
|
||||
set raw = jsonb_set(coalesce(raw, '{}'::jsonb), '{_sell_unit_override}', $3::jsonb)
|
||||
where tenant_id = $1 and woo_id = $2
|
||||
returning woo_id as woo_product_id
|
||||
`;
|
||||
const { rows } = await pool.query(sql, [tenantId, wooProductId, JSON.stringify(sell_unit)]);
|
||||
return rows[0] || null;
|
||||
}
|
||||
|
||||
export async function bulkUpdateProductSellUnit({ tenantId, wooProductIds, sell_unit }) {
|
||||
if (!wooProductIds || !wooProductIds.length) return { updated: 0 };
|
||||
|
||||
const sql = `
|
||||
update woo_products_snapshot
|
||||
set raw = jsonb_set(coalesce(raw, '{}'::jsonb), '{_sell_unit_override}', $3::jsonb)
|
||||
where tenant_id = $1 and woo_id = ANY($2::int[])
|
||||
`;
|
||||
const result = await pool.query(sql, [tenantId, wooProductIds, JSON.stringify(sell_unit)]);
|
||||
return { updated: result.rowCount };
|
||||
}
|
||||
|
||||
export async function updateProduct({ tenantId, wooProductId, sell_unit, categories }) {
|
||||
// Build the JSONB update dynamically
|
||||
let updates = [];
|
||||
let params = [tenantId, wooProductId];
|
||||
let paramIdx = 3;
|
||||
|
||||
if (sell_unit) {
|
||||
updates.push(`raw = jsonb_set(coalesce(raw, '{}'::jsonb), '{_sell_unit_override}', $${paramIdx}::jsonb)`);
|
||||
params.push(JSON.stringify(sell_unit));
|
||||
paramIdx++;
|
||||
}
|
||||
|
||||
if (categories) {
|
||||
// Also update the categories column if it exists
|
||||
updates.push(`categories = $${paramIdx}::jsonb`);
|
||||
params.push(JSON.stringify(categories.map(name => ({ name }))));
|
||||
paramIdx++;
|
||||
|
||||
// Also store in raw for persistence
|
||||
updates.push(`raw = jsonb_set(coalesce(raw, '{}'::jsonb), '{_categories_override}', $${paramIdx}::jsonb)`);
|
||||
params.push(JSON.stringify(categories));
|
||||
paramIdx++;
|
||||
}
|
||||
|
||||
if (!updates.length) return null;
|
||||
|
||||
const sql = `
|
||||
update woo_products_snapshot
|
||||
set ${updates.join(", ")}
|
||||
where tenant_id = $1 and woo_id = $2
|
||||
returning woo_id as woo_product_id
|
||||
`;
|
||||
|
||||
const { rows } = await pool.query(sql, params);
|
||||
return rows[0] || null;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Aliases
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
@@ -188,7 +251,8 @@ export async function listRecommendations({ tenantId, q = "", limit = 200 }) {
|
||||
if (query) {
|
||||
const like = `%${query}%`;
|
||||
sql = `
|
||||
select id, rule_key, trigger, queries, boosts, ask_slots, active, priority, created_at, updated_at
|
||||
select id, rule_key, trigger, queries, boosts, ask_slots, active, priority,
|
||||
trigger_product_ids, recommended_product_ids, created_at, updated_at
|
||||
from product_reco_rules
|
||||
where tenant_id = $1 and rule_key ilike $2
|
||||
order by priority desc, rule_key asc
|
||||
@@ -197,7 +261,8 @@ export async function listRecommendations({ tenantId, q = "", limit = 200 }) {
|
||||
params = [tenantId, like, lim];
|
||||
} else {
|
||||
sql = `
|
||||
select id, rule_key, trigger, queries, boosts, ask_slots, active, priority, created_at, updated_at
|
||||
select id, rule_key, trigger, queries, boosts, ask_slots, active, priority,
|
||||
trigger_product_ids, recommended_product_ids, created_at, updated_at
|
||||
from product_reco_rules
|
||||
where tenant_id = $1
|
||||
order by priority desc, rule_key asc
|
||||
@@ -212,7 +277,8 @@ export async function listRecommendations({ tenantId, q = "", limit = 200 }) {
|
||||
|
||||
export async function getRecommendationById({ tenantId, id }) {
|
||||
const sql = `
|
||||
select id, rule_key, trigger, queries, boosts, ask_slots, active, priority, created_at, updated_at
|
||||
select id, rule_key, trigger, queries, boosts, ask_slots, active, priority,
|
||||
trigger_product_ids, recommended_product_ids, created_at, updated_at
|
||||
from product_reco_rules
|
||||
where tenant_id = $1 and id = $2
|
||||
limit 1
|
||||
@@ -230,11 +296,13 @@ export async function insertRecommendation({
|
||||
ask_slots = [],
|
||||
active = true,
|
||||
priority = 100,
|
||||
trigger_product_ids = [],
|
||||
recommended_product_ids = [],
|
||||
}) {
|
||||
const sql = `
|
||||
insert into product_reco_rules (tenant_id, rule_key, trigger, queries, boosts, ask_slots, active, priority)
|
||||
values ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
returning id, rule_key, trigger, queries, boosts, ask_slots, active, priority, created_at, updated_at
|
||||
insert into product_reco_rules (tenant_id, rule_key, trigger, queries, boosts, ask_slots, active, priority, trigger_product_ids, recommended_product_ids)
|
||||
values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
||||
returning id, rule_key, trigger, queries, boosts, ask_slots, active, priority, trigger_product_ids, recommended_product_ids, created_at, updated_at
|
||||
`;
|
||||
|
||||
const { rows } = await pool.query(sql, [
|
||||
@@ -246,6 +314,8 @@ export async function insertRecommendation({
|
||||
JSON.stringify(ask_slots || []),
|
||||
active !== false,
|
||||
priority || 100,
|
||||
trigger_product_ids || [],
|
||||
recommended_product_ids || [],
|
||||
]);
|
||||
|
||||
return rows[0];
|
||||
@@ -260,6 +330,8 @@ export async function updateRecommendation({
|
||||
ask_slots,
|
||||
active,
|
||||
priority,
|
||||
trigger_product_ids,
|
||||
recommended_product_ids,
|
||||
}) {
|
||||
const sql = `
|
||||
update product_reco_rules
|
||||
@@ -270,9 +342,11 @@ export async function updateRecommendation({
|
||||
ask_slots = $6,
|
||||
active = $7,
|
||||
priority = $8,
|
||||
trigger_product_ids = $9,
|
||||
recommended_product_ids = $10,
|
||||
updated_at = now()
|
||||
where tenant_id = $1 and id = $2
|
||||
returning id, rule_key, trigger, queries, boosts, ask_slots, active, priority, created_at, updated_at
|
||||
returning id, rule_key, trigger, queries, boosts, ask_slots, active, priority, trigger_product_ids, recommended_product_ids, created_at, updated_at
|
||||
`;
|
||||
|
||||
const { rows } = await pool.query(sql, [
|
||||
@@ -284,6 +358,8 @@ export async function updateRecommendation({
|
||||
JSON.stringify(ask_slots || []),
|
||||
active !== false,
|
||||
priority || 100,
|
||||
trigger_product_ids || [],
|
||||
recommended_product_ids || [],
|
||||
]);
|
||||
|
||||
return rows[0] || null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { searchSnapshotItems } from "../../shared/wooSnapshot.js";
|
||||
import { listProducts, getProductByWooId } from "../db/repo.js";
|
||||
import { listProducts, getProductByWooId, updateProductSellUnit, bulkUpdateProductSellUnit, updateProduct } from "../db/repo.js";
|
||||
|
||||
export async function handleSearchProducts({ tenantId, q = "", limit = "10", forceWoo = "0" }) {
|
||||
const { items, source } = await searchSnapshotItems({
|
||||
@@ -25,3 +25,18 @@ export async function handleSyncProducts({ tenantId }) {
|
||||
return { ok: true, message: "Sync triggered (use import script for full sync)" };
|
||||
}
|
||||
|
||||
export async function handleUpdateProductUnit({ tenantId, wooProductId, sell_unit }) {
|
||||
await updateProductSellUnit({ tenantId, wooProductId, sell_unit });
|
||||
return { ok: true, woo_product_id: wooProductId, sell_unit };
|
||||
}
|
||||
|
||||
export async function handleBulkUpdateProductUnit({ tenantId, wooProductIds, sell_unit }) {
|
||||
await bulkUpdateProductSellUnit({ tenantId, wooProductIds, sell_unit });
|
||||
return { ok: true, updated_count: wooProductIds.length, sell_unit };
|
||||
}
|
||||
|
||||
export async function handleUpdateProduct({ tenantId, wooProductId, sell_unit, categories }) {
|
||||
await updateProduct({ tenantId, wooProductId, sell_unit, categories });
|
||||
return { ok: true, woo_product_id: wooProductId, sell_unit, categories };
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,10 @@ export async function handleCreateRecommendation({
|
||||
ask_slots = [],
|
||||
active = true,
|
||||
priority = 100,
|
||||
trigger_product_ids = [],
|
||||
recommended_product_ids = [],
|
||||
}) {
|
||||
return insertRecommendation({ tenantId, rule_key, trigger, queries, boosts, ask_slots, active, priority });
|
||||
return insertRecommendation({ tenantId, rule_key, trigger, queries, boosts, ask_slots, active, priority, trigger_product_ids, recommended_product_ids });
|
||||
}
|
||||
|
||||
export async function handleUpdateRecommendation({
|
||||
@@ -37,8 +39,10 @@ export async function handleUpdateRecommendation({
|
||||
ask_slots,
|
||||
active,
|
||||
priority,
|
||||
trigger_product_ids,
|
||||
recommended_product_ids,
|
||||
}) {
|
||||
return updateRecommendation({ tenantId, id, trigger, queries, boosts, ask_slots, active, priority });
|
||||
return updateRecommendation({ tenantId, id, trigger, queries, boosts, ask_slots, active, priority, trigger_product_ids, recommended_product_ids });
|
||||
}
|
||||
|
||||
export async function handleDeleteRecommendation({ tenantId, id }) {
|
||||
|
||||
Reference in New Issue
Block a user