Add timeline tracking features with database schema updates
- Introduced new tables `timeline_footprints` and `timeline_activities` to manage employee location data and activity records. - Updated `company_settings` to include `gps_interval_seconds` and `checkout_warning_radius_meters` for enhanced tracking configuration. - Implemented foreign key constraints to ensure data integrity between new tables and existing `employees`, `customers`, and `visits` tables. - Created services and controllers for handling timeline activities and footprints, including ingestion and retrieval of data. - Enhanced DTOs and validation logic to support new fields and ensure correct data formats in API requests. - Added unit and integration tests to validate the new functionalities and ensure proper handling of timeline records. - Created migration scripts to apply the necessary database schema changes for the new features.
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import {
|
||||
bigint,
|
||||
doublePrecision,
|
||||
index,
|
||||
pgTable,
|
||||
text,
|
||||
uuid,
|
||||
} from 'drizzle-orm/pg-core';
|
||||
import { customers } from './customers-table';
|
||||
import { employees } from './employees-table';
|
||||
import { visits } from './visits-table';
|
||||
|
||||
export const TIMELINE_ACTIVITY_TYPES = [
|
||||
'branch_check_in',
|
||||
'branch_check_out',
|
||||
'customer_check_in',
|
||||
'customer_check_out',
|
||||
'sales_order_created',
|
||||
'sales_request_created',
|
||||
'sales_payment_created',
|
||||
'customer_created',
|
||||
] as const;
|
||||
|
||||
export type TimelineActivityType = (typeof TIMELINE_ACTIVITY_TYPES)[number];
|
||||
|
||||
export const timelineActivities = pgTable(
|
||||
'timeline_activities',
|
||||
{
|
||||
id: uuid('id').defaultRandom().notNull().primaryKey(),
|
||||
employeeId: uuid('employee_id')
|
||||
.notNull()
|
||||
.references(() => employees.id, { onDelete: 'restrict' }),
|
||||
customerId: uuid('customer_id').references(() => customers.id, {
|
||||
onDelete: 'set null',
|
||||
}),
|
||||
visitId: uuid('visit_id').references(() => visits.id, {
|
||||
onDelete: 'set null',
|
||||
}),
|
||||
type: text('type').notNull(),
|
||||
sourceType: text('source_type').notNull(),
|
||||
sourceId: uuid('source_id').notNull(),
|
||||
latitude: doublePrecision('latitude').notNull(),
|
||||
longitude: doublePrecision('longitude').notNull(),
|
||||
recordedAt: bigint('recorded_at', { mode: 'number' }).notNull(),
|
||||
},
|
||||
(t) => [
|
||||
index('timeline_activities_employee_recorded_idx').on(
|
||||
t.employeeId,
|
||||
t.recordedAt,
|
||||
),
|
||||
index('timeline_activities_visit_id_idx').on(t.visitId),
|
||||
],
|
||||
);
|
||||
|
||||
export type TimelineActivityRow = typeof timelineActivities.$inferSelect;
|
||||
export type NewTimelineActivityRow = typeof timelineActivities.$inferInsert;
|
||||
Reference in New Issue
Block a user