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,111 @@
|
||||
import { sql } from 'drizzle-orm';
|
||||
import {
|
||||
bigint,
|
||||
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 { packingSlips } from './packing-slips-table';
|
||||
import { primaryEntityColumns } from './primary-entity-columns';
|
||||
import { salesInvoices } from './sales-invoices-table';
|
||||
import { users } from './schema';
|
||||
import type { StoredRouteGeometry } from './cycles-table';
|
||||
|
||||
export const plans = pgTable(
|
||||
'plans',
|
||||
{
|
||||
id: uuid('id').defaultRandom().notNull().primaryKey(),
|
||||
employeeId: uuid('employee_id')
|
||||
.notNull()
|
||||
.references(() => employees.id, { onDelete: 'restrict' }),
|
||||
purpose: text('purpose').notNull(),
|
||||
date: bigint('date', { mode: 'number' }).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(),
|
||||
...primaryEntityColumns(users),
|
||||
},
|
||||
(t) => [
|
||||
uniqueIndex('plans_employee_purpose_date_live_unique')
|
||||
.on(t.employeeId, t.purpose, t.date)
|
||||
.where(sql`${t.status} <> 'archived'`),
|
||||
index('plans_employee_id_idx').on(t.employeeId),
|
||||
],
|
||||
);
|
||||
|
||||
export const planDestinations = pgTable(
|
||||
'plan_destinations',
|
||||
{
|
||||
id: uuid('id').defaultRandom().notNull().primaryKey(),
|
||||
planId: uuid('plan_id')
|
||||
.notNull()
|
||||
.references(() => plans.id, { onDelete: 'cascade' }),
|
||||
customerId: uuid('customer_id')
|
||||
.notNull()
|
||||
.references(() => customers.id, { onDelete: 'restrict' }),
|
||||
sortOrder: integer('sort_order').notNull(),
|
||||
},
|
||||
(t) => [
|
||||
uniqueIndex('plan_destinations_plan_customer_unique').on(
|
||||
t.planId,
|
||||
t.customerId,
|
||||
),
|
||||
index('plan_destinations_plan_id_idx').on(t.planId),
|
||||
],
|
||||
);
|
||||
|
||||
export const planInvoices = pgTable(
|
||||
'plan_invoices',
|
||||
{
|
||||
id: uuid('id').defaultRandom().notNull().primaryKey(),
|
||||
planId: uuid('plan_id')
|
||||
.notNull()
|
||||
.references(() => plans.id, { onDelete: 'cascade' }),
|
||||
invoiceId: uuid('invoice_id')
|
||||
.notNull()
|
||||
.references(() => salesInvoices.id, { onDelete: 'restrict' }),
|
||||
},
|
||||
(t) => [
|
||||
uniqueIndex('plan_invoices_plan_invoice_unique').on(t.planId, t.invoiceId),
|
||||
index('plan_invoices_plan_id_idx').on(t.planId),
|
||||
],
|
||||
);
|
||||
|
||||
export const planPackingSlips = pgTable(
|
||||
'plan_packing_slips',
|
||||
{
|
||||
id: uuid('id').defaultRandom().notNull().primaryKey(),
|
||||
planId: uuid('plan_id')
|
||||
.notNull()
|
||||
.references(() => plans.id, { onDelete: 'cascade' }),
|
||||
packingSlipId: uuid('packing_slip_id')
|
||||
.notNull()
|
||||
.references(() => packingSlips.id, { onDelete: 'restrict' }),
|
||||
},
|
||||
(t) => [
|
||||
uniqueIndex('plan_packing_slips_plan_slip_unique').on(
|
||||
t.planId,
|
||||
t.packingSlipId,
|
||||
),
|
||||
index('plan_packing_slips_plan_id_idx').on(t.planId),
|
||||
],
|
||||
);
|
||||
|
||||
export type PlanRow = typeof plans.$inferSelect;
|
||||
export type NewPlanRow = typeof plans.$inferInsert;
|
||||
export type PlanDestinationRow = typeof planDestinations.$inferSelect;
|
||||
export type PlanInvoiceRow = typeof planInvoices.$inferSelect;
|
||||
export type PlanPackingSlipRow = typeof planPackingSlips.$inferSelect;
|
||||
Reference in New Issue
Block a user