/// Model for order detail with line items and modifiers class OrderDetail { final int orderId; final int businessId; final String businessName; final int status; final String statusText; final int orderTypeId; final String orderTypeName; final double subtotal; final double tax; final double tip; final double total; final String notes; final DateTime createdOn; final DateTime? submittedOn; final DateTime? updatedOn; final OrderCustomer customer; final OrderServicePoint servicePoint; final List lineItems; final List staff; const OrderDetail({ required this.orderId, required this.businessId, required this.businessName, required this.status, required this.statusText, required this.orderTypeId, required this.orderTypeName, required this.subtotal, required this.tax, required this.tip, required this.total, required this.notes, required this.createdOn, this.submittedOn, this.updatedOn, required this.customer, required this.servicePoint, required this.lineItems, required this.staff, }); factory OrderDetail.fromJson(Map json) { String safeStr(dynamic v) => v?.toString() ?? ''; final lineItemsJson = json['LineItems'] as List? ?? []; final staffJson = json['Staff'] as List? ?? []; return OrderDetail( orderId: _parseInt(json['OrderID']) ?? 0, businessId: _parseInt(json['BusinessID']) ?? 0, businessName: safeStr(json['BusinessName']), status: _parseInt(json['Status']) ?? 0, statusText: safeStr(json['StatusText']), orderTypeId: _parseInt(json['OrderTypeID']) ?? 0, orderTypeName: safeStr(json['OrderTypeName']), subtotal: _parseDouble(json['Subtotal']) ?? 0.0, tax: _parseDouble(json['Tax']) ?? 0.0, tip: _parseDouble(json['Tip']) ?? 0.0, total: _parseDouble(json['Total']) ?? 0.0, notes: safeStr(json['Notes']), createdOn: _parseDateTime(json['CreatedOn']), submittedOn: _parseDateTimeNullable(json['SubmittedOn']), updatedOn: _parseDateTimeNullable(json['UpdatedOn']), customer: OrderCustomer.fromJson(json['Customer'] as Map? ?? {}), servicePoint: OrderServicePoint.fromJson(json['ServicePoint'] as Map? ?? {}), lineItems: lineItemsJson .map((e) => OrderLineItemDetail.fromJson(e as Map)) .toList(), staff: staffJson .map((e) => OrderStaff.fromJson(e as Map)) .toList(), ); } /// Get only non-default modifiers for display List getNonDefaultModifiers(OrderLineItemDetail item) { return item.modifiers.where((m) => !m.isDefault).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 && value.isNotEmpty) 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 && value.isNotEmpty) 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 && value.isNotEmpty) { try { return DateTime.parse(value); } catch (_) {} } return DateTime.now(); } static DateTime? _parseDateTimeNullable(dynamic value) { if (value == null) return null; if (value is String && value.isEmpty) return null; if (value is DateTime) return value; if (value is String) { try { return DateTime.parse(value); } catch (_) {} } return null; } } class OrderCustomer { final int userId; final String firstName; final String lastName; final String phone; final String email; const OrderCustomer({ required this.userId, required this.firstName, required this.lastName, required this.phone, required this.email, }); factory OrderCustomer.fromJson(Map json) { return OrderCustomer( userId: _safeInt(json['UserID']), firstName: _safeStr(json['FirstName']), lastName: _safeStr(json['LastName']), phone: _safeStr(json['Phone']), email: _safeStr(json['Email']), ); } static int _safeInt(dynamic v) => v is int ? v : int.tryParse(v?.toString() ?? '') ?? 0; static String _safeStr(dynamic v) => v?.toString() ?? ''; String get fullName { final parts = [firstName, lastName].where((s) => s.isNotEmpty); return parts.isEmpty ? 'Guest' : parts.join(' '); } } class OrderServicePoint { final int servicePointId; final String name; final int typeId; const OrderServicePoint({ required this.servicePointId, required this.name, required this.typeId, }); factory OrderServicePoint.fromJson(Map json) { int safeInt(dynamic v) => v is int ? v : int.tryParse(v?.toString() ?? '') ?? 0; String safeStr(dynamic v) => v?.toString() ?? ''; return OrderServicePoint( servicePointId: safeInt(json['ServicePointID']), name: safeStr(json['Name']), typeId: safeInt(json['TypeID']), ); } } class OrderStaff { final int userId; final String firstName; final String avatarUrl; const OrderStaff({ required this.userId, required this.firstName, required this.avatarUrl, }); factory OrderStaff.fromJson(Map json) { int safeInt(dynamic v) => v is int ? v : int.tryParse(v?.toString() ?? '') ?? 0; String safeStr(dynamic v) => v?.toString() ?? ''; return OrderStaff( userId: safeInt(json['UserID']), firstName: safeStr(json['FirstName']), avatarUrl: safeStr(json['AvatarUrl']), ); } } class OrderLineItemDetail { final int lineItemId; final int itemId; final int parentLineItemId; final String itemName; final int quantity; final double unitPrice; final String remarks; final bool isDefault; final List modifiers; const OrderLineItemDetail({ required this.lineItemId, required this.itemId, required this.parentLineItemId, required this.itemName, required this.quantity, required this.unitPrice, required this.remarks, required this.isDefault, required this.modifiers, }); factory OrderLineItemDetail.fromJson(Map json) { int safeInt(dynamic v) => v is int ? v : int.tryParse(v?.toString() ?? '') ?? 0; double safeDouble(dynamic v) => v is num ? v.toDouble() : double.tryParse(v?.toString() ?? '') ?? 0.0; String safeStr(dynamic v) => v?.toString() ?? ''; final modifiersJson = json['Modifiers'] as List? ?? []; return OrderLineItemDetail( lineItemId: safeInt(json['LineItemID']), itemId: safeInt(json['ItemID']), parentLineItemId: safeInt(json['ParentLineItemID']), itemName: safeStr(json['ItemName']), quantity: safeInt(json['Quantity']), unitPrice: safeDouble(json['UnitPrice']), remarks: safeStr(json['Remarks']), isDefault: json['IsDefault'] == true, modifiers: modifiersJson .map((e) => OrderLineItemDetail.fromJson(e as Map)) .toList(), ); } /// Calculate total price for this item including modifiers double get totalPrice { double total = unitPrice * quantity; for (final mod in modifiers) { total += mod.unitPrice * mod.quantity; } return total; } /// Check if this item has any non-default modifiers bool get hasNonDefaultModifiers { return modifiers.any((m) => !m.isDefault); } /// Get only non-default modifiers List get nonDefaultModifiers { return modifiers.where((m) => !m.isDefault).toList(); } }