20260204
This commit is contained in:
@@ -2,8 +2,6 @@ import {
|
||||
handleListOrders,
|
||||
handleGetProductsWithStock,
|
||||
handleCreateTestOrder,
|
||||
handleCreatePaymentLink,
|
||||
handleSimulateMpWebhook,
|
||||
} from "../handlers/testing.js";
|
||||
import { handleGetOrderStats } from "../handlers/stats.js";
|
||||
|
||||
@@ -59,47 +57,3 @@ export const makeCreateTestOrder = (tenantIdOrFn) => async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const makeCreatePaymentLink = (tenantIdOrFn) => async (req, res) => {
|
||||
try {
|
||||
const tenantId = typeof tenantIdOrFn === "function" ? tenantIdOrFn() : tenantIdOrFn;
|
||||
const { woo_order_id, amount } = req.body || {};
|
||||
|
||||
if (!woo_order_id) {
|
||||
return res.status(400).json({ ok: false, error: "woo_order_id_required" });
|
||||
}
|
||||
if (!amount || Number(amount) <= 0) {
|
||||
return res.status(400).json({ ok: false, error: "amount_required" });
|
||||
}
|
||||
|
||||
const result = await handleCreatePaymentLink({
|
||||
tenantId,
|
||||
wooOrderId: woo_order_id,
|
||||
amount: Number(amount)
|
||||
});
|
||||
res.json(result);
|
||||
} catch (err) {
|
||||
console.error("[testing] createPaymentLink error:", err);
|
||||
res.status(500).json({ ok: false, error: err.message || "internal_error" });
|
||||
}
|
||||
};
|
||||
|
||||
export const makeSimulateMpWebhook = (tenantIdOrFn) => async (req, res) => {
|
||||
try {
|
||||
const tenantId = typeof tenantIdOrFn === "function" ? tenantIdOrFn() : tenantIdOrFn;
|
||||
const { woo_order_id, amount } = req.body || {};
|
||||
|
||||
if (!woo_order_id) {
|
||||
return res.status(400).json({ ok: false, error: "woo_order_id_required" });
|
||||
}
|
||||
|
||||
const result = await handleSimulateMpWebhook({
|
||||
tenantId,
|
||||
wooOrderId: woo_order_id,
|
||||
amount: Number(amount) || 0
|
||||
});
|
||||
res.json(result);
|
||||
} catch (err) {
|
||||
console.error("[testing] simulateMpWebhook error:", err);
|
||||
res.status(500).json({ ok: false, error: err.message || "internal_error" });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ export async function getSettings({ tenantId }) {
|
||||
pickup_hours_start::text as pickup_hours_start,
|
||||
pickup_hours_end::text as pickup_hours_end,
|
||||
schedule,
|
||||
delivery_zones,
|
||||
created_at, updated_at
|
||||
FROM tenant_settings
|
||||
WHERE tenant_id = $1
|
||||
@@ -48,6 +49,7 @@ export async function upsertSettings({ tenantId, settings }) {
|
||||
pickup_hours_start,
|
||||
pickup_hours_end,
|
||||
schedule,
|
||||
delivery_zones,
|
||||
} = settings;
|
||||
|
||||
const sql = `
|
||||
@@ -55,9 +57,9 @@ export async function upsertSettings({ tenantId, settings }) {
|
||||
tenant_id, store_name, bot_name, store_address, store_phone,
|
||||
delivery_enabled, delivery_days, delivery_hours_start, delivery_hours_end, delivery_min_order,
|
||||
pickup_enabled, pickup_days, pickup_hours_start, pickup_hours_end,
|
||||
schedule
|
||||
schedule, delivery_zones
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
|
||||
ON CONFLICT (tenant_id) DO UPDATE SET
|
||||
store_name = COALESCE(EXCLUDED.store_name, tenant_settings.store_name),
|
||||
bot_name = COALESCE(EXCLUDED.bot_name, tenant_settings.bot_name),
|
||||
@@ -73,6 +75,7 @@ export async function upsertSettings({ tenantId, settings }) {
|
||||
pickup_hours_start = COALESCE(EXCLUDED.pickup_hours_start, tenant_settings.pickup_hours_start),
|
||||
pickup_hours_end = COALESCE(EXCLUDED.pickup_hours_end, tenant_settings.pickup_hours_end),
|
||||
schedule = COALESCE(EXCLUDED.schedule, tenant_settings.schedule),
|
||||
delivery_zones = COALESCE(EXCLUDED.delivery_zones, tenant_settings.delivery_zones),
|
||||
updated_at = NOW()
|
||||
RETURNING
|
||||
id, tenant_id,
|
||||
@@ -85,6 +88,7 @@ export async function upsertSettings({ tenantId, settings }) {
|
||||
pickup_hours_start::text as pickup_hours_start,
|
||||
pickup_hours_end::text as pickup_hours_end,
|
||||
schedule,
|
||||
delivery_zones,
|
||||
created_at, updated_at
|
||||
`;
|
||||
|
||||
@@ -104,6 +108,7 @@ export async function upsertSettings({ tenantId, settings }) {
|
||||
pickup_hours_start || null,
|
||||
pickup_hours_end || null,
|
||||
schedule ? JSON.stringify(schedule) : null,
|
||||
delivery_zones ? JSON.stringify(delivery_zones) : null,
|
||||
];
|
||||
|
||||
const { rows } = await pool.query(sql, params);
|
||||
|
||||
@@ -42,6 +42,7 @@ export async function handleGetSettings({ tenantId }) {
|
||||
pickup_hours_start: "08:00",
|
||||
pickup_hours_end: "20:00",
|
||||
schedule: createDefaultSchedule(),
|
||||
delivery_zones: {},
|
||||
is_default: true,
|
||||
};
|
||||
}
|
||||
@@ -60,6 +61,7 @@ export async function handleGetSettings({ tenantId }) {
|
||||
pickup_hours_start: settings.pickup_hours_start?.slice(0, 5) || "08:00",
|
||||
pickup_hours_end: settings.pickup_hours_end?.slice(0, 5) || "20:00",
|
||||
schedule,
|
||||
delivery_zones: settings.delivery_zones || {},
|
||||
is_default: false,
|
||||
};
|
||||
}
|
||||
@@ -103,7 +105,8 @@ function buildScheduleFromLegacy(settings) {
|
||||
function validateSchedule(schedule) {
|
||||
if (!schedule || typeof schedule !== "object") return;
|
||||
|
||||
const timeRegex = /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/;
|
||||
// Acepta HH:MM o HH:MM:SS (la BD puede devolver con segundos)
|
||||
const timeRegex = /^([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/;
|
||||
|
||||
for (const type of ["delivery", "pickup"]) {
|
||||
const typeSchedule = schedule[type];
|
||||
@@ -240,6 +243,7 @@ export async function handleSaveSettings({ tenantId, settings }) {
|
||||
delivery_hours_end: result.delivery_hours_end?.slice(0, 5),
|
||||
pickup_hours_start: result.pickup_hours_start?.slice(0, 5),
|
||||
pickup_hours_end: result.pickup_hours_end?.slice(0, 5),
|
||||
delivery_zones: result.delivery_zones || {},
|
||||
},
|
||||
message: "Configuración guardada correctamente",
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { createOrder, syncOrdersIncremental } from "../../4-woo-orders/wooOrders.js";
|
||||
import { createPreference, reconcilePayment } from "../../6-mercadopago/mercadoPago.js";
|
||||
import { listProducts } from "../db/repo.js";
|
||||
import * as ordersRepo from "../../4-woo-orders/ordersRepo.js";
|
||||
|
||||
@@ -73,74 +72,3 @@ export async function handleCreateTestOrder({ tenantId, basket, address, wa_chat
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un link de pago de MercadoPago
|
||||
*/
|
||||
export async function handleCreatePaymentLink({ tenantId, wooOrderId, amount }) {
|
||||
if (!wooOrderId) {
|
||||
throw new Error("missing_woo_order_id");
|
||||
}
|
||||
if (!amount || Number(amount) <= 0) {
|
||||
throw new Error("invalid_amount");
|
||||
}
|
||||
|
||||
const pref = await createPreference({
|
||||
tenantId,
|
||||
wooOrderId,
|
||||
amount: Number(amount),
|
||||
});
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
preference_id: pref?.preference_id || null,
|
||||
init_point: pref?.init_point || null,
|
||||
sandbox_init_point: pref?.sandbox_init_point || null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Simula un webhook de MercadoPago con pago exitoso
|
||||
* No pasa por el endpoint real (requiere firma HMAC)
|
||||
* Crea un payment mock y llama a reconcilePayment directamente
|
||||
*/
|
||||
export async function handleSimulateMpWebhook({ tenantId, wooOrderId, amount }) {
|
||||
if (!wooOrderId) {
|
||||
throw new Error("missing_woo_order_id");
|
||||
}
|
||||
|
||||
// Crear payment mock con status approved
|
||||
const mockPaymentId = `test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
||||
const mockPayment = {
|
||||
id: mockPaymentId,
|
||||
status: "approved",
|
||||
status_detail: "accredited",
|
||||
external_reference: `${tenantId}|${wooOrderId}`,
|
||||
transaction_amount: Number(amount) || 0,
|
||||
currency_id: "ARS",
|
||||
date_approved: new Date().toISOString(),
|
||||
date_created: new Date().toISOString(),
|
||||
payment_method_id: "test",
|
||||
payment_type_id: "credit_card",
|
||||
payer: {
|
||||
email: "test@test.com",
|
||||
},
|
||||
order: {
|
||||
id: `pref-test-${wooOrderId}`,
|
||||
},
|
||||
};
|
||||
|
||||
// Reconciliar el pago (actualiza mp_payments y cambia status de orden a processing)
|
||||
const result = await reconcilePayment({
|
||||
tenantId,
|
||||
payment: mockPayment,
|
||||
});
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
payment_id: mockPaymentId,
|
||||
woo_order_id: result?.woo_order_id || wooOrderId,
|
||||
status: "approved",
|
||||
order_status: "processing",
|
||||
reconciled: result?.payment || null,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user