Змінено директорії
Додано скрипти CRON Поліпшено механізм запису стендів та їх редагування
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
const crypto = require('crypto');
|
||||
const db = require("../config/db");
|
||||
const Notification = require("../utils/notification.js");
|
||||
|
||||
class StandService {
|
||||
getStand(id) {
|
||||
@@ -27,7 +27,8 @@ class StandService {
|
||||
"week_days": JSON.parse(row.week_days),
|
||||
"processing_time": Number(row.processing_time),
|
||||
"status": row.status == 1 ? true : false,
|
||||
"updated_at": Number(row.updated_at)
|
||||
"updated_at": Number(row.updated_at),
|
||||
"created_at": Number(row.created_at)
|
||||
}
|
||||
|
||||
return res(data);
|
||||
@@ -62,7 +63,8 @@ class StandService {
|
||||
"week_days": JSON.parse(row.week_days),
|
||||
"processing_time": Number(row.processing_time),
|
||||
"status": row.status == 1 ? true : false,
|
||||
"updated_at": Number(row.updated_at)
|
||||
"updated_at": Number(row.updated_at),
|
||||
"created_at": Number(row.created_at)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -74,7 +76,7 @@ class StandService {
|
||||
|
||||
createStand(data) {
|
||||
return new Promise((res, rej) => {
|
||||
let sql = 'INSERT INTO stand_list(title, geo, hour_start, hour_end, quantity_sheep, week_days, processing_time, status, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
let sql = 'INSERT INTO stand_list(title, geo, hour_start, hour_end, quantity_sheep, week_days, processing_time, status, updated_at, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
|
||||
db.run(sql, [
|
||||
data.title,
|
||||
@@ -85,6 +87,7 @@ class StandService {
|
||||
JSON.stringify(data.week_days || [1]),
|
||||
Number(data.processing_time) || 1,
|
||||
1,
|
||||
Math.floor(Date.now()),
|
||||
Math.floor(Date.now())
|
||||
], function (err) {
|
||||
if (err) {
|
||||
@@ -106,6 +109,7 @@ class StandService {
|
||||
hour_start = COALESCE(?, hour_start),
|
||||
hour_end = COALESCE(?, hour_end),
|
||||
quantity_sheep = COALESCE(?, quantity_sheep),
|
||||
processing_time = COALESCE(?, processing_time),
|
||||
week_days = COALESCE(?, week_days),
|
||||
status = COALESCE(?, status),
|
||||
updated_at = ?
|
||||
@@ -118,6 +122,7 @@ class StandService {
|
||||
data.hour_start !== undefined ? Number(data.hour_start) : null,
|
||||
data.hour_end !== undefined ? Number(data.hour_end) : null,
|
||||
data.quantity_sheep !== undefined ? Number(data.quantity_sheep) : null,
|
||||
data.processing_time !== undefined ? Number(data.processing_time) : null,
|
||||
data.week_days !== undefined ? JSON.stringify(data.week_days) : null,
|
||||
data.status !== undefined ? (data.status ? 1 : 0) : null,
|
||||
Date.now(),
|
||||
@@ -153,17 +158,35 @@ class StandService {
|
||||
createSchedule(stand_id) {
|
||||
return new Promise((res, rej) => {
|
||||
let date_start;
|
||||
let getNextMonday = (ts) => {
|
||||
|
||||
const MS_DAY = 24 * 60 * 60 * 1000;
|
||||
|
||||
// Нормализует timestamp из БД: если в секундах — умножает на 1000
|
||||
const normalizeTs = (ts) => {
|
||||
if (!ts) return null;
|
||||
// если строка — привести к числу
|
||||
const n = Number(ts);
|
||||
if (Number.isNaN(n)) return null;
|
||||
// если кажется секундами (меньше ~1e12) — умножаем
|
||||
return n < 1e12 ? n * 1000 : n;
|
||||
};
|
||||
|
||||
// Возвращает timestamp (ms) следующего понедельника после ts
|
||||
const getNextMonday = (ts) => {
|
||||
let date = new Date(ts);
|
||||
// следующий день после max_date
|
||||
// нормализуем на начало дня
|
||||
date.setHours(0, 0, 0, 0);
|
||||
|
||||
// всегда переходить к следующему дню (чтобы гарантированно получить следующий понедельник,
|
||||
// даже если ts уже в понедельник)
|
||||
date.setDate(date.getDate() + 1);
|
||||
|
||||
// пока не понедельник – добавляем дни
|
||||
// пока не понедельник (в JS: 1 — понедельник)
|
||||
while (date.getDay() !== 1) {
|
||||
date.setDate(date.getDate() + 1);
|
||||
}
|
||||
return date.getTime();
|
||||
}
|
||||
};
|
||||
|
||||
// 1. Получаем стенд
|
||||
db.get(`SELECT * FROM stand_list WHERE id = ?`, [stand_id], (err, stand) => {
|
||||
@@ -176,8 +199,16 @@ class StandService {
|
||||
return res(false);
|
||||
}
|
||||
|
||||
stand.geo = JSON.parse(stand.geo);
|
||||
stand.week_days = JSON.parse(stand.week_days)
|
||||
try {
|
||||
stand.geo = JSON.parse(stand.geo);
|
||||
} catch (e) {
|
||||
stand.geo = stand.geo;
|
||||
}
|
||||
try {
|
||||
stand.week_days = JSON.parse(stand.week_days);
|
||||
} catch (e) {
|
||||
stand.week_days = Array.isArray(stand.week_days) ? stand.week_days : [];
|
||||
}
|
||||
|
||||
// 2. Берём последний date из расписания
|
||||
db.get(
|
||||
@@ -189,27 +220,35 @@ class StandService {
|
||||
return res(false);
|
||||
}
|
||||
|
||||
if (row && row.max_date) {
|
||||
date_start = getNextMonday(row.max_date); // заменить начальную дату
|
||||
const normalized = normalizeTs(row && row.max_date ? row.max_date : null);
|
||||
if (normalized) {
|
||||
date_start = getNextMonday(normalized);
|
||||
} else {
|
||||
date_start = getNextMonday(Date.now()); // заменить начальную дату
|
||||
date_start = getNextMonday(Date.now());
|
||||
}
|
||||
|
||||
// 3. Генерация новых записей
|
||||
const stand_length = (stand.hour_end - stand.hour_start) / stand.processing_time;
|
||||
const timestamp = Math.floor(Date.now());
|
||||
// вычисляем количество слотов (целое)
|
||||
const stand_length = Math.max(0, Math.floor((stand.hour_end - stand.hour_start) / stand.processing_time));
|
||||
const timestamp = Date.now();
|
||||
const list = [];
|
||||
|
||||
for (const dayOffset of stand.week_days) {
|
||||
const stand_date = date_start + (dayOffset * 24 * 60 * 60 * 1000);
|
||||
// Ожидается, что stand.week_days — массив чисел 0..6, где 0 -> Понедельник, 6 -> Воскресенье
|
||||
for (const dayOffsetRaw of stand.week_days) {
|
||||
const dayOffset = Number(dayOffsetRaw);
|
||||
if (!Number.isFinite(dayOffset) || dayOffset < 0 || dayOffset > 6) continue;
|
||||
|
||||
// dayOffset: 0 => Monday, 6 => Sunday
|
||||
const stand_date = date_start + (dayOffset * MS_DAY);
|
||||
|
||||
for (let i = 0; i < stand_length; i++) {
|
||||
for (let q = 0; q < stand.quantity_sheep; q++) {
|
||||
for (let q = 0; q < (Number(stand.quantity_sheep) || 0); q++) {
|
||||
list.push([
|
||||
stand.hour_start + (stand.processing_time * i),
|
||||
q,
|
||||
stand_date,
|
||||
stand.id,
|
||||
timestamp,
|
||||
timestamp
|
||||
]);
|
||||
}
|
||||
@@ -221,10 +260,10 @@ class StandService {
|
||||
}
|
||||
|
||||
// 4. Массовая вставка
|
||||
const placeholders = list.map(() => "(?, ?, ?, ?, ?)").join(",");
|
||||
const placeholders = list.map(() => "(?, ?, ?, ?, ?, ?)").join(",");
|
||||
const values = list.flat();
|
||||
const insertSQL = `
|
||||
INSERT INTO stand_schedule(hour, number_sheep, date, stand_id, updated_at)
|
||||
INSERT INTO stand_schedule(hour, number_sheep, date, stand_id, updated_at, created_at)
|
||||
VALUES ${placeholders}
|
||||
`;
|
||||
|
||||
@@ -233,7 +272,13 @@ class StandService {
|
||||
console.error(err.message);
|
||||
return res(false);
|
||||
}
|
||||
res({ status: "ok", inserted: list.length});
|
||||
// Notification.sendStand({
|
||||
// title: "Додан новий день служіння",
|
||||
// body: `Стенд «${stand.title}» поповнився, встигніть записатися.`,
|
||||
// page: `/stand/card/${stand.id}`
|
||||
// });
|
||||
|
||||
res({ status: "ok", inserted: list.length });
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -255,6 +300,8 @@ class StandService {
|
||||
s.id = ss.sheep_id
|
||||
WHERE
|
||||
ss.stand_id = ?
|
||||
AND
|
||||
date(ss.date / 1000, 'unixepoch') >= date('now')
|
||||
ORDER BY
|
||||
ss.id;
|
||||
`;
|
||||
@@ -273,7 +320,8 @@ class StandService {
|
||||
"sheep_id": Number(row.sheep_id),
|
||||
"sheep_name": row.sheep_name,
|
||||
"number_sheep": Number(row.number_sheep),
|
||||
"updated_at": Number(row.updated_at)
|
||||
"updated_at": Number(row.updated_at),
|
||||
"created_at": Number(row.created_at)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user