pedidos
This commit is contained in:
92
src/modules/0-ui/controllers/testing.js
Normal file
92
src/modules/0-ui/controllers/testing.js
Normal file
@@ -0,0 +1,92 @@
|
||||
import {
|
||||
handleListRecentOrders,
|
||||
handleGetProductsWithStock,
|
||||
handleCreateTestOrder,
|
||||
handleCreatePaymentLink,
|
||||
handleSimulateMpWebhook,
|
||||
} from "../handlers/testing.js";
|
||||
|
||||
export const makeListRecentOrders = (tenantIdOrFn) => async (req, res) => {
|
||||
try {
|
||||
const tenantId = typeof tenantIdOrFn === "function" ? tenantIdOrFn() : tenantIdOrFn;
|
||||
const limit = parseInt(req.query.limit) || 20;
|
||||
const result = await handleListRecentOrders({ tenantId, limit });
|
||||
res.json(result);
|
||||
} catch (err) {
|
||||
console.error("[testing] listRecentOrders error:", err);
|
||||
res.status(500).json({ ok: false, error: err.message || "internal_error" });
|
||||
}
|
||||
};
|
||||
|
||||
export const makeGetProductsWithStock = (tenantIdOrFn) => async (req, res) => {
|
||||
try {
|
||||
const tenantId = typeof tenantIdOrFn === "function" ? tenantIdOrFn() : tenantIdOrFn;
|
||||
const result = await handleGetProductsWithStock({ tenantId });
|
||||
res.json(result);
|
||||
} catch (err) {
|
||||
console.error("[testing] getProductsWithStock error:", err);
|
||||
res.status(500).json({ ok: false, error: err.message || "internal_error" });
|
||||
}
|
||||
};
|
||||
|
||||
export const makeCreateTestOrder = (tenantIdOrFn) => async (req, res) => {
|
||||
try {
|
||||
const tenantId = typeof tenantIdOrFn === "function" ? tenantIdOrFn() : tenantIdOrFn;
|
||||
const { basket, address, wa_chat_id } = req.body || {};
|
||||
|
||||
if (!basket?.items?.length) {
|
||||
return res.status(400).json({ ok: false, error: "basket_required" });
|
||||
}
|
||||
|
||||
const result = await handleCreateTestOrder({ tenantId, basket, address, wa_chat_id });
|
||||
res.json(result);
|
||||
} catch (err) {
|
||||
console.error("[testing] createTestOrder error:", err);
|
||||
res.status(500).json({ ok: false, error: err.message || "internal_error" });
|
||||
}
|
||||
};
|
||||
|
||||
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" });
|
||||
}
|
||||
};
|
||||
131
src/modules/0-ui/handlers/testing.js
Normal file
131
src/modules/0-ui/handlers/testing.js
Normal file
@@ -0,0 +1,131 @@
|
||||
import { createOrder, listRecentOrders } from "../../4-woo-orders/wooOrders.js";
|
||||
import { createPreference, reconcilePayment } from "../../6-mercadopago/mercadoPago.js";
|
||||
import { listProducts } from "../db/repo.js";
|
||||
|
||||
/**
|
||||
* Lista pedidos recientes de WooCommerce
|
||||
*/
|
||||
export async function handleListRecentOrders({ tenantId, limit = 20 }) {
|
||||
const orders = await listRecentOrders({ tenantId, limit });
|
||||
return { items: orders };
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene productos con stock para testing
|
||||
*/
|
||||
export async function handleGetProductsWithStock({ tenantId }) {
|
||||
const allProducts = await listProducts({ tenantId, limit: 500 });
|
||||
const withStock = allProducts.filter(p =>
|
||||
p.stock_status === "instock" &&
|
||||
p.price &&
|
||||
Number(p.price) > 0
|
||||
);
|
||||
return { items: withStock };
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea una orden de prueba en WooCommerce
|
||||
*/
|
||||
export async function handleCreateTestOrder({ tenantId, basket, address, wa_chat_id }) {
|
||||
if (!basket?.items?.length) {
|
||||
throw new Error("basket_empty");
|
||||
}
|
||||
|
||||
const order = await createOrder({
|
||||
tenantId,
|
||||
wooCustomerId: null, // Sin customer de Woo para testing
|
||||
basket,
|
||||
address,
|
||||
run_id: `test-${Date.now()}`,
|
||||
});
|
||||
|
||||
// Calcular total desde line_items
|
||||
let total = 0;
|
||||
if (order?.raw?.line_items) {
|
||||
for (const item of order.raw.line_items) {
|
||||
total += Number(item.total) || 0;
|
||||
}
|
||||
} else if (order?.raw?.total) {
|
||||
total = Number(order.raw.total) || 0;
|
||||
}
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
woo_order_id: order?.id || null,
|
||||
total,
|
||||
line_items: order?.line_items || [],
|
||||
raw: order?.raw || null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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