This commit is contained in:
2025-09-09 00:10:53 +03:00
parent 38f2a05107
commit 204fc092d7
239 changed files with 22447 additions and 9536 deletions

View File

@@ -1,34 +1,27 @@
const db = require("../config/db");
class AuthService {
findUserByID(id, sheepRole) {
findUserByID(id, mode) {
return new Promise((res, rej) => {
let sql = `
SELECT
sheeps.*,
groups.group_number AS group_id,
administrators.id AS administrators_id,
administrators.uuid AS administrators_uuid,
moderators.id AS moderators_id,
moderators.uuid AS moderators_uuid,
moderators.can_add_sheeps,
moderators.can_add_territory,
moderators.can_manager_territory,
moderators.can_add_stand,
moderators.can_manager_stand,
moderators.can_add_schedule
FROM
sheeps
LEFT JOIN
groups ON groups.group_number = sheeps.group_id
LEFT JOIN
administrators ON administrators.sheep_id = sheeps.id
LEFT JOIN
moderators ON moderators.sheep_id = sheeps.id
WHERE
sheeps.id = ?
LIMIT 1;
`
SELECT
sheeps.*,
possibilities.can_add_sheeps AS can_add_sheeps,
possibilities.can_view_sheeps AS can_view_sheeps,
possibilities.can_add_territory AS can_add_territory,
possibilities.can_view_territory AS can_view_territory,
possibilities.can_manager_territory AS can_manager_territory,
possibilities.can_add_stand AS can_add_stand,
possibilities.can_view_stand AS can_view_stand,
possibilities.can_manager_stand AS can_manager_stand,
possibilities.can_add_schedule AS can_add_schedule,
possibilities.can_view_schedule AS can_view_schedule
FROM
sheeps
LEFT JOIN
possibilities ON possibilities.sheep_id = sheeps.id
WHERE
sheeps.id = ?`;
db.get(sql, [id], (err, sheep) => {
if (err) {
console.error(err.message);
@@ -38,40 +31,36 @@ class AuthService {
return res(false);
} else {
let data = {
"id": Number(sheep.id),
"group_id": Number(sheep.group_id),
"name": sheep.name,
"icon": sheep.icon,
"uuid": sheep.uuid,
"appointment": sheep.appointment,
"can_view_stand": sheep.can_view_stand == 0 ? false : true,
"can_view_schedule": sheep.can_view_schedule == 0 ? false : true,
"can_view_territory": sheep.can_view_territory == 0 ? false : true,
"administrator": {
"id": sheep.administrators_id ? sheep.administrators_id : false,
"uuid": null
},
"moderator": {
"id": sheep.moderators_id ? sheep.moderators_id : false,
"uuid": null,
"can_add_sheeps": sheep.can_add_sheeps == 1 ? true : false,
"can_add_territory": sheep.can_add_territory == 1 ? true : false,
"can_manager_territory": sheep.can_manager_territory == 1 ? true : false,
"can_add_stand": sheep.can_add_stand == 1 ? true : false,
"can_manager_stand": sheep.can_manager_stand == 1 ? true : false,
"can_add_schedule": sheep.can_add_schedule == 1 ? true : false
id: sheep.id,
group_id: sheep.group_id,
name: sheep.name,
icon: sheep.icon,
uuid: sheep.uuid,
uuid_manager: mode && mode == 2 ? sheep.uuid_manager : null,
appointment: sheep.appointment,
mode: mode ? Number(sheep.mode) : 0,
sheepRole: sheep.mode_title,
possibilities: {
can_add_sheeps: false,
can_view_sheeps: false,
can_add_territory: false,
can_manager_territory: false,
can_add_stand: false,
can_manager_stand: false,
can_add_schedule: false,
can_view_schedule: sheep.can_view_schedule == 1 ? true : false,
can_view_stand: sheep.can_view_stand == 1 ? true : false,
can_view_territory: sheep.can_view_territory == 1 ? true : false
}
}
if (sheepRole == "administrator") {
if (sheep.administrators_id) {
data.administrator.uuid = sheep.administrators_uuid;
}
}
if (sheepRole == "moderator") {
if (sheep.moderators_id) {
data.moderator.uuid = sheep.moderators_uuid;
}
if (mode && (mode == 1 || mode == 2)) {
data.possibilities.can_add_sheeps = sheep.can_add_sheeps == 1 ? true : false;
data.possibilities.can_view_sheeps = sheep.can_view_sheeps == 1 ? true : false;
data.possibilities.can_add_territory = sheep.can_add_territory == 1 ? true : false;
data.possibilities.can_manager_territory = sheep.can_manager_territory == 1 ? true : false;
data.possibilities.can_add_stand = sheep.can_add_stand == 1 ? true : false;
data.possibilities.can_manager_stand = sheep.can_manager_stand == 1 ? true : false;
data.possibilities.can_add_schedule = sheep.can_add_schedule == 1 ? true : false;
}
return res(data);

View File

@@ -0,0 +1,102 @@
const db = require("../config/db");
class BuildingsService {
getList(homestead_id) {
return new Promise((res, rej) => {
let sql = `
SELECT
*
FROM
buildings
WHERE
homestead_id = '${homestead_id}'
ORDER BY
id
`;
db.all(sql, (err, rows) => {
if (err) {
console.error(err.message);
return res(false);
} else {
let data = rows.map((row) => {
return {
"id": Number(row.id),
"homestead_id": Number(row.homestead_id),
"sheep_id": Number(row.sheep_id),
"geo": JSON.parse(row.geo),
"title": row.title,
"status": Number(row.status),
"description": row.description,
"updated_at": Number(row.updated_at)
}
})
return res(data);
}
});
});
}
createBuildings(homestead_id, data) {
return new Promise((res, rej) => {
let sql = 'INSERT INTO buildings(homestead_id, title, geo) VALUES (?, ?, ?)';
db.run(sql, [
homestead_id,
data.title,
JSON.stringify(data.geo)
], function(err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "status": "ok", "id": this.lastID });
}
});
});
}
updateBuildings(data) {
return new Promise((res, rej) => {
let sql = 'UPDATE buildings SET title = ?, status = ?, description = ?, updated_at = ?, geo = ? WHERE id = ?';
db.run(sql, [
data.title,
data.status,
data.description,
Math.floor(new Date(Date.now()).getTime()),
JSON.stringify(data.geo),
data.id
], function(err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "status": "ok" });
}
});
});
}
deleteBuildings(building_id) {
return new Promise((res, rej) => {
db.run('DELETE FROM buildings WHERE id = ?', [building_id], function(err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "status": "ok"});
}
});
});
}
}
module.exports = new BuildingsService();

View File

@@ -101,17 +101,114 @@ class ConstructorService {
// });
// });
// }
// createPack(data) {
// return new Promise((res, rej) => {
// if (data.type == "house") {
// const sql = `
// INSERT INTO house (
// title, number, points, points_number, geo, osm_id, settlement, created_at
// ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`;
// db.run(sql, [
// data.title,
// data.number,
// JSON.stringify(data.points),
// JSON.stringify(data.points_number),
// JSON.stringify(data.geo),
// JSON.stringify(data.osm_id),
// data.settlement,
// Math.floor(Date.now())
// ], function (err) {
// if (err) {
// console.error(err.message);
// return res(false);
// }
// if (this.changes === 0) {
// return res(false);
// }
// const houseId = this.lastID;
// saveCards({ center: data.geo, wayId: data.osm_id, zoom: data.zoom ?? 18, type: "house", number: houseId, address: `${data.title} ${data.number}` });
// const entranceStmt = db.prepare(`
// INSERT INTO entrance (
// house_id, entrance_number, title, points, points_number, created_at
// ) VALUES (?, ?, ?, ?, ?, ?)`);
// const apartmentStmt = db.prepare(`
// INSERT INTO apartments (
// entrance_id, apartment_number, title, floors_number
// ) VALUES (?, ?, ?, ?)`);
// const entranceIdMap = {}; // Для сопоставления editor_id → entrance_id
// let pendingEntrances = data.entrance.length;
// data.entrance.forEach((e) => {
// entranceStmt.run(
// houseId,
// Number(e.entrance_number),
// e.title,
// JSON.stringify(e.points),
// JSON.stringify(e.points_number),
// Math.floor(Date.now()),
// function (err) {
// if (err) {
// console.error(err.message);
// return;
// }
// const entranceId = this.lastID;
// entranceIdMap[e.editor_id] = entranceId;
// if (--pendingEntrances === 0) {
// insertApartments();
// }
// }
// );
// });
// function insertApartments() {
// for (const [editor_id, apartments] of Object.entries(data.apartments)) {
// const entranceId = entranceIdMap[editor_id];
// if (!entranceId) continue;
// apartments.forEach(apartment => {
// apartmentStmt.run(
// entranceId,
// Number(apartment.apartment_number),
// apartment.title,
// apartment.floors_number
// );
// });
// }
// entranceStmt.finalize();
// apartmentStmt.finalize();
// res({ "status": "ok", "id": houseId });
// }
// });
// } else if (data.type == "homestead") {
// return res(false);
// } else {
// return res(false);
// }
// });
// }
createPack(data) {
return new Promise((res, rej) => {
if (data.type == "house") {
if (data.type === "house") {
const sql = `
INSERT INTO house (
group_id, title, number, points, points_number, geo, osm_id, settlement, created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`;
title, number, points, points_number, geo, osm_id, settlement, created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`;
db.run(sql, [
Number(data.group_id),
data.title,
data.number,
JSON.stringify(data.points),
@@ -131,103 +228,132 @@ class ConstructorService {
const houseId = this.lastID;
saveCards({ center: data.geo, wayId: data.osm_id, zoom: data.zoom ?? 18, type: "house", number: houseId, address: `${data.title} ${data.number}` });
// saveCards({ center: data.geo, wayId: data.osm_id, zoom: data.zoom ?? 18, type: "house", number: houseId, address: `${data.title} ${data.number}` });
const entranceStmt = db.prepare(`
INSERT INTO entrance (
house_id, entrance_number, title, points, points_number, created_at
) VALUES (?, ?, ?, ?, ?, ?)`);
house_id, entrance_number, title, created_at
) VALUES (?, ?, ?, ?)`);
const apartmentStmt = db.prepare(`
INSERT INTO apartments (
entrance_id, apartment_number, title, floors_number
) VALUES (?, ?, ?, ?)`);
const entranceIdMap = {}; // Для сопоставления editor_id → entrance_id
let pendingEntrances = data.entrances.length;
const entranceIdMap = {};
let pendingEntrances = data.entrance.length;
if (pendingEntrances === 0) return finalize();
data.entrance.forEach((e) => {
// Вставляем подъезды
data.entrances.forEach(entrance => {
entranceStmt.run(
houseId,
Number(e.entrance_number),
e.title,
JSON.stringify(e.points),
JSON.stringify(e.points_number),
Number(entrance.entrance_number),
entrance.title,
Math.floor(Date.now()),
function (err) {
if (err) {
console.error(err.message);
return res(false);
}
const entranceID = this.lastID;
entranceIdMap[entrance.entrance_number] = entranceID;
// Вставляем квартиры данного подъезда
let pendingApartments = entrance.apartments.length;
if (pendingApartments === 0) {
if (--pendingEntrances === 0) finalize();
return;
}
const entranceId = this.lastID;
entranceIdMap[e.editor_id] = entranceId;
if (--pendingEntrances === 0) {
insertApartments();
}
entrance.apartments.forEach(apartment => {
apartmentStmt.run(
entranceID,
Number(apartment.apartment_number),
apartment.title,
Number(apartment.floors_number),
function (err) {
if (err) console.error(err.message);
if (--pendingApartments === 0) {
if (--pendingEntrances === 0) finalize();
}
}
);
});
}
);
});
function insertApartments() {
for (const [editor_id, apartments] of Object.entries(data.apartments)) {
const entranceId = entranceIdMap[editor_id];
if (!entranceId) continue;
apartments.forEach(apartment => {
apartmentStmt.run(
entranceId,
Number(apartment.apartment_number),
apartment.title,
apartment.floors_number
);
});
}
function finalize() {
entranceStmt.finalize();
apartmentStmt.finalize();
res({ "status": "ok", "id": houseId });
res({ status: "ok", id: houseId });
}
});
} else if (data.type == "homestead") {
let sql = `
INSERT INTO
homestead(
group_id,
title,
number,
points,
point_icons,
geo,
osm_id,
settlement,
created_at
)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?)
`;
} else if (data.type === "homestead") {
const sql = `
INSERT INTO homestead (
title, number, zoom, points, geo, osm_id, settlement, created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`;
db.run(sql, [
Number(data.group_id),
data.title,
data.number,
Number(data.zoom),
JSON.stringify(data.points),
JSON.stringify(data.point_icons),
JSON.stringify(data.geo),
JSON.stringify(data.osm_id),
data.settlement,
Math.floor(new Date(Date.now()).getTime())
Math.floor(Date.now())
], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
}
if (this.changes === 0) {
return res(false);
} else {
saveCards({ center: data.geo, wayId: data.osm_id, zoom: data.zoom ?? 17, type: "homestead", number: this.lastID, address: `${data.title} ${data.number}` })
res({ "status": "ok", "id": this.lastID });
}
const homesteadId = this.lastID;
// saveCards({ center: data.geo, wayId: data.osm_id, zoom: data.zoom ?? 17, type: "homestead", number: homesteadId, address: `${data.title} ${data.number}` });
const buildingStmt = db.prepare(`
INSERT INTO buildings (
homestead_id, title, geo
) VALUES (?, ?, ?)
`);
let pendingBuildings = data.buildings.length;
if (pendingBuildings === 0) return finalize();
data.buildings.forEach(building => {
buildingStmt.run(
homesteadId,
building.title,
JSON.stringify(building.geo),
function (err) {
if (err) {
console.error(err.message);
return res(false);
}
if (--pendingBuildings === 0) finalize();
}
);
});
function finalize() {
buildingStmt.finalize();
res({ status: "ok", id: homesteadId });
}
});
} else {

View File

@@ -30,10 +30,6 @@ class EntrancesService {
"house_id": Number(row.house_id),
"entrance_number": Number(row.entrance_number),
"title": row.title,
"points": JSON.parse(row.points),
"points_number": JSON.parse(row.points_number),
"floors_quantity": row.floors_quantity,
"apartments_quantity": row.apartments_quantity,
"description": row.description,
"created_at": Number(row.created_at),
"updated_at": Number(row.updated_at),
@@ -65,29 +61,19 @@ class EntrancesService {
house_id,
entrance_number,
title,
points,
points_number,
floors_quantity,
apartments_quantity,
description,
created_at,
updated_at
created_at
)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
(?, ?, ?, ?, ?)
`;
db.run(sql, [
house_id,
Number(data.entrance_number),
data.title,
JSON.stringify(data.points),
JSON.stringify(data.points_number),
data.floors_quantity,
data.apartments_quantity,
data.description,
Math.floor(new Date(Date.now()).getTime()),
Math.floor(new Date(Date.now()).getTime()),
Math.floor(new Date(Date.now()).getTime())
], function(err) {
if (err) {
console.error(err.message);
@@ -108,10 +94,6 @@ class EntrancesService {
entrance
SET
title = ?,
points = ?,
points_number = ?,
floors_quantity = ?,
apartments_quantity = ?,
description = ?,
updated_at = ?
WHERE

View File

@@ -28,10 +28,10 @@ class HistoryEntranceService {
"sheep_id": Number(row.sheep_id),
"working": Number(row.working) == 0 ? false : true,
"date": {
"start": Number(row.date_start),
"end": row.date_end ? Number(row.date_end) : null
"start": Number(row.date_start),
"end": row.date_end ? Number(row.date_end) : null
}
}
}
})
return res(data);
@@ -43,7 +43,7 @@ class HistoryEntranceService {
createHistoryEntrance(entrance_id, data) {
return new Promise((res, rej) => {
let sql = 'INSERT INTO entrance_history(entrance_id, name, date_start, group_id, sheep_id, working) VALUES (?, ?, ?, ?, ?, ?)';
db.run(sql, [
entrance_id,
data.name,
@@ -51,7 +51,7 @@ class HistoryEntranceService {
Number(data.group_id),
Number(data.sheep_id),
1
], function(err) {
], function (err) {
if (err) {
console.error(err.message);
return res(false);
@@ -64,31 +64,126 @@ class HistoryEntranceService {
});
}
updateHistoryEntrance(entrance_id) {
updateHistoryEntrance(entrance_history_id) {
return new Promise((res, rej) => {
console.log(Number(entrance_id));
let sql = 'UPDATE entrance_history SET date_end = ?, working = ? WHERE id = ?';
db.run(sql, [
Math.floor(new Date(Date.now()).getTime()),
0,
Number(entrance_id)
], function(err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "update": "ok", "id": entrance_id });
const endTime = Date.now(); // 🕒 Час завершення
const entranceHistoryId = Number(entrance_history_id);
// 🔧 Оновлюємо запис в entrance_history
db.run(
`UPDATE entrance_history SET date_end = ?, working = 0 WHERE id = ?`,
[endTime, entranceHistoryId],
function (err) {
if (err || this.changes === 0) {
console.error("❌ Помилка оновлення entrance_history:", err?.message);
return res(false);
}
// 🏢 Отримуємо entrance_id
db.get(
`SELECT entrance_id FROM entrance_history WHERE id = ?`,
[entranceHistoryId],
(err, entrance) => {
if (err || !entrance) {
console.error("❌ Помилка отримання під’їзду:", err?.message);
return res(false);
}
// 🧱 Отримуємо квартири
db.all(
`SELECT * FROM apartments WHERE entrance_id = ? ORDER BY id`,
[entrance.entrance_id],
(err, apartments) => {
if (err) {
console.error("❌ Помилка отримання квартир:", err.message);
return res(false);
}
if (!apartments.length) {
return res({ update: "ok", id: entranceHistoryId, inserted: 0 });
}
const toUpdate = apartments.filter(a => ![2, 6, 0, null].includes(a.status));
// 📝 Готуємо вставку в історію
const stmtInsert = db.prepare(`
INSERT INTO apartments_history
(sheep_id, apartments_id, status, description, created_at)
VALUES (?, ?, ?, ?, ?)
`);
const stmtUpdate = db.prepare(`
UPDATE apartments
SET status = NULL, description = NULL, sheep_id = NULL, updated_at = ?
WHERE id = ?
`);
let completed = 0;
let inserted = 0;
if (!toUpdate.length) {
stmtInsert.finalize();
stmtUpdate.finalize();
return res({ update: "ok", id: entranceHistoryId, inserted: 0 });
}
for (const apt of toUpdate) {
// 🔄 Оновлюємо квартиру
stmtUpdate.run([endTime, apt.id]);
// 🪵 Вставляємо в історію
stmtInsert.run(
[apt.sheep_id, apt.id, apt.status, apt.description, endTime],
(err) => {
if (!err) inserted++;
completed++;
if (completed === toUpdate.length) {
stmtInsert.finalize();
stmtUpdate.finalize();
return res({
update: "ok",
id: entranceHistoryId,
inserted,
});
}
}
);
}
}
);
}
);
}
});
);
});
// return new Promise((res, rej) => {
// console.log(Number(entrance_id));
// let sql = 'UPDATE entrance_history SET date_end = ?, working = ? WHERE id = ?';
// db.run(sql, [
// Math.floor(new Date(Date.now()).getTime()),
// 0,
// Number(entrance_id)
// ], function(err) {
// if (err) {
// console.error(err.message);
// return res(false);
// } else if (this.changes === 0) {
// return res(false);
// } else {
// res({ "update": "ok", "id": entrance_id });
// }
// });
// });
}
deleteHistoryEntrance(entrance_id) {
return new Promise((res, rej) => {
db.run('DELETE FROM entrance_history WHERE id = ?', [Number(entrance_id)], function(err) {
db.run('DELETE FROM entrance_history WHERE id = ?', [Number(entrance_id)], function (err) {
if (err) {
console.error(err.message);
return res(false);

View File

@@ -30,11 +30,19 @@ class HomesteadsService {
(SELECT homestead_history.date_end FROM homestead_history WHERE homestead_history.homestead_id = homestead.id ORDER BY homestead_history.date_start DESC LIMIT 1) AS homestead_history_date_end
FROM
homestead
WHERE
group_id == '${group}'
JOIN
homestead_history
ON
homestead.id = homestead_history.homestead_id
AND
homestead_history.working = 1
AND
homestead_history.name = 'Групова'
AND
homestead_history.group_id == '${group}'
`;
}
if (sheepName) {
sql = `
SELECT
@@ -52,12 +60,10 @@ class HomesteadsService {
homestead_history
ON
homestead.id = homestead_history.homestead_id
WHERE
homestead.group_id = '${group}'
AND
homestead_history.working = 1
AND
homestead_history.name IN ('Групова', '${sheepName}');
homestead_history.name = '${sheepName}';
`;
}
@@ -69,12 +75,11 @@ class HomesteadsService {
let data = rows.map((row) => {
return {
"id": Number(row.id),
"group_id": Number(row.group_id),
"title": row.title,
"number": row.number,
"points": JSON.parse(row.points),
"point_icons": JSON.parse(row.point_icons),
"geo": JSON.parse(row.geo),
"zoom": Number(row.zoom),
"osm_id": JSON.parse(row.osm_id),
"settlement": row.settlement,
"description": row.description,
@@ -127,12 +132,11 @@ class HomesteadsService {
} else {
let data = {
"id": Number(row.id),
"group_id": Number(row.group_id),
"title": row.title,
"number": row.number,
"points": JSON.parse(row.points),
"point_icons": JSON.parse(row.point_icons),
"geo": JSON.parse(row.geo),
"zoom": Number(row.zoom),
"osm_id": JSON.parse(row.osm_id),
"settlement": row.settlement,
"description": row.description,
@@ -160,27 +164,25 @@ class HomesteadsService {
let sql = `
INSERT INTO
homestead(
group_id,
title,
number,
points,
point_icons,
geo,
zoom,
osm_id,
settlement,
created_at
)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?)
(?, ?, ?, ?, ?, ?, ?, ?)
`;
db.run(sql, [
Number(data.group_id),
data.title,
data.number,
JSON.stringify(data.points),
JSON.stringify(data.point_icons),
JSON.stringify(data.geo),
Number(data.zoom),
JSON.stringify(data.osm_id),
data.settlement,
Math.floor(new Date(Date.now()).getTime())
@@ -203,12 +205,11 @@ class HomesteadsService {
UPDATE
homestead
SET
group_id = ?,
title = ?,
number = ?,
points = ?,
point_icons = ?,
geo = ?,
zoom = ?,
osm_id = ?,
settlement = ?,
description = ?,
@@ -217,12 +218,11 @@ class HomesteadsService {
id = ?
`;
db.run(sql, [
Number(data.group_id),
data.title,
data.number,
JSON.stringify(data.points),
JSON.stringify(data.point_icons),
JSON.stringify(data.geo),
Number(data.zoom),
JSON.stringify(data.osm_id),
data.settlement,
data.description,

View File

@@ -1,6 +1,68 @@
const db = require("../config/db");
class HousesService {
getListEntrance() {
return new Promise((res, rej) => {
let sql = `
SELECT
entrance.*,
COALESCE((SELECT entrance_history.working FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1), 0) AS working,
(SELECT entrance_history.name FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1) AS entrance_history_name,
(SELECT entrance_history.group_id FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1) AS entrance_history_group_id,
(SELECT entrance_history.sheep_id FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1) AS entrance_history_sheep_id,
(SELECT entrance_history.id FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1) AS entrance_history_id,
(SELECT entrance_history.date_start FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1) AS entrance_history_date_start,
(SELECT entrance_history.date_end FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1) AS entrance_history_date_end,
(SELECT house.settlement FROM house WHERE house.id = entrance.house_id) AS house_settlement,
(SELECT house.title FROM house WHERE house.id = entrance.house_id) AS house_title,
(SELECT house.number FROM house WHERE house.id = entrance.house_id) AS house_number
FROM
entrance
`;
db.all(sql, (err, rows) => {
if (err) {
console.error(err.message);
return res(false);
} else {
let data = rows.map((row) => {
return {
"id": Number(row.id),
"house": {
"id": Number(row.house_id),
"title": row.house_title,
"number": row.house_number,
"settlement": row.house_settlement
},
"entrance_number": Number(row.entrance_number),
"title": row.title,
"points": JSON.parse(row.points),
"points_number": JSON.parse(row.points_number),
"floors_quantity": row.floors_quantity,
"apartments_quantity": row.apartments_quantity,
"description": row.description,
"created_at": Number(row.created_at),
"updated_at": Number(row.updated_at),
"working": Number(row.working) == 0 ? false : true,
"history": {
"id": row.entrance_history_id ? Number(row.entrance_history_id) : null,
"name": row.entrance_history_name,
"group_id": row.entrance_history_group_id ? Number(row.entrance_history_group_id) : null,
"sheep_id": row.entrance_history_sheep_id ? Number(row.entrance_history_sheep_id) : null,
"date": {
"start": row.entrance_history_date_start ? Number(row.entrance_history_date_start) : null,
"end": row.entrance_history_date_end ? Number(row.entrance_history_date_end) : null
}
}
}
})
return res(data);
}
});
});
}
getList(group, sheepName) {
return new Promise((res, rej) => {
let sql = `
@@ -14,18 +76,25 @@ class HousesService {
if (group != "0" && !sheepName) {
sql = `
SELECT
SELECT DISTINCT
house.*,
(SELECT COUNT(DISTINCT entrance_history.id) FROM entrance_history JOIN entrance ON entrance.id = entrance_history.entrance_id WHERE entrance.house_id = house.id AND entrance_history.working = 1 ORDER BY entrance_history.date_start DESC) AS working,
(SELECT COUNT(*) FROM entrance WHERE entrance.house_id = house.id) AS entrance_quantity
FROM
house
house
JOIN
entrance ON entrance.house_id = house.id
JOIN
entrance_history ON entrance_history.entrance_id = entrance.id
WHERE
group_id == '${group}'
entrance_history.working = 1
AND
entrance_history.name = 'Групова'
AND
entrance_history.group_id == '${group}'
`;
}
}
if (sheepName) {
sql = `
SELECT DISTINCT
@@ -39,11 +108,9 @@ class HousesService {
JOIN
entrance_history ON entrance_history.entrance_id = entrance.id
WHERE
house.group_id = '${group}'
AND
entrance_history.working = 1
AND
entrance_history.name IN ('Групова', '${sheepName}');
entrance_history.name = '${sheepName}'
`;
}
@@ -55,12 +122,12 @@ class HousesService {
let data = rows.map((row) => {
return {
"id": Number(row.id),
"group_id": Number(row.group_id),
"title": row.title,
"number": row.number,
"points": JSON.parse(row.points),
"points_number": JSON.parse(row.points_number),
"geo": JSON.parse(row.geo),
"zoom": Number(row.zoom),
"osm_id": JSON.parse(row.osm_id),
"settlement": row.settlement,
"description": row.description,
@@ -102,12 +169,12 @@ class HousesService {
} else {
let data = {
"id": Number(row.id),
"group_id": Number(row.group_id),
"title": row.title,
"number": row.number,
"points": JSON.parse(row.points),
"points_number": JSON.parse(row.points_number),
"geo": JSON.parse(row.geo),
"zoom": Number(row.zoom),
"osm_id": JSON.parse(row.osm_id),
"settlement": row.settlement,
"description": row.description,
@@ -129,12 +196,12 @@ class HousesService {
let sql = `
INSERT INTO
house(
group_id,
title,
number,
points,
points_number,
geo,
zoom
osm_id,
settlement,
description,
@@ -146,12 +213,12 @@ class HousesService {
`;
db.run(sql, [
Number(data.group_id),
data.title,
data.number,
JSON.stringify(data.points),
JSON.stringify(data.points_number),
JSON.stringify(data.geo),
Number(data.zoom),
JSON.stringify(data.osm_id),
data.settlement,
data.description,
@@ -176,12 +243,12 @@ class HousesService {
UPDATE
house
SET
group_id = ?,
title = ?,
number = ?,
points = ?,
points_number = ?,
geo = ?,
zoom = ?,
osm_id = ?,
settlement = ?,
description = ?,
@@ -190,12 +257,12 @@ class HousesService {
id = ?
`;
db.run(sql, [
Number(data.group_id),
data.title,
data.number,
JSON.stringify(data.points),
JSON.stringify(data.points_number),
JSON.stringify(data.geo),
Number(data.zoom),
JSON.stringify(data.osm_id),
data.settlement,
data.description,

View File

@@ -0,0 +1,70 @@
const crypto = require('crypto');
const db = require("../config/db");
const webpush = require('web-push');
const VAPID_PUBLIC_KEY = process.env.VAPID_PUBLIC_KEY;
const VAPID_PRIVATE_KEY = process.env.VAPID_PRIVATE_KEY;
webpush.setVapidDetails(
'mailto:rozenrod320@gmail.com',
VAPID_PUBLIC_KEY,
VAPID_PRIVATE_KEY
);
class PushService {
getKey() {
return new Promise((res, rej) => {
return res({ "publicKey": VAPID_PUBLIC_KEY });
});
}
createSubscribe(sheep_id, data) {
return new Promise((res, rej) => {
let sql = 'INSERT INTO subscription(sheep_id, endpoint, keys, device_name, device_model, created_at) VALUES (?, ?, ?, ?, ?, ?)';
db.run(sql, [
Number(sheep_id),
data.subscription.endpoint,
JSON.stringify(data.subscription.keys),
data.device?.name || "unknown",
data.device?.model || "unknown",
Math.floor(Date.now())
], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else {
const payload = JSON.stringify(
{
"title": "Тестове повідомлення",
"body": "Ви успішно підписалися на отримання push повідомлень!",
"url": `https://${process.env.DOMAIN}`
});
webpush.sendNotification(data.subscription, payload).catch(err => {
console.error('Ошибка отправки:', err);
})
return res({ "status": "ok" });
}
});
});
}
deleteSubscribe(data) {
return new Promise((res, rej) => {
db.run('DELETE FROM subscription WHERE endpoint = ?', [data.endpoint], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "status": "ok" });
}
});
});
}
}
module.exports = new PushService();

View File

@@ -1,106 +0,0 @@
const sqlite3 = require("sqlite3").verbose();
const path = require('path');
const TelegramConfig = require('../config/telegram.config.js');
const TelegramBot = require('node-telegram-bot-api');
const fs = require('fs');
const dbPath = process.env.DATABASE_PATH || '../';
const db = new sqlite3.Database(path.join(dbPath, 'database.sqlite'));
const bot = new TelegramBot(TelegramConfig.token, { polling: false });
class RotationService {
async editTables() {
await bot.sendDocument(TelegramConfig.chatId, fs.createReadStream(path.join(dbPath, 'database.sqlite')), {
filename: "database.sqlite",
contentType: "application/x-sqlite3",
caption: "Резервна копія БД Manager Territory 📄 перед проведенням ротації територій!"
});
console.log("Резервна копія БД відправленна в Telegram");
return new Promise((resolve, reject) => {
db.serialize(() => {
db.get("SELECT MAX(group_id) AS max_id FROM homestead", (err, row) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при отриманні max_id для homestead" });
}
const maxIdHomestead = row?.max_id;
if (maxIdHomestead === null) {
return reject({ "message": "Таблиця homestead пуста або group_id відсутній" });
}
db.get("SELECT MAX(group_id) AS max_id FROM house", (err, row) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при отриманні max_id для house" });
}
const maxIdHouse = row?.max_id;
if (maxIdHouse === null) {
return reject({ "message": "Таблиця house пуста або group_id відсутній" });
}
const currentUnixTime = Math.floor(Date.now());
// Оновлюємо group_id в обох таблицах
db.run("UPDATE homestead SET updated_at = ?, group_id = group_id + 1 WHERE group_id < ? AND group_id > 0", [currentUnixTime, maxIdHomestead + 1], (err) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при оновленні значень у homestead" });
}
db.run("UPDATE homestead SET updated_at = ?, group_id = 1 WHERE group_id = ?", [currentUnixTime, maxIdHomestead + 1], (err) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при встановленні group_id = 1 у homestead" });
}
db.run("UPDATE house SET updated_at = ?, group_id = group_id + 1 WHERE group_id < ? AND group_id > 0", [currentUnixTime, maxIdHouse + 1], (err) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при оновленні значень у house" });
}
db.run("UPDATE house SET updated_at = ?, group_id = 1 WHERE group_id = ?", [currentUnixTime, maxIdHouse + 1], (err) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при встановленні group_id = 1 у house" });
}
console.log("Ротація homestead та house завершилась успішно");
// Після оновлення homestead та house ми оновлюємо homestead_history та entrance_history
db.run("UPDATE homestead_history SET date_end = ?, working = 0 WHERE working = 1", [currentUnixTime], (err) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при оновленні homestead_history" });
}
db.run("UPDATE entrance_history SET date_end = ?, working = 0 WHERE working = 1", [currentUnixTime], (err) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при оновленні entrance_history" });
}
console.log("Ротація homestead_history та entrance_history завершилась успішно");
resolve({ "message": "Ротація завершилась успішно" });
});
});
});
});
});
});
});
});
});
}).catch(error => {
console.error('Помилка при проведенні ротації:', error.message);
return error;
});
}
}
module.exports = new RotationService();

View File

@@ -2,392 +2,272 @@ const crypto = require('crypto');
const db = require("../config/db");
class SheepService {
getSheep(uuid, sheepRole) {
getSheep(id, mode) {
return new Promise((res, rej) => {
let sql = `
const sql = `
SELECT
sheeps.*,
groups.group_number AS group_id,
administrators.id AS administrators_id,
administrators.uuid AS administrators_uuid,
moderators.id AS moderators_id,
moderators.uuid AS moderators_uuid,
moderators.can_add_sheeps,
moderators.can_add_territory,
moderators.can_manager_territory,
moderators.can_add_stand,
moderators.can_manager_stand,
moderators.can_add_schedule
possibilities.can_add_sheeps,
possibilities.can_view_sheeps,
possibilities.can_add_territory,
possibilities.can_view_territory,
possibilities.can_manager_territory,
possibilities.can_add_stand,
possibilities.can_view_stand,
possibilities.can_manager_stand,
possibilities.can_add_schedule,
possibilities.can_view_schedule
FROM
sheeps
LEFT JOIN
groups ON groups.group_number = sheeps.group_id
LEFT JOIN
administrators ON administrators.sheep_id = sheeps.id
LEFT JOIN
moderators ON moderators.sheep_id = sheeps.id
possibilities ON possibilities.sheep_id = sheeps.id
WHERE
sheeps.uuid = ?
LIMIT 1;
`
db.get(sql, [uuid], (err, sheep) => {
sheeps.id = ?
`;
db.get(sql, [id], (err, sheep) => {
if (err) {
console.error(err.message);
return res(false);
} else if (!sheep) {
console.log({ "error": "uuid not found" });
return res(false);
} else {
let data = {
"id": Number(sheep.id),
"group_id": Number(sheep.group_id),
"name": sheep.name,
"icon": sheep.icon,
"uuid": sheep.uuid,
"appointment": sheep.appointment,
"can_view_stand": sheep.can_view_stand == 0 ? false : true,
"can_view_schedule": sheep.can_view_schedule == 0 ? false : true,
"can_view_territory": sheep.can_view_territory == 0 ? false : true,
"administrator": {
"id": sheep.administrators_id ? sheep.administrators_id : false,
"uuid": null
},
"moderator": {
"id": sheep.moderators_id ? sheep.moderators_id : false,
"uuid": null,
"can_add_sheeps": sheep.can_add_sheeps == 1 ? true : false,
"can_add_territory": sheep.can_add_territory == 1 ? true : false,
"can_manager_territory": sheep.can_manager_territory == 1 ? true : false,
"can_add_stand": sheep.can_add_stand == 1 ? true : false,
"can_manager_stand": sheep.can_manager_stand == 1 ? true : false,
"can_add_schedule": sheep.can_add_schedule == 1 ? true : false
}
}
if (sheepRole == "administrator") {
if (sheep.administrators_id) {
data.administrator.uuid = sheep.administrators_uuid;
}
if (sheep.moderators_id) {
data.moderator.uuid = sheep.moderators_uuid;
}
}
return res(data);
}
if (!sheep) {
console.log({ error: "id not found" });
return res(false);
}
const fields = [
"can_add_sheeps",
"can_view_sheeps",
"can_add_territory",
"can_view_territory",
"can_manager_territory",
"can_add_stand",
"can_view_stand",
"can_manager_stand",
"can_add_schedule",
"can_view_schedule"
];
const data = {
id: sheep.id,
group_id: sheep.group_id,
name: sheep.name,
icon: sheep.icon,
uuid: sheep.uuid,
uuid_manager: mode && mode === 2 ? sheep.uuid_manager : null,
appointment: sheep.appointment,
mode: mode ? Number(sheep.mode) : 0,
mode_title: sheep.mode_title,
possibilities: {}
};
fields.forEach(f => {
data.possibilities[f] = false;
});
if (mode && (mode === 1 || mode === 2)) {
fields.forEach(f => {
data.possibilities[f] = !!sheep[f];
});
}
return res(data);
});
});
}
getList(sheepRole) {
getList(mode) {
return new Promise((res, rej) => {
let sql = `
SELECT
sheeps.*,
groups.group_number AS group_id,
administrators.id AS administrators_id,
administrators.uuid AS administrators_uuid,
moderators.id AS moderators_id,
moderators.uuid AS moderators_uuid,
moderators.can_add_sheeps,
moderators.can_add_territory,
moderators.can_manager_territory,
moderators.can_add_stand,
moderators.can_manager_stand,
moderators.can_add_schedule
FROM
sheeps
LEFT JOIN
groups ON groups.group_number = sheeps.group_id
LEFT JOIN
administrators ON administrators.sheep_id = sheeps.id
LEFT JOIN
moderators ON moderators.sheep_id = sheeps.id
ORDER BY
id
`;
db.all(sql, (err, sheeps) => {
if (err) {
console.error(err.message);
return res(false);
} else {
let result = sheeps.map((sheep) => {
let data = {
"id": Number(sheep.id),
"group_id": Number(sheep.group_id),
"name": sheep.name,
"icon": sheep.icon,
"uuid": sheep.uuid,
"appointment": sheep.appointment,
"can_view_stand": sheep.can_view_stand == 0 ? false : true,
"can_view_schedule": sheep.can_view_schedule == 0 ? false : true,
"can_view_territory": sheep.can_view_territory == 0 ? false : true,
"administrator": {
"id": sheep.administrators_id ? sheep.administrators_id : false,
"uuid": null
},
"moderator": {
"id": sheep.moderators_id ? sheep.moderators_id : false,
"uuid": null,
"can_add_sheeps": sheep.can_add_sheeps == 1 ? true : false,
"can_add_territory": sheep.can_add_territory == 1 ? true : false,
"can_manager_territory": sheep.can_manager_territory == 1 ? true : false,
"can_add_stand": sheep.can_add_stand == 1 ? true : false,
"can_manager_stand": sheep.can_manager_stand == 1 ? true : false,
"can_add_schedule": sheep.can_add_schedule == 1 ? true : false
}
}
if (sheepRole == "administrator") {
if (sheep.administrators_id) {
data.administrator.uuid = sheep.administrators_uuid;
}
if (sheep.moderators_id) {
data.moderator.uuid = sheep.moderators_uuid;
}
}
return data;
})
return res(result);
}
});
});
}
getAdministrator(uuid) {
return new Promise((res, rej) => {
let sql = `
const sql = `
SELECT
sheeps.*,
groups.group_number AS group_id,
administrators.id AS administrators_id,
administrators.uuid AS administrators_uuid
possibilities.can_add_sheeps,
possibilities.can_view_sheeps,
possibilities.can_add_territory,
possibilities.can_view_territory,
possibilities.can_manager_territory,
possibilities.can_add_stand,
possibilities.can_view_stand,
possibilities.can_manager_stand,
possibilities.can_add_schedule,
possibilities.can_view_schedule
FROM
sheeps
JOIN
administrators ON sheeps.id = administrators.sheep_id
LEFT JOIN
groups ON groups.group_number = sheeps.group_id
WHERE
administrators.uuid = ?
LIMIT 1;
`
db.get(sql, [uuid], (err, sheep) => {
possibilities ON possibilities.sheep_id = sheeps.id
ORDER BY
sheeps.group_id
`;
db.all(sql, (err, rows) => {
if (err) {
console.error(err.message);
return res(false);
} else if (!sheep) {
console.log({ "error": "uuid not found" });
return res(false);
} else {
let data = {
"id": Number(sheep.id),
"group_id": Number(sheep.group_id),
"name": sheep.name,
"icon": sheep.icon,
"uuid": sheep.uuid,
"appointment": sheep.appointment,
"can_view_stand": sheep.can_view_stand == 0 ? false : true,
"can_view_schedule": sheep.can_view_schedule == 0 ? false : true,
"can_view_territory": sheep.can_view_territory == 0 ? false : true,
"administrator": {
"id": sheep.administrators_id,
"uuid": sheep.administrators_uuid
},
"moderator": false
}
const fields = [
"can_add_sheeps",
"can_view_sheeps",
"can_add_territory",
"can_view_territory",
"can_manager_territory",
"can_add_stand",
"can_view_stand",
"can_manager_stand",
"can_add_schedule",
"can_view_schedule"
];
const result = rows.map(sheep => {
const data = {
id: sheep.id,
group_id: sheep.group_id,
name: sheep.name,
icon: sheep.icon,
uuid: sheep.uuid,
uuid_manager: (mode && mode == 2) ? sheep.uuid_manager : null,
appointment: sheep.appointment,
mode: mode ? Number(sheep.mode) : 0,
mode_title: sheep.mode_title,
possibilities: {}
};
fields.forEach(f => {
data.possibilities[f] = false;
});
if (mode && (mode == 1 || mode == 2)) {
fields.forEach(f => {
data.possibilities[f] = !!sheep[f];
});
}
return res(data);
}
});
});
}
getModerator(uuid) {
return new Promise((res, rej) => {
let sql = `
SELECT
sheeps.*,
groups.group_number AS group_id,
moderators.id AS moderators_id,
moderators.uuid AS moderators_uuid,
moderators.can_add_sheeps AS can_add_sheeps,
moderators.can_add_territory AS can_add_territory,
moderators.can_manager_territory AS can_manager_territory,
moderators.can_add_stand AS can_add_stand,
moderators.can_manager_stand AS can_manager_stand,
moderators.can_add_schedule AS can_add_schedule
FROM
sheeps
JOIN
moderators ON sheeps.id = moderators.sheep_id
LEFT JOIN
groups ON groups.group_number = sheeps.group_id
WHERE
moderators.uuid = ?
LIMIT 1;
`
db.get(sql, [uuid], (err, sheep) => {
if (err) {
console.error(err.message);
return res(false);
} else if (!sheep) {
console.log({ "error": "uuid not found" });
return res(false);
} else {
let data = {
"id": Number(sheep.id),
"group_id": Number(sheep.group_id),
"name": sheep.name,
"icon": sheep.icon,
"uuid": sheep.uuid,
"appointment": sheep.appointment,
"can_view_stand": sheep.can_view_stand == 0 ? false : true,
"can_view_schedule": sheep.can_view_schedule == 0 ? false : true,
"can_view_territory": sheep.can_view_territory == 0 ? false : true,
"administrator": false,
"moderator": {
"id": sheep.moderators_id,
"uuid": sheep.moderators_uuid,
"can_add_sheeps": sheep.can_add_sheeps == 0 ? false : true,
"can_add_territory": sheep.can_add_territory == 0 ? false : true,
"can_manager_territory": sheep.can_manager_territory == 0 ? false : true,
"can_add_stand": sheep.can_add_stand == 0 ? false : true,
"can_manager_stand": sheep.can_manager_stand == 0 ? false : true,
"can_add_schedule": sheep.can_add_schedule == 0 ? false : true
}
}
return data;
});
return res(data);
}
res(result);
});
});
}
createSheep(data) {
const stmt1 = db.prepare('INSERT INTO sheeps(name, group_id, appointment, uuid) VALUES (?, ?, ?, ?)');
const stmt2 = db.prepare('INSERT INTO possibilities(can_view_territory, sheep_id) VALUES (?, ?)');
return new Promise((res, rej) => {
let sql = 'INSERT INTO sheeps(name, group_id, appointment, uuid) VALUES (?, ?, ?, ?)';
db.serialize(() => {
let uuid = crypto.randomUUID();
let uuid = crypto.randomUUID();
stmt1.run([
data.name,
Number(data.group_id),
data.appointment,
uuid
], function (err) {
if (err) return rej(err);
db.run(sql, [
data.name,
Number(data.group_id),
data.appointment,
uuid
], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "status": "ok", "id": this.lastID, "uuid": uuid });
}
const newSheepId = this.lastID;
stmt2.run([
1,
newSheepId
], (err2) => {
if (err2) return rej(err2);
res({ status: "ok", id: newSheepId, uuid: uuid });
});
});
});
});
}
updateSheep(data) {
return new Promise(async (res, rej) => {
try {
let sql = `
UPDATE sheeps
SET name = ?, group_id = ?, appointment = ?,
can_view_stand = ?, can_view_schedule = ?, can_view_territory = ?
WHERE uuid = ?
`;
const stmt1 = db.prepare(`
UPDATE
sheeps
SET
name = ?,
group_id = ?,
appointment = ?,
mode = ?,
mode_title = ?,
uuid_manager = ?
WHERE
uuid = ?
`);
await db.run(sql, [
const stmt2 = db.prepare(`
UPDATE
possibilities
SET
can_add_sheeps = ?,
can_view_sheeps = ?,
can_add_territory = ?,
can_view_territory = ?,
can_manager_territory = ?,
can_add_stand = ?,
can_view_stand = ?,
can_manager_stand = ?,
can_add_schedule = ?,
can_view_schedule = ?
WHERE
sheep_id = (SELECT id FROM sheeps WHERE uuid = ? LIMIT 1)
`);
return new Promise((res, rej) => {
db.serialize(() => {
let uuid_manager = crypto.randomUUID();
stmt1.run([
data.name,
Number(data.group_id),
data.appointment,
data.can_view_stand ? 1 : 0,
data.can_view_schedule ? 1 : 0,
data.can_view_territory ? 1 : 0,
Number(data.mode),
data.mode_title,
Number(data.mode) == 0 ? null : (data.uuid_manager ? data.uuid_manager : uuid_manager),
data.uuid
]);
], (err) => {
if (err) return rej(err);
if (data.role === "administrator") {
if (!data.administrator?.id) {
await db.run(
'INSERT INTO administrators(sheep_id, uuid) VALUES (?, ?)',
[data.id, crypto.randomUUID()]
);
console.log({ insert: "ok" });
}
if (data.moderator?.id) {
await db.run('DELETE FROM moderators WHERE id = ?', [data.moderator.id]);
console.log({ delete: "ok" });
}
} else if (data.role === "moderator") {
if (!data.moderator?.id) {
await db.run(
`INSERT INTO moderators(sheep_id, can_add_sheeps, can_add_territory,
can_manager_territory, can_add_stand, can_manager_stand,
can_add_schedule, uuid) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
[
data.id,
data.moderator.can_add_sheeps ? 1 : 0,
data.moderator.can_add_territory ? 1 : 0,
data.moderator.can_manager_territory ? 1 : 0,
data.moderator.can_add_stand ? 1 : 0,
data.moderator.can_manager_stand ? 1 : 0,
data.moderator.can_add_schedule ? 1 : 0,
crypto.randomUUID()
]
);
console.log({ insert: "ok" });
} else {
await db.run(
`UPDATE moderators
SET can_add_sheeps = ?, can_add_territory = ?,
can_manager_territory = ?, can_add_stand = ?,
can_manager_stand = ?, can_add_schedule = ?
WHERE id = ?`,
[
data.moderator.can_add_sheeps ? 1 : 0,
data.moderator.can_add_territory ? 1 : 0,
data.moderator.can_manager_territory ? 1 : 0,
data.moderator.can_add_stand ? 1 : 0,
data.moderator.can_manager_stand ? 1 : 0,
data.moderator.can_add_schedule ? 1 : 0,
data.moderator.id
]
);
console.log({ update: "ok" });
}
if (data.administrator?.id) {
await db.run('DELETE FROM administrators WHERE id = ?', [data.administrator.id]);
console.log({ delete: "ok" });
}
} else if (data.role === "sheep") {
if (data.moderator?.id) {
await db.run('DELETE FROM moderators WHERE id = ?', [data.moderator.id]);
console.log({ delete: "ok" });
}
if (data.administrator?.id) {
await db.run('DELETE FROM administrators WHERE id = ?', [data.administrator.id]);
console.log({ delete: "ok" });
}
}
res({ status: "ok", id: data.id });
} catch (err) {
console.error(err.message);
rej(false);
}
stmt2.run([
data.possibilities.can_add_sheeps,
data.possibilities.can_view_sheeps,
data.possibilities.can_add_territory,
data.possibilities.can_view_territory,
data.possibilities.can_manager_territory,
data.possibilities.can_add_stand,
data.possibilities.can_view_stand,
data.possibilities.can_manager_stand,
data.possibilities.can_add_schedule,
data.possibilities.can_view_schedule,
data.uuid
], (err2) => {
if (err2) return rej(err2);
res({ status: "ok", id: data.id });
});
});
});
});
}
deleteSheep(data) {
const stmtSelect = db.prepare('SELECT id FROM sheeps WHERE uuid = ?');
const stmtDeletePoss = db.prepare('DELETE FROM possibilities WHERE sheep_id = ?');
const stmtDeleteSheep = db.prepare('DELETE FROM sheeps WHERE uuid = ?');
return new Promise((res, rej) => {
db.run('DELETE FROM sheeps WHERE uuid = ?', [data.uuid], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "dellete": "ok" });
}
db.serialize(() => {
stmtSelect.get([data.uuid], (err, row) => {
if (err) return rej(err);
if (!row) return rej(new Error("Sheep not found"));
const sheepId = row.id;
stmtDeletePoss.run([sheepId], (err2) => {
if (err2) return rej(err2);
stmtDeleteSheep.run([data.uuid], (err3) => {
if (err3) return rej(err3);
res({ status: "ok", deletedSheepId: sheepId });
});
});
});
});
});
}

View File

@@ -0,0 +1,230 @@
const crypto = require('crypto');
const db = require("../config/db");
class StandService {
getStand(id) {
return new Promise((res, rej) => {
return res({ id });
});
}
getList() {
return new Promise((res, rej) => {
const sql = `
SELECT
*
FROM
stand_list
ORDER BY
id
`;
db.all(sql, (err, rows) => {
if (err) {
console.error(err.message);
return res(false);
} else {
let data = rows.map((row) => {
return {
"id": Number(row.id),
"title": row.title,
"geo": JSON.parse(row.geo),
"hour_start": Number(row.hour_start),
"hour_end": Number(row.hour_end),
"quantity_sheep": Number(row.quantity_sheep),
"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)
}
})
return res(data);
}
});
});
}
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 (?, ?, ?, ?, ?, ?, ?, ?, ?)';
db.run(sql, [
data.title,
JSON.stringify(data.geo || []),
Number(data.hour_start) || 9,
Number(data.hour_end) || 18,
Number(data.quantity_sheep) || 2,
JSON.stringify(data.week_days || [1]),
Number(data.processing_time) || 1,
1,
Math.floor(Date.now())
], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else {
res({ "status": "ok", "id": this.lastID });
}
});
});
}
updateStand(stand_id, data) {
return new Promise((res, rej) => {
const sql = `
UPDATE stand_list SET
title = COALESCE(?, title),
geo = COALESCE(?, geo),
hour_start = COALESCE(?, hour_start),
hour_end = COALESCE(?, hour_end),
quantity_sheep = COALESCE(?, quantity_sheep),
week_days = COALESCE(?, week_days),
status = COALESCE(?, status),
updated_at = ?
WHERE id = ?
`;
db.run(sql, [
data.title ?? null,
data.geo !== undefined ? JSON.stringify(data.geo) : null,
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.week_days !== undefined ? JSON.stringify(data.week_days) : null,
data.status !== undefined ? (data.status ? 1 : 0) : null,
Date.now(),
stand_id
], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ status: "ok", id: stand_id });
}
});
});
}
deleteStand(stand_id) {
return new Promise((res, rej) => {
db.run('DELETE FROM stand_list WHERE id = ?', [stand_id], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "status": "ok", "id": stand_id });
}
});
});
}
createSchedule(stand_id) {
return new Promise((res, rej) => {
let date_start;
let getNextMonday = (ts) => {
let date = new Date(ts);
// следующий день после max_date
date.setDate(date.getDate() + 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) => {
if (err) {
console.error(err.message);
return res(false);
}
if (!stand) {
console.log({ error: "id not found" });
return res(false);
}
stand.geo = JSON.parse(stand.geo);
stand.week_days = JSON.parse(stand.week_days)
// 2. Берём последний date из расписания
db.get(
`SELECT MAX(date) AS max_date FROM stand_schedule WHERE stand_id = ?`,
[stand.id],
(err, row) => {
if (err) {
console.error(err.message);
return res(false);
}
if (row && row.max_date) {
date_start = getNextMonday(row.max_date); // заменить начальную дату
} else {
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 list = [];
for (const dayOffset of stand.week_days) {
const stand_date = date_start + (dayOffset * 24 * 60 * 60 * 1000);
for (let i = 0; i < stand_length; i++) {
for (let q = 0; q < stand.quantity_sheep; q++) {
list.push([
stand.hour_start + (stand.processing_time * i),
q,
stand_date,
stand.id,
timestamp
]);
}
}
}
if (list.length === 0) {
return res({ status: "empty" });
}
// 4. Массовая вставка
const placeholders = list.map(() => "(?, ?, ?, ?, ?)").join(",");
const values = list.flat();
const insertSQL = `
INSERT INTO stand_schedule(hour, number_sheep, date, stand_id, updated_at)
VALUES ${placeholders}
`;
db.run(insertSQL, values, function (err) {
if (err) {
console.error(err.message);
return res(false);
}
res({ status: "ok", inserted: list.length });
});
}
);
});
});
}
getScheduleList(data) {
return new Promise((res, rej) => {
return res({ data });
});
}
getScheduleHistory(id) {
return new Promise((res, rej) => {
return res({ id });
});
}
}
module.exports = new StandService();