import '../../shared/models/approval_status.dart'; class ExpenseModel { final String id; final String reportNo; final String applicantId; final String applicantName; final String deptId; final String deptName; final String expenseType; final double totalAmount; final int invoiceCount; final String costCenterId; final String costCenterName; final String projectId; final String projectName; final String budgetSubjectId; final String budgetSubjectName; final double loanWriteoffAmount; final String paymentMethod; final String accountBankName; final String accountHolderName; final String accountId; final String accountName; final String remark; final String purpose; final String status; final String currentApproverId; final List approvalChain; final DateTime createTime; final DateTime updateTime; final List attachments; final String paymentStatus; final String voucherNo; final List details; final List approvalRecords; // 财务查验 final bool isInvoiceVerified; final bool isTaxIdMatched; final bool isCategoryCompliant; // 申请来源 final String sourceApplicationId; final double sourceImportAmount; // 发票附件图片 final List invoiceImages; // 数据库字段 final String bankName; final String bankAccount; final String bankTransferNo; final String approvalInstanceId; final DateTime? applicationDate; const ExpenseModel({ required this.id, required this.reportNo, required this.applicantId, required this.applicantName, required this.deptId, required this.deptName, required this.expenseType, required this.totalAmount, this.invoiceCount = 0, this.costCenterId = '', this.costCenterName = '', this.projectId = '', this.projectName = '', this.budgetSubjectId = '', this.budgetSubjectName = '', this.loanWriteoffAmount = 0.0, this.attachments = const [], this.paymentStatus = 'unpaid', this.voucherNo = '', this.paymentMethod = '', this.accountId = '', this.accountName = '', this.accountBankName = '', this.accountHolderName = '', this.remark = '', this.purpose = '', this.status = 'draft', this.currentApproverId = '', this.approvalChain = const [], required this.createTime, required this.updateTime, this.details = const [], this.approvalRecords = const [], this.isInvoiceVerified = false, this.isTaxIdMatched = false, this.isCategoryCompliant = false, this.sourceApplicationId = '', this.sourceImportAmount = 0.0, this.bankName = '', this.bankAccount = '', this.bankTransferNo = '', this.approvalInstanceId = '', this.applicationDate, this.invoiceImages = const [], }); factory ExpenseModel.fromJson(Map json) { return ExpenseModel( id: json['id'] as String, reportNo: json['reportNo'] as String? ?? '', applicantId: json['applicantId'] as String? ?? '', applicantName: json['applicantName'] as String? ?? '', deptId: json['deptId'] as String? ?? '', deptName: json['deptName'] as String? ?? '', expenseType: json['expenseType'] as String? ?? '', totalAmount: (json['totalAmount'] as num?)?.toDouble() ?? 0.0, invoiceCount: json['invoiceCount'] as int? ?? 0, costCenterId: json['costCenterId'] as String? ?? '', costCenterName: json['costCenterName'] as String? ?? '', projectId: json['projectId'] as String? ?? '', projectName: json['projectName'] as String? ?? '', budgetSubjectId: json['budgetSubjectId'] as String? ?? '', budgetSubjectName: json['budgetSubjectName'] as String? ?? '', loanWriteoffAmount: (json['loanWriteoffAmount'] as num?)?.toDouble() ?? 0.0, attachments: (json['attachments'] as List?) ?.map((e) => e as String) .toList() ?? [], paymentStatus: json['paymentStatus'] as String? ?? 'unpaid', voucherNo: json['voucherNo'] as String? ?? '', paymentMethod: json['paymentMethod'] as String? ?? '', accountId: json['accountId'] as String? ?? '', accountName: json['accountName'] as String? ?? '', accountBankName: json['accountBankName'] as String? ?? '', accountHolderName: json['accountHolderName'] as String? ?? '', remark: json['remark'] as String? ?? '', purpose: json['purpose'] as String? ?? '', status: json['status'] as String? ?? 'draft', currentApproverId: json['currentApproverId'] as String? ?? '', approvalChain: (json['approvalChain'] as List?) ?.map((e) => e as String) .toList() ?? [], createTime: DateTime.parse(json['createTime'] as String), updateTime: DateTime.parse(json['updateTime'] as String), details: (json['details'] as List?) ?.map( (e) => ExpenseDetailModel.fromJson(e as Map), ) .toList() ?? [], approvalRecords: (json['approvalRecords'] as List?) ?.map((e) => ApprovalRecord.fromJson(e as Map)) .toList() ?? [], isInvoiceVerified: json['isInvoiceVerified'] as bool? ?? false, isTaxIdMatched: json['isTaxIdMatched'] as bool? ?? false, isCategoryCompliant: json['isCategoryCompliant'] as bool? ?? false, sourceApplicationId: json['sourceApplicationId'] as String? ?? '', sourceImportAmount: (json['sourceImportAmount'] as num?)?.toDouble() ?? 0.0, bankName: json['bankName'] as String? ?? '', bankAccount: json['bankAccount'] as String? ?? '', bankTransferNo: json['bankTransferNo'] as String? ?? '', approvalInstanceId: json['approvalInstanceId'] as String? ?? '', applicationDate: json['applicationDate'] != null ? DateTime.parse(json['applicationDate'] as String) : null, invoiceImages: (json['invoiceImages'] as List?) ?.map((e) => e as String) .toList() ?? [], ); } Map toJson() => { 'id': id, 'reportNo': reportNo, 'applicantId': applicantId, 'applicantName': applicantName, 'deptId': deptId, 'deptName': deptName, 'expenseType': expenseType, 'totalAmount': totalAmount, 'invoiceCount': invoiceCount, 'costCenterId': costCenterId, 'costCenterName': costCenterName, 'projectId': projectId, 'projectName': projectName, 'budgetSubjectId': budgetSubjectId, 'budgetSubjectName': budgetSubjectName, 'loanWriteoffAmount': loanWriteoffAmount, 'attachments': attachments, 'paymentStatus': paymentStatus, 'voucherNo': voucherNo, 'paymentMethod': paymentMethod, 'accountId': accountId, 'accountName': accountName, 'accountBankName': accountBankName, 'accountHolderName': accountHolderName, 'remark': remark, 'purpose': purpose, 'status': status, 'currentApproverId': currentApproverId, 'approvalChain': approvalChain, 'createTime': createTime.toIso8601String(), 'updateTime': updateTime.toIso8601String(), 'details': details.map((d) => d.toJson()).toList(), 'approvalRecords': approvalRecords.map((r) => r.toJson()).toList(), 'isInvoiceVerified': isInvoiceVerified, 'isTaxIdMatched': isTaxIdMatched, 'isCategoryCompliant': isCategoryCompliant, 'sourceApplicationId': sourceApplicationId, 'sourceImportAmount': sourceImportAmount, 'bankName': bankName, 'bankAccount': bankAccount, 'bankTransferNo': bankTransferNo, 'approvalInstanceId': approvalInstanceId, 'applicationDate': applicationDate?.toIso8601String(), 'invoiceImages': invoiceImages, }; ExpenseModel copyWith({ String? id, String? reportNo, String? applicantId, String? applicantName, String? deptId, String? deptName, String? expenseType, double? totalAmount, int? invoiceCount, String? costCenterId, String? costCenterName, String? projectId, String? projectName, String? budgetSubjectId, String? budgetSubjectName, double? loanWriteoffAmount, List? attachments, String? paymentStatus, String? voucherNo, String? paymentMethod, String? accountId, String? accountName, String? accountBankName, String? accountHolderName, String? remark, String? purpose, String? status, String? currentApproverId, List? approvalChain, DateTime? createTime, DateTime? updateTime, List? details, List? approvalRecords, bool? isInvoiceVerified, bool? isTaxIdMatched, bool? isCategoryCompliant, String? sourceApplicationId, double? sourceImportAmount, String? bankName, String? bankAccount, String? bankTransferNo, String? approvalInstanceId, DateTime? applicationDate, List? invoiceImages, }) { return ExpenseModel( id: id ?? this.id, reportNo: reportNo ?? this.reportNo, applicantId: applicantId ?? this.applicantId, applicantName: applicantName ?? this.applicantName, deptId: deptId ?? this.deptId, deptName: deptName ?? this.deptName, expenseType: expenseType ?? this.expenseType, totalAmount: totalAmount ?? this.totalAmount, invoiceCount: invoiceCount ?? this.invoiceCount, costCenterId: costCenterId ?? this.costCenterId, costCenterName: costCenterName ?? this.costCenterName, projectId: projectId ?? this.projectId, projectName: projectName ?? this.projectName, budgetSubjectId: budgetSubjectId ?? this.budgetSubjectId, budgetSubjectName: budgetSubjectName ?? this.budgetSubjectName, loanWriteoffAmount: loanWriteoffAmount ?? this.loanWriteoffAmount, attachments: attachments ?? this.attachments, paymentStatus: paymentStatus ?? this.paymentStatus, voucherNo: voucherNo ?? this.voucherNo, paymentMethod: paymentMethod ?? this.paymentMethod, accountId: accountId ?? this.accountId, accountName: accountName ?? this.accountName, accountBankName: accountBankName ?? this.accountBankName, accountHolderName: accountHolderName ?? this.accountHolderName, remark: remark ?? this.remark, purpose: purpose ?? this.purpose, status: status ?? this.status, currentApproverId: currentApproverId ?? this.currentApproverId, approvalChain: approvalChain ?? this.approvalChain, createTime: createTime ?? this.createTime, updateTime: updateTime ?? this.updateTime, details: details ?? this.details, approvalRecords: approvalRecords ?? this.approvalRecords, isInvoiceVerified: isInvoiceVerified ?? this.isInvoiceVerified, isTaxIdMatched: isTaxIdMatched ?? this.isTaxIdMatched, isCategoryCompliant: isCategoryCompliant ?? this.isCategoryCompliant, sourceApplicationId: sourceApplicationId ?? this.sourceApplicationId, sourceImportAmount: sourceImportAmount ?? this.sourceImportAmount, bankName: bankName ?? this.bankName, bankAccount: bankAccount ?? this.bankAccount, bankTransferNo: bankTransferNo ?? this.bankTransferNo, approvalInstanceId: approvalInstanceId ?? this.approvalInstanceId, applicationDate: applicationDate ?? this.applicationDate, invoiceImages: invoiceImages ?? this.invoiceImages, ); } } class ExpenseDetailModel { final String id; final String expenseId; final DateTime expenseDate; final String expenseType; final String expenseDesc; final double amount; final double taxAmount; final double totalAmount; final double baseAmount; final String currency; final double exchangeRate; final String invoiceNo; final String invoiceCode; final String invoiceType; final bool isDeductible; final double taxRate; final String remark; final List attachments; final int sortOrder; const ExpenseDetailModel({ required this.id, required this.expenseId, required this.expenseDate, required this.expenseType, required this.expenseDesc, required this.amount, this.taxAmount = 0.0, required this.totalAmount, this.baseAmount = 0.0, this.currency = 'CNY', this.exchangeRate = 1.0, this.invoiceNo = '', this.invoiceCode = '', this.invoiceType = '', this.isDeductible = false, this.taxRate = 0.0, this.remark = '', this.attachments = const [], this.sortOrder = 1, }); factory ExpenseDetailModel.fromJson(Map json) { return ExpenseDetailModel( id: json['id'] as String, expenseId: json['expenseId'] as String? ?? '', expenseDate: DateTime.parse(json['expenseDate'] as String), expenseType: json['expenseType'] as String? ?? '', expenseDesc: json['expenseDesc'] as String? ?? '', amount: (json['amount'] as num?)?.toDouble() ?? 0.0, taxAmount: (json['taxAmount'] as num?)?.toDouble() ?? 0.0, totalAmount: (json['totalAmount'] as num?)?.toDouble() ?? 0.0, baseAmount: (json['baseAmount'] as num?)?.toDouble() ?? 0.0, currency: json['currency'] as String? ?? 'CNY', exchangeRate: (json['exchangeRate'] as num?)?.toDouble() ?? 1.0, invoiceNo: json['invoiceNo'] as String? ?? '', invoiceCode: json['invoiceCode'] as String? ?? '', invoiceType: json['invoiceType'] as String? ?? '', isDeductible: json['isDeductible'] as bool? ?? false, taxRate: (json['taxRate'] as num?)?.toDouble() ?? 0.0, remark: json['remark'] as String? ?? '', attachments: (json['attachments'] as List?) ?.map((e) => e as String) .toList() ?? [], sortOrder: json['sortOrder'] as int? ?? 1, ); } Map toJson() => { 'id': id, 'expenseId': expenseId, 'expenseDate': expenseDate.toIso8601String(), 'expenseType': expenseType, 'expenseDesc': expenseDesc, 'amount': amount, 'taxAmount': taxAmount, 'totalAmount': totalAmount, 'baseAmount': baseAmount, 'currency': currency, 'exchangeRate': exchangeRate, 'invoiceNo': invoiceNo, 'invoiceCode': invoiceCode, 'invoiceType': invoiceType, 'isDeductible': isDeductible, 'taxRate': taxRate, 'remark': remark, 'attachments': attachments, 'sortOrder': sortOrder, }; }