Files
jiu/client/lib/models/stock_in.dart
T

170 lines
6.0 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
class StockInItem {
final int? id;
final int? orderId;
final int productId;
final double quantity;
final double costPrice; // 进价(单瓶)
final double costAmount; // 总进价 = quantity × costPrice
final double returnedQuantity; // 0=未退;>=quantity 表示整行已退单
final String? batchNo;
final String? productionDate;
/// 该明细是否已退单(整行已退)。
bool get isReturned => returnedQuantity >= quantity && quantity > 0;
// Denormalized for display
final String? productName;
final String? productCode;
final String? productSeries;
final String? productSpec;
final String? productUnit;
final String? productOrigin;
final String? productShelfLife;
final String? productStorage;
const StockInItem({
this.id,
this.orderId,
required this.productId,
required this.quantity,
required this.costPrice,
required this.costAmount,
this.returnedQuantity = 0,
this.batchNo,
this.productionDate,
this.productName,
this.productCode,
this.productSeries,
this.productSpec,
this.productUnit,
this.productOrigin,
this.productShelfLife,
this.productStorage,
});
factory StockInItem.fromJson(Map<String, dynamic> json) {
final product = json['product'] as Map<String, dynamic>?;
// 历史导入行 product_id=0、无 product 关联,商品信息存在明细行自身列上。
// 优先取明细行快照列,回退到 product 关联(App 新建单据走 product)。
String? lineOrProduct(String lineKey, String productKey) {
final line = json[lineKey] as String?;
if (line != null && line.isNotEmpty) return line;
return product?[productKey] as String?;
}
return StockInItem(
id: json['id'] != null ? (json['id'] as num).toInt() : null,
orderId:
json['order_id'] != null ? (json['order_id'] as num).toInt() : null,
productId: (json['product_id'] as num).toInt(),
quantity: (json['quantity'] as num).toDouble(),
costPrice: (json['cost_price'] as num?)?.toDouble() ?? 0,
costAmount: (json['cost_amount'] as num?)?.toDouble() ?? 0,
returnedQuantity: (json['returned_quantity'] as num?)?.toDouble() ?? 0,
// 批次号/生产日期:优先明细行快照,回退 product 关联(对齐 stock_out.dart 写法)
batchNo: lineOrProduct('batch_no', 'batch_no'),
productionDate: lineOrProduct('production_date', 'production_date'),
productName: lineOrProduct('product_name', 'name'),
productCode: lineOrProduct('product_code', 'code'),
productSeries: lineOrProduct('series', 'series'),
productSpec: lineOrProduct('spec', 'spec'),
productUnit:
(json['product'] as Map<String, dynamic>?)?['unit'] as String?,
productOrigin: ((json['product'] as Map<String, dynamic>?)?['origin']
as Map<String, dynamic>?)?['name'] as String?,
productShelfLife:
((json['product'] as Map<String, dynamic>?)?['shelf_life']
as Map<String, dynamic>?)?['name'] as String?,
productStorage: ((json['product'] as Map<String, dynamic>?)?['storage']
as Map<String, dynamic>?)?['name'] as String?,
);
}
Map<String, dynamic> toJson() => {
'product_id': productId,
'quantity': quantity,
'cost_price': costPrice,
'cost_amount': costAmount,
if (batchNo != null) 'batch_no': batchNo,
if (productionDate != null) 'production_date': productionDate,
};
}
class StockInOrder {
final int id;
final String orderNo;
final String? type;
final int warehouseId;
final String? warehouseName;
final int? partnerId;
final String? partnerName;
final int? operatorId;
final String? operatorName;
final int? reviewerId;
final String? reviewerName;
final String status; // draft | pending | approved | rejected
final String returnState; // none | partial | full(退单状态)
final String? orderDate;
final String? reviewedAt;
final double? costTotal; // 应付合计 = Σ 总进价
final String? remark;
final List<StockInItem> items;
const StockInOrder({
required this.id,
required this.orderNo,
this.type,
required this.warehouseId,
this.warehouseName,
this.partnerId,
this.partnerName,
this.operatorId,
this.operatorName,
this.reviewerId,
this.reviewerName,
required this.status,
this.returnState = 'none',
this.orderDate,
this.reviewedAt,
this.costTotal,
this.remark,
this.items = const [],
});
factory StockInOrder.fromJson(Map<String, dynamic> json) => StockInOrder(
id: (json['id'] as num).toInt(),
orderNo: json['order_no'] as String,
type: json['type'] as String?,
warehouseId: (json['warehouse_id'] as num).toInt(),
warehouseName:
(json['warehouse'] as Map<String, dynamic>?)?['name'] as String?,
partnerId: json['partner_id'] != null
? (json['partner_id'] as num).toInt()
: null,
partnerName:
(json['partner'] as Map<String, dynamic>?)?['name'] as String?,
operatorId: json['operator_id'] != null
? (json['operator_id'] as num).toInt()
: null,
operatorName: (json['operator'] as Map<String, dynamic>?)?['real_name']
as String?,
reviewerId: json['reviewer_id'] != null
? (json['reviewer_id'] as num).toInt()
: null,
reviewerName: (json['reviewer'] as Map<String, dynamic>?)?['real_name']
as String?,
status: json['status'] as String,
returnState: json['return_state'] as String? ?? 'none',
orderDate: json['order_date'] as String?,
reviewedAt: json['reviewed_at'] as String?,
costTotal: json['cost_total'] != null
? (json['cost_total'] as num).toDouble()
: null,
remark: json['remark'] as String?,
items: json['items'] != null
? (json['items'] as List)
.map((e) => StockInItem.fromJson(e as Map<String, dynamic>))
.toList()
: [],
);
}