Compare commits
1 Commits
fix/rankin
...
fix/citado
| Author | SHA1 | Date | |
|---|---|---|---|
| 97ef005913 |
17
server.js
17
server.js
@@ -1058,8 +1058,6 @@ ALTER TABLE protection_subscriptions ALTER COLUMN status SET DEFAULT 'pendiente_
|
|||||||
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='scraped_services' AND column_name='automation_status') THEN ALTER TABLE scraped_services ADD COLUMN automation_status TEXT DEFAULT 'manual'; END IF;
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='scraped_services' AND column_name='automation_status') THEN ALTER TABLE scraped_services ADD COLUMN automation_status TEXT DEFAULT 'manual'; END IF;
|
||||||
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='scraped_services' AND column_name='closed_at') THEN ALTER TABLE scraped_services ADD COLUMN closed_at TIMESTAMP; END IF;
|
|
||||||
|
|
||||||
-- AÑADIDO: Token mágico para el Portal del Cliente
|
-- AÑADIDO: Token mágico para el Portal del Cliente
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='clients' AND column_name='portal_token') THEN
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='clients' AND column_name='portal_token') THEN
|
||||||
ALTER TABLE clients ADD COLUMN portal_token TEXT UNIQUE;
|
ALTER TABLE clients ADD COLUMN portal_token TEXT UNIQUE;
|
||||||
@@ -3850,8 +3848,8 @@ app.put('/providers/scraped/:id', authMiddleware, async (req, res) => {
|
|||||||
const mainStatus = isFinal ? 'archived' : 'imported';
|
const mainStatus = isFinal ? 'archived' : 'imported';
|
||||||
|
|
||||||
await pool.query(
|
await pool.query(
|
||||||
`UPDATE scraped_services SET raw_data = $1, assigned_to = $2, is_urgent = $3, status = $6, closed_at = CASE WHEN $7 THEN COALESCE(closed_at, NOW()) ELSE NULL END WHERE id = $4 AND owner_id = $5`,
|
`UPDATE scraped_services SET raw_data = $1, assigned_to = $2, is_urgent = $3, status = $6 WHERE id = $4 AND owner_id = $5`,
|
||||||
[JSON.stringify(updatedRawData), finalAssignedTo, isUrgentFinal, id, req.user.accountId, mainStatus, isFinal]
|
[JSON.stringify(updatedRawData), finalAssignedTo, isUrgentFinal, id, req.user.accountId, mainStatus]
|
||||||
);
|
);
|
||||||
|
|
||||||
// BANDERAS INTELIGENTES
|
// BANDERAS INTELIGENTES
|
||||||
@@ -4780,15 +4778,12 @@ function calculateScore(services) {
|
|||||||
let scoreCierre = 0;
|
let scoreCierre = 0;
|
||||||
if (closedLast30Days.length > 0) {
|
if (closedLast30Days.length > 0) {
|
||||||
let totalDaysToClose = 0;
|
let totalDaysToClose = 0;
|
||||||
let closedWithTimestamp = 0;
|
|
||||||
closedLast30Days.forEach(s => {
|
closedLast30Days.forEach(s => {
|
||||||
if (!s.closed_at) return; // 🟢 FIX: sin fecha real de cierre (servicio cerrado antes de esta corrección), no lo contamos
|
|
||||||
const created = new Date(s.created_at);
|
const created = new Date(s.created_at);
|
||||||
const closed = new Date(s.closed_at); // 🟢 FIX: usamos la fecha real de cierre, no "ahora"
|
const closed = new Date(); // Estimamos el cierre en el ciclo actual
|
||||||
totalDaysToClose += Math.max(1, (closed - created) / (1000 * 60 * 60 * 24));
|
totalDaysToClose += Math.max(1, (closed - created) / (1000 * 60 * 60 * 24));
|
||||||
closedWithTimestamp++;
|
|
||||||
});
|
});
|
||||||
const avgCloseDays = closedWithTimestamp > 0 ? (totalDaysToClose / closedWithTimestamp) : 999;
|
const avgCloseDays = totalDaysToClose / closedLast30Days.length;
|
||||||
|
|
||||||
if (avgCloseDays <= 2) scoreCierre = 30;
|
if (avgCloseDays <= 2) scoreCierre = 30;
|
||||||
else if (avgCloseDays >= 14) scoreCierre = 0;
|
else if (avgCloseDays >= 14) scoreCierre = 0;
|
||||||
@@ -4868,7 +4863,7 @@ app.get("/ranking", authMiddleware, async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
// CORRECCIÓN: Hemos quitado "updated_at" de aquí para evitar que la base de datos se queje
|
// CORRECCIÓN: Hemos quitado "updated_at" de aquí para evitar que la base de datos se queje
|
||||||
const q = await pool.query(`
|
const q = await pool.query(`
|
||||||
SELECT id, created_at, closed_at, raw_data,
|
SELECT id, created_at, raw_data,
|
||||||
(SELECT is_final FROM service_statuses WHERE id::text = raw_data->>'status_operativo') as is_final
|
(SELECT is_final FROM service_statuses WHERE id::text = raw_data->>'status_operativo') as is_final
|
||||||
FROM scraped_services
|
FROM scraped_services
|
||||||
WHERE assigned_to = $1
|
WHERE assigned_to = $1
|
||||||
@@ -5256,7 +5251,7 @@ app.post("/budgets/:id/convert", authMiddleware, async (req, res) => {
|
|||||||
triggerWhatsAppEvent(req.user.accountId, newServiceId, 'wa_evt_date').catch(console.error);
|
triggerWhatsAppEvent(req.user.accountId, newServiceId, 'wa_evt_date').catch(console.error);
|
||||||
|
|
||||||
if (assigned_to) {
|
if (assigned_to) {
|
||||||
const statusQ = await pool.query("SELECT id FROM service_statuses WHERE owner_id=$1 AND name ILIKE '%asignado%' LIMIT 1", [req.user.accountId]);
|
const statusQ = await pool.query("SELECT id FROM service_statuses WHERE owner_id=$1 AND name ILIKE '%citado%' LIMIT 1", [req.user.accountId]);
|
||||||
if (statusQ.rowCount > 0) {
|
if (statusQ.rowCount > 0) {
|
||||||
rawData.status_operativo = statusQ.rows[0].id;
|
rawData.status_operativo = statusQ.rows[0].id;
|
||||||
await pool.query("UPDATE scraped_services SET raw_data = $1 WHERE id = $2", [JSON.stringify(rawData), newServiceId]);
|
await pool.query("UPDATE scraped_services SET raw_data = $1 WHERE id = $2", [JSON.stringify(rawData), newServiceId]);
|
||||||
|
|||||||
Reference in New Issue
Block a user