erp-retail-backend/src/modules/inventory/entities/stock-adjustment.entity.ts

170 lines
4.5 KiB
TypeScript

import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
OneToMany,
Index,
} from 'typeorm';
import { StockAdjustmentLine } from './stock-adjustment-line.entity';
export enum AdjustmentStatus {
DRAFT = 'draft',
PENDING_APPROVAL = 'pending_approval',
APPROVED = 'approved',
POSTED = 'posted',
REJECTED = 'rejected',
CANCELLED = 'cancelled',
}
export enum AdjustmentType {
INVENTORY_COUNT = 'inventory_count',
DAMAGE = 'damage',
THEFT = 'theft',
EXPIRY = 'expiry',
CORRECTION = 'correction',
INITIAL_STOCK = 'initial_stock',
PRODUCTION = 'production',
OTHER = 'other',
}
@Entity('stock_adjustments', { schema: 'retail' })
@Index(['tenantId', 'branchId', 'status'])
@Index(['tenantId', 'adjustmentDate'])
@Index(['tenantId', 'number'], { unique: true })
export class StockAdjustment {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ name: 'tenant_id', type: 'uuid' })
@Index()
tenantId: string;
@Column({ name: 'branch_id', type: 'uuid' })
branchId: string;
@Column({ name: 'warehouse_id', type: 'uuid' })
warehouseId: string;
@Column({ name: 'location_id', type: 'uuid', nullable: true })
locationId: string;
@Column({ length: 30, unique: true })
number: string;
@Column({
type: 'enum',
enum: AdjustmentType,
default: AdjustmentType.INVENTORY_COUNT,
})
type: AdjustmentType;
@Column({
type: 'enum',
enum: AdjustmentStatus,
default: AdjustmentStatus.DRAFT,
})
status: AdjustmentStatus;
@Column({ name: 'adjustment_date', type: 'date' })
adjustmentDate: Date;
// Count info (for inventory counts)
@Column({ name: 'is_full_count', type: 'boolean', default: false })
isFullCount: boolean;
@Column({ name: 'count_category_id', type: 'uuid', nullable: true })
countCategoryId: string;
// Summary
@Column({ name: 'lines_count', type: 'int', default: 0 })
linesCount: number;
@Column({ name: 'total_increase_qty', type: 'decimal', precision: 15, scale: 4, default: 0 })
totalIncreaseQty: number;
@Column({ name: 'total_decrease_qty', type: 'decimal', precision: 15, scale: 4, default: 0 })
totalDecreaseQty: number;
@Column({ name: 'total_increase_value', type: 'decimal', precision: 15, scale: 2, default: 0 })
totalIncreaseValue: number;
@Column({ name: 'total_decrease_value', type: 'decimal', precision: 15, scale: 2, default: 0 })
totalDecreaseValue: number;
@Column({ name: 'net_adjustment_value', type: 'decimal', precision: 15, scale: 2, default: 0 })
netAdjustmentValue: number;
// Financial account (for accounting integration)
@Column({ name: 'account_id', type: 'uuid', nullable: true })
accountId: string;
@Column({ name: 'counterpart_account_id', type: 'uuid', nullable: true })
counterpartAccountId: string;
// Approval workflow
@Column({ name: 'requires_approval', type: 'boolean', default: true })
requiresApproval: boolean;
@Column({ name: 'approval_threshold', type: 'decimal', precision: 15, scale: 2, nullable: true })
approvalThreshold: number;
// Users
@Column({ name: 'created_by', type: 'uuid' })
createdBy: string;
@Column({ name: 'approved_by', type: 'uuid', nullable: true })
approvedBy: string;
@Column({ name: 'approved_at', type: 'timestamp with time zone', nullable: true })
approvedAt: Date;
@Column({ name: 'posted_by', type: 'uuid', nullable: true })
postedBy: string;
@Column({ name: 'posted_at', type: 'timestamp with time zone', nullable: true })
postedAt: Date;
@Column({ name: 'rejected_by', type: 'uuid', nullable: true })
rejectedBy: string;
@Column({ name: 'rejected_at', type: 'timestamp with time zone', nullable: true })
rejectedAt: Date;
@Column({ name: 'rejection_reason', length: 255, nullable: true })
rejectionReason: string;
// Reason/Description
@Column({ type: 'text' })
reason: string;
// Reference
@Column({ name: 'reference_type', length: 50, nullable: true })
referenceType: string;
@Column({ name: 'reference_id', type: 'uuid', nullable: true })
referenceId: string;
@Column({ name: 'reference_number', length: 50, nullable: true })
referenceNumber: string;
// Notes
@Column({ type: 'text', nullable: true })
notes: string;
// Metadata
@Column({ type: 'jsonb', nullable: true })
metadata: Record<string, any>;
@CreateDateColumn({ name: 'created_at' })
createdAt: Date;
@UpdateDateColumn({ name: 'updated_at' })
updatedAt: Date;
// Relations
@OneToMany(() => StockAdjustmentLine, (line) => line.adjustment)
lines: StockAdjustmentLine[];
}