Complete implementation of the Assets/Machinery/Maintenance module: Entities (10): - AssetCategory: Hierarchical asset categorization with depreciation config - Asset: Main asset entity (machinery, vehicles, tools, equipment) - AssetAssignment: Asset-to-project assignments tracking - WorkOrder: Maintenance work orders with workflow - WorkOrderPart: Parts/materials used in work orders - MaintenancePlan: Preventive maintenance plans - MaintenanceHistory: Historical maintenance records - FuelLog: Fuel consumption tracking with efficiency calculation - AssetCost: TCO (Total Cost of Ownership) tracking Services (3): - AssetService: CRUD, assignments, categories, statistics - WorkOrderService: CRUD, workflow (start/hold/resume/complete/cancel), parts - FuelLogService: CRUD, efficiency calculation, statistics Controllers (3): - AssetController: REST API for assets, assignments, categories - WorkOrderController: REST API for work orders, workflow, plans - FuelLogController: REST API for fuel logs, statistics Features: - Multi-tenant support with tenant_id - Complete workflow for work orders (draft→scheduled→in_progress→completed) - Automatic efficiency calculation for fuel consumption - Asset assignment history tracking - Maintenance plan generation - TCO tracking by cost type Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
133 lines
3.2 KiB
TypeScript
133 lines
3.2 KiB
TypeScript
/**
|
|
* AssetCost Entity - Costos de Activos (TCO)
|
|
*
|
|
* Registro de costos para calculo de TCO (Total Cost of Ownership).
|
|
*
|
|
* @module Assets (MAE-015)
|
|
*/
|
|
|
|
import {
|
|
Entity,
|
|
PrimaryGeneratedColumn,
|
|
Column,
|
|
CreateDateColumn,
|
|
UpdateDateColumn,
|
|
ManyToOne,
|
|
JoinColumn,
|
|
Index,
|
|
} from 'typeorm';
|
|
import { Asset } from './asset.entity';
|
|
|
|
export type CostType =
|
|
| 'maintenance'
|
|
| 'repair'
|
|
| 'fuel'
|
|
| 'insurance'
|
|
| 'tax'
|
|
| 'depreciation'
|
|
| 'operator'
|
|
| 'other';
|
|
|
|
@Entity('asset_costs', { schema: 'assets' })
|
|
@Index(['tenantId', 'assetId'])
|
|
@Index(['tenantId', 'periodStart', 'periodEnd'])
|
|
@Index(['tenantId', 'costType'])
|
|
@Index(['tenantId', 'projectId'])
|
|
export class AssetCost {
|
|
@PrimaryGeneratedColumn('uuid')
|
|
id!: string;
|
|
|
|
@Column({ name: 'tenant_id', type: 'uuid' })
|
|
@Index()
|
|
tenantId!: string;
|
|
|
|
// Activo
|
|
@Column({ name: 'asset_id', type: 'uuid' })
|
|
assetId!: string;
|
|
|
|
@ManyToOne(() => Asset)
|
|
@JoinColumn({ name: 'asset_id' })
|
|
asset!: Asset;
|
|
|
|
// Periodo
|
|
@Column({ name: 'period_start', type: 'date' })
|
|
periodStart!: Date;
|
|
|
|
@Column({ name: 'period_end', type: 'date' })
|
|
periodEnd!: Date;
|
|
|
|
@Column({ name: 'fiscal_year', type: 'int' })
|
|
fiscalYear!: number;
|
|
|
|
@Column({ name: 'fiscal_month', type: 'int' })
|
|
fiscalMonth!: number;
|
|
|
|
// Proyecto (si aplica)
|
|
@Column({ name: 'project_id', type: 'uuid', nullable: true })
|
|
projectId?: string;
|
|
|
|
@Column({ name: 'project_code', length: 50, nullable: true })
|
|
projectCode?: string;
|
|
|
|
// Tipo de costo
|
|
@Column({
|
|
name: 'cost_type',
|
|
type: 'enum',
|
|
enum: ['maintenance', 'repair', 'fuel', 'insurance', 'tax', 'depreciation', 'operator', 'other'],
|
|
enumName: 'cost_type',
|
|
})
|
|
costType!: CostType;
|
|
|
|
// Descripcion
|
|
@Column({ length: 255, nullable: true })
|
|
description?: string;
|
|
|
|
@Column({ name: 'reference_document', length: 100, nullable: true })
|
|
referenceDocument?: string;
|
|
|
|
// Monto
|
|
@Column({ type: 'decimal', precision: 18, scale: 2 })
|
|
amount!: number;
|
|
|
|
@Column({ length: 3, default: 'MXN' })
|
|
currency!: string;
|
|
|
|
// Uso asociado
|
|
@Column({ name: 'hours_in_period', type: 'decimal', precision: 12, scale: 2, nullable: true })
|
|
hoursInPeriod?: number;
|
|
|
|
@Column({ name: 'kilometers_in_period', type: 'decimal', precision: 12, scale: 2, nullable: true })
|
|
kilometersInPeriod?: number;
|
|
|
|
// Calculo de tarifa
|
|
@Column({ name: 'cost_per_hour', type: 'decimal', precision: 18, scale: 4, nullable: true })
|
|
costPerHour?: number;
|
|
|
|
@Column({ name: 'cost_per_kilometer', type: 'decimal', precision: 18, scale: 4, nullable: true })
|
|
costPerKilometer?: number;
|
|
|
|
// Origen
|
|
@Column({ name: 'source_module', length: 50, nullable: true })
|
|
sourceModule?: string;
|
|
|
|
@Column({ name: 'source_id', type: 'uuid', nullable: true })
|
|
sourceId?: string;
|
|
|
|
// Notas
|
|
@Column({ type: 'text', nullable: true })
|
|
notes?: string;
|
|
|
|
@Column({ type: 'jsonb', nullable: true })
|
|
metadata?: Record<string, any>;
|
|
|
|
// Auditoria
|
|
@Column({ name: 'created_by', type: 'uuid', nullable: true })
|
|
createdBy?: string;
|
|
|
|
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
|
|
createdAt!: Date;
|
|
|
|
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
|
|
updatedAt!: Date;
|
|
}
|