erp-retail-backend-v2/src/modules/cash/entities/cash-closing.entity.ts
rckrdmrd a6186c4022 Migración desde erp-retail/backend - Estándar multi-repo v2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:11:34 -06:00

206 lines
5.8 KiB
TypeScript

import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
OneToMany,
Index,
} from 'typeorm';
import { CashCount } from './cash-count.entity';
export enum ClosingStatus {
IN_PROGRESS = 'in_progress',
PENDING_REVIEW = 'pending_review',
APPROVED = 'approved',
REJECTED = 'rejected',
RECONCILED = 'reconciled',
}
export enum ClosingType {
SHIFT = 'shift',
DAILY = 'daily',
WEEKLY = 'weekly',
MONTHLY = 'monthly',
}
@Entity('cash_closings', { schema: 'retail' })
@Index(['tenantId', 'branchId', 'closingDate'])
@Index(['tenantId', 'status'])
@Index(['tenantId', 'sessionId'])
export class CashClosing {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ name: 'tenant_id', type: 'uuid' })
@Index()
tenantId: string;
@Column({ name: 'branch_id', type: 'uuid' })
branchId: string;
@Column({ name: 'register_id', type: 'uuid', nullable: true })
registerId: string;
@Column({ name: 'session_id', type: 'uuid', nullable: true })
sessionId: string;
@Column({ length: 30, unique: true })
number: string;
@Column({
type: 'enum',
enum: ClosingType,
default: ClosingType.SHIFT,
})
type: ClosingType;
@Column({
type: 'enum',
enum: ClosingStatus,
default: ClosingStatus.IN_PROGRESS,
})
status: ClosingStatus;
@Column({ name: 'closing_date', type: 'date' })
closingDate: Date;
@Column({ name: 'period_start', type: 'timestamp with time zone' })
periodStart: Date;
@Column({ name: 'period_end', type: 'timestamp with time zone' })
periodEnd: Date;
// Opening balance
@Column({ name: 'opening_balance', type: 'decimal', precision: 15, scale: 2, default: 0 })
openingBalance: number;
// Expected amounts by payment method
@Column({ name: 'expected_cash', type: 'decimal', precision: 15, scale: 2, default: 0 })
expectedCash: number;
@Column({ name: 'expected_card', type: 'decimal', precision: 15, scale: 2, default: 0 })
expectedCard: number;
@Column({ name: 'expected_transfer', type: 'decimal', precision: 15, scale: 2, default: 0 })
expectedTransfer: number;
@Column({ name: 'expected_other', type: 'decimal', precision: 15, scale: 2, default: 0 })
expectedOther: number;
@Column({ name: 'expected_total', type: 'decimal', precision: 15, scale: 2, default: 0 })
expectedTotal: number;
// Counted amounts
@Column({ name: 'counted_cash', type: 'decimal', precision: 15, scale: 2, nullable: true })
countedCash: number;
@Column({ name: 'counted_card', type: 'decimal', precision: 15, scale: 2, nullable: true })
countedCard: number;
@Column({ name: 'counted_transfer', type: 'decimal', precision: 15, scale: 2, nullable: true })
countedTransfer: number;
@Column({ name: 'counted_other', type: 'decimal', precision: 15, scale: 2, nullable: true })
countedOther: number;
@Column({ name: 'counted_total', type: 'decimal', precision: 15, scale: 2, nullable: true })
countedTotal: number;
// Differences
@Column({ name: 'cash_difference', type: 'decimal', precision: 15, scale: 2, nullable: true })
cashDifference: number;
@Column({ name: 'card_difference', type: 'decimal', precision: 15, scale: 2, nullable: true })
cardDifference: number;
@Column({ name: 'total_difference', type: 'decimal', precision: 15, scale: 2, nullable: true })
totalDifference: number;
// Transaction summary
@Column({ name: 'total_sales', type: 'decimal', precision: 15, scale: 2, default: 0 })
totalSales: number;
@Column({ name: 'total_refunds', type: 'decimal', precision: 15, scale: 2, default: 0 })
totalRefunds: number;
@Column({ name: 'total_discounts', type: 'decimal', precision: 15, scale: 2, default: 0 })
totalDiscounts: number;
@Column({ name: 'net_sales', type: 'decimal', precision: 15, scale: 2, default: 0 })
netSales: number;
@Column({ name: 'orders_count', type: 'int', default: 0 })
ordersCount: number;
@Column({ name: 'refunds_count', type: 'int', default: 0 })
refundsCount: number;
@Column({ name: 'voided_count', type: 'int', default: 0 })
voidedCount: number;
// Cash movements
@Column({ name: 'cash_in_total', type: 'decimal', precision: 15, scale: 2, default: 0 })
cashInTotal: number;
@Column({ name: 'cash_out_total', type: 'decimal', precision: 15, scale: 2, default: 0 })
cashOutTotal: number;
// Deposit info
@Column({ name: 'deposit_amount', type: 'decimal', precision: 15, scale: 2, nullable: true })
depositAmount: number;
@Column({ name: 'deposit_reference', length: 100, nullable: true })
depositReference: string;
@Column({ name: 'deposit_date', type: 'date', nullable: true })
depositDate: Date;
// User info
@Column({ name: 'closed_by', type: 'uuid' })
closedBy: string;
@Column({ name: 'reviewed_by', type: 'uuid', nullable: true })
reviewedBy: string;
@Column({ name: 'reviewed_at', type: 'timestamp with time zone', nullable: true })
reviewedAt: Date;
@Column({ name: 'approved_by', type: 'uuid', nullable: true })
approvedBy: string;
@Column({ name: 'approved_at', type: 'timestamp with time zone', nullable: true })
approvedAt: Date;
// Notes
@Column({ name: 'closing_notes', type: 'text', nullable: true })
closingNotes: string;
@Column({ name: 'review_notes', type: 'text', nullable: true })
reviewNotes: string;
// Detailed breakdown by payment method
@Column({ name: 'payment_breakdown', type: 'jsonb', nullable: true })
paymentBreakdown: {
method: string;
expected: number;
counted: number;
difference: number;
transactionCount: number;
}[];
// Metadata
@Column({ type: 'jsonb', nullable: true })
metadata: Record<string, any>;
@CreateDateColumn({ name: 'created_at' })
createdAt: Date;
@UpdateDateColumn({ name: 'updated_at' })
updatedAt: Date;
// Relations
@OneToMany(() => CashCount, (count) => count.closing)
cashCounts: CashCount[];
}