import 'package:collection/collection.dart'; /// 受注ステータスの定義。 enum SalesOrderStatus { draft, confirmed, picking, shipped, closed, cancelled, } extension SalesOrderStatusX on SalesOrderStatus { String get displayName { switch (this) { case SalesOrderStatus.draft: return '下書き'; case SalesOrderStatus.confirmed: return '確定'; case SalesOrderStatus.picking: return '出荷準備中'; case SalesOrderStatus.shipped: return '出荷済み'; case SalesOrderStatus.closed: return '完了'; case SalesOrderStatus.cancelled: return 'キャンセル'; } } static SalesOrderStatus fromDbValue(String? value) { return SalesOrderStatus.values.firstWhere( (status) => status.name == value, orElse: () => SalesOrderStatus.draft, ); } } class SalesOrderItem { SalesOrderItem({ required this.id, required this.orderId, required this.description, required this.quantity, required this.unitPrice, this.productId, this.taxRate = 0, this.sortIndex = 0, }); final String id; final String orderId; final String? productId; final String description; final int quantity; final int unitPrice; final double taxRate; final int sortIndex; int get lineTotal => quantity * unitPrice; Map toMap() => { 'id': id, 'order_id': orderId, 'product_id': productId, 'description': description, 'quantity': quantity, 'unit_price': unitPrice, 'tax_rate': taxRate, 'sort_index': sortIndex, }; factory SalesOrderItem.fromMap(Map map) => SalesOrderItem( id: map['id'] as String, orderId: map['order_id'] as String, productId: map['product_id'] as String?, description: map['description'] as String, quantity: map['quantity'] as int, unitPrice: map['unit_price'] as int, taxRate: (map['tax_rate'] as num?)?.toDouble() ?? 0, sortIndex: map['sort_index'] as int? ?? 0, ); } class SalesOrder { SalesOrder({ required this.id, required this.customerId, required this.orderDate, required this.status, required this.subtotal, required this.taxAmount, required this.totalAmount, required this.createdAt, required this.updatedAt, this.orderNumber, this.customerNameSnapshot, this.requestedShipDate, this.notes, this.assignedTo, this.workflowStage, this.items = const [], }); final String id; final String customerId; final String? customerNameSnapshot; final DateTime orderDate; final DateTime? requestedShipDate; final SalesOrderStatus status; final int subtotal; final int taxAmount; final int totalAmount; final String? orderNumber; final String? notes; final String? assignedTo; final String? workflowStage; final DateTime createdAt; final DateTime updatedAt; final List items; SalesOrder copyWith({ String? id, String? customerId, String? customerNameSnapshot, DateTime? orderDate, DateTime? requestedShipDate, SalesOrderStatus? status, int? subtotal, int? taxAmount, int? totalAmount, String? orderNumber, String? notes, String? assignedTo, String? workflowStage, DateTime? createdAt, DateTime? updatedAt, List? items, }) { return SalesOrder( id: id ?? this.id, customerId: customerId ?? this.customerId, customerNameSnapshot: customerNameSnapshot ?? this.customerNameSnapshot, orderDate: orderDate ?? this.orderDate, requestedShipDate: requestedShipDate ?? this.requestedShipDate, status: status ?? this.status, subtotal: subtotal ?? this.subtotal, taxAmount: taxAmount ?? this.taxAmount, totalAmount: totalAmount ?? this.totalAmount, orderNumber: orderNumber ?? this.orderNumber, notes: notes ?? this.notes, assignedTo: assignedTo ?? this.assignedTo, workflowStage: workflowStage ?? this.workflowStage, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt, items: items ?? this.items, ); } Map toMap() => { 'id': id, 'order_number': orderNumber, 'customer_id': customerId, 'customer_name_snapshot': customerNameSnapshot, 'order_date': orderDate.toIso8601String(), 'requested_ship_date': requestedShipDate?.toIso8601String(), 'status': status.name, 'subtotal': subtotal, 'tax_amount': taxAmount, 'total_amount': totalAmount, 'notes': notes, 'assigned_to': assignedTo, 'workflow_stage': workflowStage, 'created_at': createdAt.toIso8601String(), 'updated_at': updatedAt.toIso8601String(), }; factory SalesOrder.fromMap(Map map, {List items = const []}) { return SalesOrder( id: map['id'] as String, orderNumber: map['order_number'] as String?, customerId: map['customer_id'] as String, customerNameSnapshot: map['customer_name_snapshot'] as String?, orderDate: DateTime.parse(map['order_date'] as String), requestedShipDate: (map['requested_ship_date'] as String?) != null ? DateTime.parse(map['requested_ship_date'] as String) : null, status: SalesOrderStatusX.fromDbValue(map['status'] as String?), subtotal: map['subtotal'] as int? ?? 0, taxAmount: map['tax_amount'] as int? ?? 0, totalAmount: map['total_amount'] as int? ?? 0, notes: map['notes'] as String?, assignedTo: map['assigned_to'] as String?, workflowStage: map['workflow_stage'] as String?, createdAt: DateTime.parse(map['created_at'] as String), updatedAt: DateTime.parse(map['updated_at'] as String), items: items, ); } SalesOrder recalculateTotals({double? defaultTaxRate}) { final newSubtotal = items.fold(0, (sum, item) => sum + item.lineTotal); final taxRate = defaultTaxRate ?? items.map((e) => e.taxRate).firstWhereOrNull((rate) => rate > 0) ?? 0; final newTaxAmount = (newSubtotal * taxRate).round(); return copyWith( subtotal: newSubtotal, taxAmount: newTaxAmount, totalAmount: newSubtotal + newTaxAmount, ); } }