h-1.flutter.0/lib/models/order_models.dart
2026-03-04 14:55:40 +09:00

211 lines
6.3 KiB
Dart

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<String, dynamic> 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<String, dynamic> 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<SalesOrderItem> 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<SalesOrderItem>? 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<String, dynamic> 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<String, dynamic> map, {List<SalesOrderItem> 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<int>(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,
);
}
}