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.
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user