Files
trackgo-be/src/database/cycles-table.ts
T
shancheas c9f9b31abf Add field management module with database schema and validation
- Introduced `FieldModule` to manage cycles and plans, including read and write controllers.
- Created database migrations for `company_settings`, `cycles`, `cycle_weekdays`, `cycle_destinations`, `plans`, `plan_destinations`, `plan_invoices`, and `plan_packing_slips` tables, including constraints and unique indexes.
- Developed service and repository layers for handling cycle and plan data operations.
- Added unit tests for the cycles and plans services, repositories, and controllers to ensure functionality and correctness.
- Updated application module to include the new `FieldModule` for better organization.
2026-08-25 18:20:19 +07:00

84 lines
2.6 KiB
TypeScript

import { sql } from 'drizzle-orm';
import {
index,
integer,
jsonb,
pgTable,
text,
uniqueIndex,
uuid,
} from 'drizzle-orm/pg-core';
import { branches } from './branches-table';
import { customers } from './customers-table';
import { employees } from './employees-table';
import { primaryEntityColumns } from './primary-entity-columns';
import { users } from './schema';
export type StoredRouteGeometry = {
readonly type: 'LineString';
readonly coordinates: readonly (readonly [number, number])[];
};
export const cycles = pgTable(
'cycles',
{
id: uuid('id').defaultRandom().notNull().primaryKey(),
employeeId: uuid('employee_id')
.notNull()
.references(() => employees.id, { onDelete: 'restrict' }),
purpose: text('purpose').notNull(),
cycleNumber: integer('cycle_number').notNull(),
...primaryEntityColumns(users),
},
(t) => [
uniqueIndex('cycles_employee_purpose_number_live_unique')
.on(t.employeeId, t.purpose, t.cycleNumber)
.where(sql`${t.status} <> 'archived'`),
index('cycles_employee_id_idx').on(t.employeeId),
],
);
export const cycleWeekdays = pgTable(
'cycle_weekdays',
{
id: uuid('id').defaultRandom().notNull().primaryKey(),
cycleId: uuid('cycle_id')
.notNull()
.references(() => cycles.id, { onDelete: 'cascade' }),
weekday: text('weekday').notNull(),
startBranchId: uuid('start_branch_id')
.notNull()
.references(() => branches.id, { onDelete: 'restrict' }),
endBranchId: uuid('end_branch_id')
.notNull()
.references(() => branches.id, { onDelete: 'restrict' }),
routeGeometry: jsonb('route_geometry')
.$type<StoredRouteGeometry>()
.notNull(),
},
(t) => [
uniqueIndex('cycle_weekdays_cycle_weekday_unique').on(t.cycleId, t.weekday),
index('cycle_weekdays_cycle_id_idx').on(t.cycleId),
],
);
export const cycleDestinations = pgTable(
'cycle_destinations',
{
id: uuid('id').defaultRandom().notNull().primaryKey(),
cycleWeekdayId: uuid('cycle_weekday_id')
.notNull()
.references(() => cycleWeekdays.id, { onDelete: 'cascade' }),
customerId: uuid('customer_id')
.notNull()
.references(() => customers.id, { onDelete: 'restrict' }),
sortOrder: integer('sort_order').notNull(),
},
(t) => [index('cycle_destinations_weekday_id_idx').on(t.cycleWeekdayId)],
);
export type CycleRow = typeof cycles.$inferSelect;
export type NewCycleRow = typeof cycles.$inferInsert;
export type CycleWeekdayRow = typeof cycleWeekdays.$inferSelect;
export type CycleDestinationRow = typeof cycleDestinations.$inferSelect;