This commit is contained in:
2025-05-26 18:13:45 +05:00
parent 8007eac52f
commit 650b6f4fdd
12 changed files with 636 additions and 564 deletions
+3 -2
View File
@@ -1,11 +1,12 @@
import { $, Glob } from "bun";
import path from "path";
// Cross-platform directory removal
// Cross-platform directory removal
if (process.platform === "win32") {
// await $`cmd /c "rmdir /s /q dist"`;
await $`cmd /c "if exist dist rmdir /s /q dist"`;
} else {
await $`rm -rf ./dist`;
await $`rm -rf dist`;
}
// await Bun.build({
+26 -4
View File
@@ -7,7 +7,7 @@
"@elysiajs/cors": "^1.2.0",
"drizzle-orm": "^0.41.0",
"drizzle-typebox": "^0.3.1",
"elysia": "latest",
"elysia": "^1.3.1",
"got": "^14.4.7",
"node-cron": "^3.0.3",
},
@@ -82,6 +82,10 @@
"@szmarczak/http-timer": ["@szmarczak/http-timer@5.0.1", "", { "dependencies": { "defer-to-connect": "^2.0.1" } }, "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw=="],
"@tokenizer/inflate": ["@tokenizer/inflate@0.2.7", "", { "dependencies": { "debug": "^4.4.0", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg=="],
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
"@types/http-cache-semantics": ["@types/http-cache-semantics@4.0.4", "", {}, "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA=="],
"@types/node": ["@types/node@22.14.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw=="],
@@ -110,7 +114,7 @@
"drizzle-typebox": ["drizzle-typebox@0.3.1", "", { "peerDependencies": { "@sinclair/typebox": ">=0.34.8", "drizzle-orm": ">=0.36.0" } }, "sha512-XRFaWyMC5MN5CRYoO8MiPIy7NmjrJGaBRNbMPOZEMSWWOOLjcQ5tyjUoPfenFBsw2Rs4UAN5wDGFAaJTia5E/A=="],
"elysia": ["elysia@1.2.25", "", { "dependencies": { "@sinclair/typebox": "^0.34.27", "cookie": "^1.0.2", "memoirist": "^0.3.0", "openapi-types": "^12.1.3" }, "peerDependencies": { "typescript": ">= 5.0.0" }, "optionalPeers": ["typescript"] }, "sha512-WsdQpORJvb4uszzeqYT0lg97knw1iBW1NTzJ1Jm57tiHg+DfAotlWXYbjmvQ039ssV0fYELDHinLLoUazZkEHg=="],
"elysia": ["elysia@1.3.1", "", { "dependencies": { "cookie": "^1.0.2", "exact-mirror": "0.1.2", "fast-decode-uri-component": "^1.0.1" }, "optionalDependencies": { "@sinclair/typebox": "^0.34.33", "openapi-types": "^12.1.3" }, "peerDependencies": { "file-type": ">= 20.0.0", "typescript": ">= 5.0.0" } }, "sha512-En41P6cDHcHtQ0nvfsn9ayB+8ahQJqG1nzvPX8FVZjOriFK/RtZPQBtXMfZDq/AsVIk7JFZGFEtAVEmztNJVhQ=="],
"env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="],
@@ -118,6 +122,14 @@
"esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="],
"exact-mirror": ["exact-mirror@0.1.2", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-wFCPCDLmHbKGUb8TOi/IS7jLsgR8WVDGtDK3CzcB4Guf/weq7G+I+DkXiRSZfbemBFOxOINKpraM6ml78vo8Zw=="],
"fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
"fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
"file-type": ["file-type@21.0.0", "", { "dependencies": { "@tokenizer/inflate": "^0.2.7", "strtok3": "^10.2.2", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg=="],
"form-data-encoder": ["form-data-encoder@4.0.2", "", {}, "sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw=="],
"gel": ["gel@2.0.2", "", { "dependencies": { "@petamoriken/float16": "^3.8.7", "debug": "^4.3.4", "env-paths": "^3.0.0", "semver": "^7.6.2", "shell-quote": "^1.8.1", "which": "^4.0.0" }, "bin": { "gel": "dist/cli.mjs" } }, "sha512-XTKpfNR9HZOw+k0Bl04nETZjuP5pypVAXsZADSdwr3EtyygTTe1RqvftU2FjGu7Tp9e576a9b/iIOxWrRBxMiQ=="],
@@ -132,6 +144,8 @@
"http2-wrapper": ["http2-wrapper@2.2.1", "", { "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" } }, "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ=="],
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
"is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="],
"isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="],
@@ -142,8 +156,6 @@
"lowercase-keys": ["lowercase-keys@3.0.0", "", {}, "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ=="],
"memoirist": ["memoirist@0.3.0", "", {}, "sha512-wR+4chMgVPq+T6OOsk40u9Wlpw1Pjx66NMNiYxCQQ4EUJ7jDs3D9kTCeKdBOkvAiqXlHLVJlvYL01PvIJ1MPNg=="],
"mimic-response": ["mimic-response@4.0.0", "", {}, "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
@@ -156,6 +168,8 @@
"p-cancelable": ["p-cancelable@4.0.1", "", {}, "sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg=="],
"peek-readable": ["peek-readable@7.0.0", "", {}, "sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ=="],
"postgres": ["postgres@3.4.5", "", {}, "sha512-cDWgoah1Gez9rN3H4165peY9qfpEo+SA61oQv65O3cRUE1pOEoJWwddwcqKE8XZYjbblOJlYDlLV4h67HrEVDg=="],
"quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="],
@@ -174,8 +188,16 @@
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
"strtok3": ["strtok3@10.2.2", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^7.0.0" } }, "sha512-Xt18+h4s7Z8xyZ0tmBoRmzxcop97R4BAh+dXouUDCYn+Em+1P3qpkUfI5ueWLT8ynC5hZ+q4iPEmGG1urvQGBg=="],
"token-types": ["token-types@6.0.0", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA=="],
"type-fest": ["type-fest@4.39.1", "", {}, "sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w=="],
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
"uint8array-extras": ["uint8array-extras@1.4.0", "", {}, "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ=="],
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
"uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],
+269 -246
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+269 -246
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -10,7 +10,7 @@
"@elysiajs/cors": "^1.2.0",
"drizzle-orm": "^0.41.0",
"drizzle-typebox": "^0.3.1",
"elysia": "latest",
"elysia": "^1.3.1",
"got": "^14.4.7",
"node-cron": "^3.0.3"
},
+5
View File
@@ -53,6 +53,11 @@ for (const {
suitsArea: suits_area,
squareFt: square_ft,
balconyArea: balcony_area,
wing: unit_no.startsWith("E")
? "East"
: unit_no.startsWith("W")
? "West"
: null,
};
await db
+56 -57
View File
@@ -1,4 +1,4 @@
import Elysia, { error, t } from "elysia";
import Elysia, { status, t } from "elysia";
import { unitsTable } from "../db/schema";
import { createSelectSchema } from "drizzle-typebox";
import { db } from "../db";
@@ -12,7 +12,8 @@ import {
inArray,
max,
min,
like,
isNull,
not,
} from "drizzle-orm";
export const getUnitSchema = createSelectSchema(unitsTable);
@@ -41,7 +42,8 @@ export const unitsController = new Elysia({ prefix: "/units" })
cost ? between(unitsTable.salesPrice, cost[0], cost[1]) : undefined,
floor ? between(unitsTable.floor, floor[0], floor[1]) : undefined,
area ? between(unitsTable.squareFt, area[0], area[1]) : undefined,
view ? eq(unitsTable.unitView, view) : undefined
view ? eq(unitsTable.unitView, view) : undefined,
not(isNull(unitsTable.unitType))
),
orderBy: order
? [
@@ -63,7 +65,7 @@ export const unitsController = new Elysia({ prefix: "/units" })
});
} catch (err) {
console.log((err as Error).message);
return error(500, "Internal server error");
return status(500, "Internal server error");
}
},
{
@@ -134,13 +136,14 @@ export const unitsController = new Elysia({ prefix: "/units" })
area
? between(unitsTable.squareFt, area[0], area[1])
: undefined,
view ? eq(unitsTable.unitView, view) : undefined
view ? eq(unitsTable.unitView, view) : undefined,
not(isNull(unitsTable.unitType))
)
)
)[0].count;
} catch (err) {
console.log((err as Error).message);
return error(500, "Internal server error");
return status(500, "Internal server error");
}
},
{
@@ -263,7 +266,7 @@ export const unitsController = new Elysia({ prefix: "/units" })
)[0];
} catch (err) {
console.log((err as Error).message);
return error(500, "Internal server error");
return status(500, "Internal server error");
}
},
{
@@ -332,11 +335,7 @@ export const unitsController = new Elysia({ prefix: "/units" })
try {
// Получаем данные о номерах квартир, этажах и типах
const unitsData = await db
.select({
unitNo: unitsTable.unitNo,
floor: unitsTable.floor,
unitType: unitsTable.unitType,
})
.select()
.from(unitsTable)
.where(eq(unitsTable.project, decodeURIComponent(project)));
@@ -345,68 +344,68 @@ export const unitsController = new Elysia({ prefix: "/units" })
string | number,
{
floor: string | number;
east: {
East: {
types: Record<string, number>;
totalUnits: number;
};
west: {
West: {
types: Record<string, number>;
totalUnits: number;
};
others: {
types: Record<string, number>;
totalUnits: number;
};
// totalUnits: number;
}
>();
// Обрабатываем данные квартир
for (const { unitNo, floor, unitType } of unitsData) {
if (!unitNo || !floor || !unitType) continue;
for (const unit of unitsData) {
if (unit.unitNo && unit.floor && unit.unitType) {
// Инициализируем данные для этажа, если их еще нет
// Инициализируем данные для этажа, если их еще нет
if (!floorMap.has(unit.floor)) {
floorMap.set(unit.floor, {
floor: unit.floor,
East: {
types: {},
totalUnits: 0,
},
West: {
types: {},
totalUnits: 0,
},
others: {
types: {},
totalUnits: 0,
},
});
}
// Определяем сторону (East/West) по номеру квартиры
const side = unitNo.toString().startsWith("W") ? "west" : "east";
const floorData = floorMap.get(unit.floor)!;
// Инициализируем данные для этажа, если их еще нет
if (!floorMap.has(floor)) {
floorMap.set(floor, {
floor,
east: {
types: {},
totalUnits: 0,
},
west: {
types: {},
totalUnits: 0,
},
// totalUnits: 0,
});
// Увеличиваем счетчик для типа квартиры на соответствующей стороне
if (unit.wing === "East") {
floorData.East.types[unit.unitType] =
(floorData.East.types[unit.unitType] || 0) + 1;
floorData.East.totalUnits++;
} else if (unit.wing === "West") {
floorData.West.types[unit.unitType] =
(floorData.West.types[unit.unitType] || 0) + 1;
floorData.West.totalUnits++;
} else {
floorData.others.types[unit.unitType] =
(floorData.others.types[unit.unitType] || 0) + 1;
floorData.others.totalUnits++;
}
}
const floorData = floorMap.get(floor)!;
// Увеличиваем счетчик для типа квартиры на соответствующей стороне
if (side === "east") {
floorData.east.types[unitType] =
(floorData.east.types[unitType] || 0) + 1;
floorData.east.totalUnits++;
} else {
floorData.west.types[unitType] =
(floorData.west.types[unitType] || 0) + 1;
floorData.west.totalUnits++;
}
// Увеличиваем общий счетчик квартир на этаже
// floorData.totalUnits++;
}
// Преобразуем Map в массив и сортируем по этажам
return Array.from(floorMap.values()).map((floorData) => ({
floor: floorData.floor,
east: floorData.east,
west: floorData.west,
// totalUnits: floorData.totalUnits,
}));
return Array.from(floorMap.values());
} catch (err) {
console.log((err as Error).message);
return error(500, "Internal server error");
return status(500, "Internal server error");
}
},
{
+3 -1
View File
@@ -1,4 +1,3 @@
import { primaryKey } from "drizzle-orm/pg-core";
import { unique } from "drizzle-orm/pg-core";
import { doublePrecision } from "drizzle-orm/pg-core";
import { integer, pgTable, uuid, varchar } from "drizzle-orm/pg-core";
@@ -55,6 +54,9 @@ export const unitsTable = pgTable(
enum: ["reserved", "sold_spa", "available", "sold_registered"],
}).notNull(),
balconyArea: doublePrecision("balcony_area").notNull(),
wing: varchar("wing", {
enum: ["East", "West"],
}),
},
(t) => [unique().on(t.project, t.unitNo)]
);
-3
View File
@@ -1,9 +1,6 @@
import { eq, sql } from "drizzle-orm";
import { Elysia } from "elysia";
import { unitsController } from "./controllers/units";
import { cors } from "@elysiajs/cors";
import { db } from "./db";
import { unitsTable } from "./db/schema";
const app = new Elysia()
.use(cors({ origin: "*" }))