class Cart { final int orderId; final String orderUuid; final int userId; final int businessId; final double businessDeliveryMultiplier; final int orderTypeId; final double deliveryFee; final int statusId; final int? addressId; final int? paymentId; final String? remarks; final DateTime addedOn; final DateTime lastEditedOn; final DateTime? submittedOn; final int servicePointId; final List lineItems; const Cart({ required this.orderId, required this.orderUuid, required this.userId, required this.businessId, required this.businessDeliveryMultiplier, required this.orderTypeId, required this.deliveryFee, required this.statusId, this.addressId, this.paymentId, this.remarks, required this.addedOn, required this.lastEditedOn, this.submittedOn, required this.servicePointId, required this.lineItems, }); factory Cart.fromJson(Map json) { final order = (json["ORDER"] ?? json["Order"]) as Map? ?? {}; final lineItemsJson = (json["ORDERLINEITEMS"] ?? json["OrderLineItems"]) as List? ?? []; return Cart( orderId: _parseInt(order["OrderID"]) ?? 0, orderUuid: (order["OrderUUID"] as String?) ?? "", userId: _parseInt(order["OrderUserID"]) ?? 0, businessId: _parseInt(order["OrderBusinessID"]) ?? 0, businessDeliveryMultiplier: _parseDouble(order["OrderBusinessDeliveryMultiplier"]) ?? 0.0, orderTypeId: _parseInt(order["OrderTypeID"]) ?? 0, deliveryFee: _parseDouble(order["OrderDeliveryFee"]) ?? 0.0, statusId: _parseInt(order["OrderStatusID"]) ?? 0, addressId: _parseInt(order["OrderAddressID"]), paymentId: _parseInt(order["OrderPaymentID"]), remarks: order["OrderRemarks"] as String?, addedOn: _parseDateTime(order["OrderAddedOn"]), lastEditedOn: _parseDateTime(order["OrderLastEditedOn"]), submittedOn: _parseDateTime(order["OrderSubmittedOn"]), servicePointId: _parseInt(order["OrderServicePointID"]) ?? 0, lineItems: lineItemsJson .map((item) => OrderLineItem.fromJson(item as Map)) .toList(), ); } static int? _parseInt(dynamic value) { if (value == null) return null; if (value is int) return value; if (value is num) return value.toInt(); if (value is String) { if (value.isEmpty) return null; return int.tryParse(value); } return null; } static double? _parseDouble(dynamic value) { if (value == null) return null; if (value is double) return value; if (value is num) return value.toDouble(); if (value is String) { if (value.isEmpty) return null; return double.tryParse(value); } return null; } static DateTime _parseDateTime(dynamic value) { if (value == null) return DateTime.now(); if (value is DateTime) return value; if (value is String) { try { return DateTime.parse(value); } catch (e) { return DateTime.now(); } } return DateTime.now(); } double get subtotal { return lineItems .where((item) => !item.isDeleted && item.parentOrderLineItemId == 0) .fold(0.0, (sum, item) => sum + (item.price * item.quantity)); } // Only include delivery fee for delivery orders (orderTypeId == 3) double get total => subtotal + (orderTypeId == 3 ? deliveryFee : 0); int get itemCount { return lineItems .where((item) => !item.isDeleted && item.parentOrderLineItemId == 0) .fold(0, (sum, item) => sum + item.quantity); } } class OrderLineItem { final int orderLineItemId; final int parentOrderLineItemId; final int orderId; final int itemId; final int statusId; final double price; final int quantity; final String? remark; final bool isDeleted; final DateTime addedOn; const OrderLineItem({ required this.orderLineItemId, required this.parentOrderLineItemId, required this.orderId, required this.itemId, required this.statusId, required this.price, required this.quantity, this.remark, required this.isDeleted, required this.addedOn, }); factory OrderLineItem.fromJson(Map json) { return OrderLineItem( orderLineItemId: _parseInt(json["OrderLineItemID"]) ?? 0, parentOrderLineItemId: _parseInt(json["OrderLineItemParentOrderLineItemID"]) ?? 0, orderId: _parseInt(json["OrderLineItemOrderID"]) ?? 0, itemId: _parseInt(json["OrderLineItemItemID"]) ?? 0, statusId: _parseInt(json["OrderLineItemStatusID"]) ?? 0, price: _parseDouble(json["OrderLineItemPrice"]) ?? 0.0, quantity: _parseInt(json["OrderLineItemQuantity"]) ?? 0, remark: json["OrderLineItemRemark"] as String?, isDeleted: _parseBool(json["OrderLineItemIsDeleted"]), addedOn: _parseDateTime(json["OrderLineItemAddedOn"]), ); } static int? _parseInt(dynamic value) { if (value == null) return null; if (value is int) return value; if (value is num) return value.toInt(); if (value is String) { if (value.isEmpty) return null; return int.tryParse(value); } return null; } static double? _parseDouble(dynamic value) { if (value == null) return null; if (value is double) return value; if (value is num) return value.toDouble(); if (value is String) { if (value.isEmpty) return null; return double.tryParse(value); } return null; } static bool _parseBool(dynamic value) { if (value == null) return false; if (value is bool) return value; if (value is num) return value != 0; if (value is String) { final lower = value.toLowerCase(); return lower == "true" || lower == "1"; } return false; } static DateTime _parseDateTime(dynamic value) { if (value == null) return DateTime.now(); if (value is DateTime) return value; if (value is String) { try { return DateTime.parse(value); } catch (e) { return DateTime.now(); } } return DateTime.now(); } bool get isRootItem => parentOrderLineItemId == 0; bool get isModifier => parentOrderLineItemId != 0; }