- Add 11 entities: ServiceChecklist, ChecklistItemTemplate, ChecklistResponse, ChecklistItemResponse, WorkLog, DiagnosisRecord, ActivityCatalog, RootCauseCatalog, FieldEvidence, FieldCheckin, OfflineQueueItem - Add 5 services: ChecklistService, WorkLogService, DiagnosisService, OfflineSyncService, CheckinService - Add 5 controllers: ChecklistController, WorkLogController, DiagnosisController, SyncController, CheckinController - Integrate module in main.ts with routes under /api/v1/field/* Features: - Configurable checklists with multiple item types - Labor time tracking with pause/resume - Diagnosis with OBD-II code parsing - Offline sync queue with conflict resolution - Technician check-in/check-out with geolocation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
142 lines
3.7 KiB
TypeScript
142 lines
3.7 KiB
TypeScript
/**
|
|
* DiagnosisRecord Entity
|
|
* Mecanicas Diesel - ERP Suite
|
|
*
|
|
* Diagnosis and root cause records.
|
|
* Module: MMD-012 Field Service
|
|
*/
|
|
|
|
import {
|
|
Entity,
|
|
PrimaryGeneratedColumn,
|
|
Column,
|
|
CreateDateColumn,
|
|
UpdateDateColumn,
|
|
Index,
|
|
} from 'typeorm';
|
|
|
|
export enum DiagnosisType {
|
|
VISUAL = 'VISUAL',
|
|
OBD = 'OBD',
|
|
ELECTRONIC = 'ELECTRONIC',
|
|
MECHANICAL = 'MECHANICAL',
|
|
}
|
|
|
|
export enum DiagnosisSeverity {
|
|
LOW = 'LOW',
|
|
MEDIUM = 'MEDIUM',
|
|
HIGH = 'HIGH',
|
|
CRITICAL = 'CRITICAL',
|
|
}
|
|
|
|
@Entity({ name: 'diagnosis_records', schema: 'field_service' })
|
|
@Index('idx_diagnosis_tenant', ['tenantId'])
|
|
@Index('idx_diagnosis_incident', ['tenantId', 'incidentId'])
|
|
@Index('idx_diagnosis_vehicle', ['tenantId', 'vehicleId'])
|
|
@Index('idx_diagnosis_technician', ['tenantId', 'technicianId'])
|
|
export class DiagnosisRecord {
|
|
@PrimaryGeneratedColumn('uuid')
|
|
id: string;
|
|
|
|
@Column({ name: 'tenant_id', type: 'uuid' })
|
|
tenantId: string;
|
|
|
|
@Column({ name: 'incident_id', type: 'uuid', nullable: true })
|
|
incidentId?: string;
|
|
|
|
@Column({ name: 'service_order_id', type: 'uuid', nullable: true })
|
|
serviceOrderId?: string;
|
|
|
|
@Column({ name: 'vehicle_id', type: 'uuid', nullable: true })
|
|
vehicleId?: string;
|
|
|
|
@Column({ name: 'technician_id', type: 'uuid' })
|
|
technicianId: string;
|
|
|
|
// Diagnosis type
|
|
@Column({
|
|
name: 'diagnosis_type',
|
|
type: 'varchar',
|
|
length: 20,
|
|
default: DiagnosisType.VISUAL,
|
|
})
|
|
diagnosisType: DiagnosisType;
|
|
|
|
// Symptoms
|
|
@Column({ type: 'text' })
|
|
symptoms: string;
|
|
|
|
@Column({ name: 'customer_complaint', type: 'text', nullable: true })
|
|
customerComplaint?: string;
|
|
|
|
// Root cause
|
|
@Column({ name: 'root_cause_code', type: 'varchar', length: 50, nullable: true })
|
|
rootCauseCode?: string;
|
|
|
|
@Column({ name: 'root_cause_category', type: 'varchar', length: 100, nullable: true })
|
|
rootCauseCategory?: string;
|
|
|
|
@Column({ name: 'root_cause_description', type: 'text', nullable: true })
|
|
rootCauseDescription?: string;
|
|
|
|
// OBD-II codes
|
|
@Column({ name: 'obd2_codes', type: 'jsonb', nullable: true })
|
|
obd2Codes?: string[];
|
|
|
|
@Column({ name: 'obd2_raw_data', type: 'jsonb', nullable: true })
|
|
obd2RawData?: Record<string, any>;
|
|
|
|
// Readings
|
|
@Column({ name: 'odometer_reading', type: 'decimal', precision: 12, scale: 2, nullable: true })
|
|
odometerReading?: number;
|
|
|
|
@Column({ name: 'engine_hours', type: 'decimal', precision: 10, scale: 2, nullable: true })
|
|
engineHours?: number;
|
|
|
|
@Column({ name: 'fuel_level', type: 'integer', nullable: true })
|
|
fuelLevel?: number;
|
|
|
|
// Recommendation
|
|
@Column({ type: 'text', nullable: true })
|
|
recommendation?: string;
|
|
|
|
@Column({ type: 'varchar', length: 20, nullable: true })
|
|
severity?: DiagnosisSeverity;
|
|
|
|
@Column({ name: 'requires_immediate_action', type: 'boolean', default: false })
|
|
requiresImmediateAction: boolean;
|
|
|
|
// Evidence
|
|
@Column({ name: 'photo_urls', type: 'jsonb', nullable: true })
|
|
photoUrls?: string[];
|
|
|
|
@Column({ name: 'video_urls', type: 'jsonb', nullable: true })
|
|
videoUrls?: string[];
|
|
|
|
// Location
|
|
@Column({ type: 'decimal', precision: 10, scale: 7, nullable: true })
|
|
latitude?: number;
|
|
|
|
@Column({ type: 'decimal', precision: 10, scale: 7, nullable: true })
|
|
longitude?: number;
|
|
|
|
// Offline
|
|
@Column({ name: 'is_offline', type: 'boolean', default: false })
|
|
isOffline: boolean;
|
|
|
|
@Column({ name: 'device_id', type: 'varchar', length: 100, nullable: true })
|
|
deviceId?: string;
|
|
|
|
@Column({ name: 'local_id', type: 'varchar', length: 100, nullable: true })
|
|
localId?: string;
|
|
|
|
@Column({ name: 'synced_at', type: 'timestamptz', nullable: true })
|
|
syncedAt?: Date;
|
|
|
|
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
|
|
createdAt: Date;
|
|
|
|
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
|
|
updatedAt: Date;
|
|
}
|