Files
edr-platform/apps/edr-freight-api/src/modules/rule-engine/entities/rate-change-request.entity.ts
2026-07-17 10:15:26 +00:00

55 lines
1.9 KiB
TypeScript

import { BaseEntity } from '@edr/api-common';
import { Column, Entity, Index, JoinColumn, ManyToOne } from 'typeorm';
import { Rate } from './rate.entity';
export type RateChangeStatus = 'PENDING' | 'APPROVED' | 'REJECTED';
/**
* One proposed edit to a LIVE rate, awaiting approval.
*
* A LIVE rate is what pricing actually charges, so it is never mutated in
* place: the edit is filed here and the live row keeps its old value until an
* approver applies it. `payload` holds only the changed fields (an
* UpdateRateDto patch), `rateId` the rate being repriced.
*
* DRAFT rates are not covered — nothing prices off a draft, so those still
* edit directly and reach LIVE through the existing submit/approve flow.
*/
@Entity({ schema: 'freight', name: 'rate_change_requests' })
@Index(['status'])
export class RateChangeRequest extends BaseEntity {
@Column({ name: 'rate_id', type: 'uuid' })
rateId!: string;
@ManyToOne(() => Rate, { nullable: false })
@JoinColumn({ name: 'rate_id' })
rate?: Rate | null;
/** Proposed field changes — an UpdateRateDto patch, changed keys only. */
@Column({ name: 'payload', type: 'jsonb' })
payload!: Record<string, unknown>;
/**
* The rate's values at submit time, for the approver's before→after diff.
* Snapshotted because the live row can move on between submit and decision.
*/
@Column({ name: 'previous_values', type: 'jsonb' })
previousValues!: Record<string, unknown>;
@Column({ name: 'status', type: 'varchar', length: 10, default: 'PENDING' })
status!: RateChangeStatus;
@Column({ name: 'requested_by_user_id', type: 'uuid', nullable: true })
requestedByUserId?: string | null;
@Column({ name: 'decided_by_user_id', type: 'uuid', nullable: true })
decidedByUserId?: string | null;
@Column({ name: 'decided_at', type: 'timestamptz', nullable: true })
decidedAt?: Date | null;
@Column({ name: 'decision_note', type: 'text', nullable: true })
decisionNote?: string | null;
}