phase3(foundation): http_util dio5 migration + null-safe models

- http_util.dart: dio4->5 (DioException, nullable params, drop unused statusCode,
  null-safe e.response!.data), countryCode ?? ''
- models/* (39 files): make all instance fields nullable (fromJson initializer-list
  pattern forces nullable); fix internal method usages (cart_info/cart_line_item/
  order/shipping_rate) with !/??
- models/ now passes dart analyze with 0 errors

Widget-level null-safety + remaining utils/store continue in next batch.
This commit is contained in:
2026-07-24 03:45:01 +08:00
parent 1a578c925d
commit 4f9aa4f683
40 changed files with 382 additions and 389 deletions

View File

@@ -4,9 +4,9 @@ import 'dart:convert';
import 'package:flutter_wisetronic/models/product_attribute.dart';
class Subproduct {
int id;
SimpleProduct product;
double quantity;
int? id;
SimpleProduct? product;
double? quantity;
Subproduct.fromJson(Map<String, dynamic> json) :
id = json['id'],
@@ -26,15 +26,15 @@ class Subproduct {
}
class SimpleProduct {
int id;
String name;
String sku;
double price;
String description;
String image;
List<ProductAttribute> productAttributes;
double customerLastPrice;
String extraData;
int? id;
String? name;
String? sku;
double? price;
String? description;
String? image;
List<ProductAttribute>? productAttributes;
double? customerLastPrice;
String? extraData;
SimpleProduct.fromJson(Map<String, dynamic> json) :
id = json['id'],

View File

@@ -1,21 +1,21 @@
import 'dart:convert';
class Address {
int id;
String addressLine1;
String addressLine2;
String city;
String state;
String country;
String zip;
String phone;
String fax;
String email;
String contactName;
int gender;
String lat;
String lng;
String fullAddress;
int? id;
String? addressLine1;
String? addressLine2;
String? city;
String? state;
String? country;
String? zip;
String? phone;
String? fax;
String? email;
String? contactName;
int? gender;
String? lat;
String? lng;
String? fullAddress;
Address.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -2,8 +2,8 @@
import 'dart:convert';
class Section {
int id;
String name;
int? id;
String? name;
Section.fromJson(Map<String, dynamic> json) :
id = json['id'],
@@ -21,14 +21,14 @@ class Section {
}
class Blog {
int id;
String title;
String body;
String createdAt;
String thumbUrl;
String imageUrl;
String videoUrl;
Section section;
int? id;
String? title;
String? body;
String? createdAt;
String? thumbUrl;
String? imageUrl;
String? videoUrl;
Section? section;
Blog.fromJson(Map<String, dynamic> json) :
id = json['id'],

View File

@@ -4,10 +4,10 @@ import 'dart:convert';
import 'booking_time.dart';
class BookingDateTime {
String viewDate;
int unixTime;
String sendTimeTip;
List<BookingTime> bookTimes;
String? viewDate;
int? unixTime;
String? sendTimeTip;
List<BookingTime>? bookTimes;
BookingDateTime(this.viewDate, this.unixTime, this.sendTimeTip, this.bookTimes);

View File

@@ -2,9 +2,9 @@
import 'dart:convert';
class BookingTime {
String viewTime;
int unixTime;
String sendTimeTip;
String? viewTime;
int? unixTime;
String? sendTimeTip;
BookingTime(this.viewTime, this.unixTime, this.sendTimeTip);

View File

@@ -8,7 +8,7 @@ import 'product.dart';
import 'waiting_line.dart';
class QuickInput {
String value;
String? value;
QuickInput.fromJson(Map<String, dynamic> json)
: value = json['value'];
@@ -23,48 +23,48 @@ class QuickInput {
}
class Business {
int id;
String name;
String phone;
Address address;
String fullAddress;
String picUrl;
int status;
List<BusinessTime> openingTime;
double shippingFee;
double packageFee;
double minPrice;
int shippingTime;
int monthSales;
String bulletin;
int category;
bool isLike;
String description;
String policy;
String bannerImageUrl;
int todayOpen;
int todayClose;
bool showMonthlySold;
List<ImageUrl> slideImages;
List<Product> promoProducts;
String paypalEmail;
bool deliveryCanadaPost;
bool deliveryStoreDelivery;
bool deliveryPickup;
String currency;
List<WaitingLine> waitingLine;
bool enableWaitingLine;
double pointsToCreditsConversionRate;
String chaseXLogin;
String chaseTransactionKey;
String chaseResponseKey;
DistanceInfo distanceInfo;
int commentsCount;
bool forceClose;
bool isPublic;
double referrerCoupon;
bool instanceDelivery;
List<QuickInput> quickInputs;
int? id;
String? name;
String? phone;
Address? address;
String? fullAddress;
String? picUrl;
int? status;
List<BusinessTime>? openingTime;
double? shippingFee;
double? packageFee;
double? minPrice;
int? shippingTime;
int? monthSales;
String? bulletin;
int? category;
bool? isLike;
String? description;
String? policy;
String? bannerImageUrl;
int? todayOpen;
int? todayClose;
bool? showMonthlySold;
List<ImageUrl>? slideImages;
List<Product>? promoProducts;
String? paypalEmail;
bool? deliveryCanadaPost;
bool? deliveryStoreDelivery;
bool? deliveryPickup;
String? currency;
List<WaitingLine>? waitingLine;
bool? enableWaitingLine;
double? pointsToCreditsConversionRate;
String? chaseXLogin;
String? chaseTransactionKey;
String? chaseResponseKey;
DistanceInfo? distanceInfo;
int? commentsCount;
bool? forceClose;
bool? isPublic;
double? referrerCoupon;
bool? instanceDelivery;
List<QuickInput>? quickInputs;
Business.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -1,8 +1,8 @@
import 'dart:convert';
class BusinessTime {
String openTime;
String closeTime;
String? openTime;
String? closeTime;
BusinessTime.fromJson(Map<String, dynamic> json)
: openTime = json['open_time'],

View File

@@ -7,18 +7,18 @@ import 'cart_line_item.dart';
import 'extra_fee.dart';
class CartInfo {
int id;
double originPrice;
double discountPrice;
double totalPrice;
Business businessInfo;
List<CartLineItem> productList;
List<ExtraFee> extraFeeList;
List<ExtraFee> discountList;
int deliveryMethod;
String shippingMethod;
double amountPaid;
String extraData;
int? id;
double? originPrice;
double? discountPrice;
double? totalPrice;
Business? businessInfo;
List<CartLineItem>? productList;
List<ExtraFee>? extraFeeList;
List<ExtraFee>? discountList;
int? deliveryMethod;
String? shippingMethod;
double? amountPaid;
String? extraData;
CartInfo.fromJson(Map<String, dynamic> json)
: id = json['id'],
@@ -53,7 +53,7 @@ class CartInfo {
if (productList == null) {
productList = [item];
} else {
productList.add(item);
productList!.add(item);
}
}
@@ -74,19 +74,19 @@ class CartInfo {
originPrice = 0.0;
discountPrice = 0.0;
totalPrice = 0.0;
for (var i = 0; i < productList.length; i++) {
newTotal += productList[i].getTotalPrice();
for (var i = 0; i < (productList?.length ?? 0); i++) {
newTotal += productList![i].getTotalPrice();
}
originPrice = newTotal;
totalPrice = newTotal;
return totalPrice;
return totalPrice ?? 0.0;
}
int getProductListTotalQuantity() {
int qty = 0;
if (productList != null && productList.length > 0) {
for (var i = 0; i < productList.length; i++) {
qty += productList[i].quantity.round();
if (productList != null && productList!.length > 0) {
for (var i = 0; i < productList!.length; i++) {
qty += (productList![i].quantity ?? 0).round();
}
}
return qty;

View File

@@ -6,15 +6,15 @@ import 'package:uuid/uuid.dart';
import 'product.dart';
class CartLineItem {
int id;
double unitPrice;
double totalPrice;
Product product;
String name;
String description;
double quantity;
String uuid;
String parentUuid;
int? id;
double? unitPrice;
double? totalPrice;
Product? product;
String? name;
String? description;
double? quantity;
String? uuid;
String? parentUuid;
CartLineItem() {
uuid = Uuid().v4();
@@ -48,7 +48,7 @@ class CartLineItem {
}
double getTotalPrice() {
totalPrice = unitPrice * quantity;
return totalPrice;
totalPrice = (unitPrice ?? 0.0) * (quantity ?? 0);
return totalPrice ?? 0.0;
}
}

View File

@@ -2,8 +2,8 @@
import 'dart:convert';
class Category {
int id;
String name;
int? id;
String? name;
Category.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -4,12 +4,12 @@ import 'dart:convert';
import 'product.dart';
class CategoryProducts {
int id;
int businessId;
String name;
String description;
String iconUrl;
List<Product> products;
int? id;
int? businessId;
String? name;
String? description;
String? iconUrl;
List<Product>? products;
CategoryProducts.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -4,15 +4,15 @@ import 'dart:convert';
import 'product_image.dart';
class Comment {
int id;
String contact;
String content;
int rating;
List<ProductImage> images;
String createdAt;
int thumbUp;
int thumbDown;
String replyFromStore;
int? id;
String? contact;
String? content;
int? rating;
List<ProductImage>? images;
String? createdAt;
int? thumbUp;
int? thumbDown;
String? replyFromStore;
Comment.fromJson(Map<String, dynamic> json) :
id = json['id'],

View File

@@ -4,14 +4,14 @@ import 'dart:convert';
import 'business.dart';
class Coupon {
int id;
String code;
String description;
String expirationDate;
double minAmount;
Business store;
double valueAmount;
bool isPercentage;
int? id;
String? code;
String? description;
String? expirationDate;
double? minAmount;
Business? store;
double? valueAmount;
bool? isPercentage;
Coupon.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -4,9 +4,9 @@ import 'dart:convert';
import 'text_value.dart';
class DistanceInfo {
TextValue duration;
TextValue distance;
String status;
TextValue? duration;
TextValue? distance;
String? status;
DistanceInfo.fromJson(Map<String, dynamic> json)
: duration = json['duration'] != null ? TextValue.fromJson(json['duration']) : null,

View File

@@ -2,8 +2,8 @@
import 'dart:convert';
class ErrorMessage {
String code;
String string;
String? code;
String? string;
ErrorMessage.fromJson(Map<String, dynamic> json)
: code = json['code'],

View File

@@ -3,11 +3,11 @@
import 'dart:convert';
class ExtraFee {
int id;
String name;
String description;
double rate;
double price;
int? id;
String? name;
String? description;
double? rate;
double? price;
ExtraFee.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -2,11 +2,11 @@
import 'dart:convert';
class Fulfillment {
int id;
String shippingMethod;
String trackingNumber;
String note;
String createdAt;
int? id;
String? shippingMethod;
String? trackingNumber;
String? note;
String? createdAt;
Fulfillment.fromJson(Map<String, dynamic> json) :
id = json['id'],

View File

@@ -2,9 +2,9 @@
import 'dart:convert';
class Gallery {
int id;
String image;
String linkUrl;
int? id;
String? image;
String? linkUrl;
Gallery.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -3,8 +3,8 @@
import 'dart:convert';
class Group {
int id;
String name;
int? id;
String? name;
Group.fromJson(Map<String, dynamic> json) :
id = json['id'],

View File

@@ -1,8 +1,8 @@
import 'dart:convert';
class ImageUrl {
int id;
String imageUrl;
int? id;
String? imageUrl;
ImageUrl.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -1,7 +1,7 @@
class KeyValue {
String name;
dynamic value;
String? name;
dynamic? value;
KeyValue(this.name, this.value);

View File

@@ -1,17 +1,17 @@
import 'dart:convert';
class LocatedAddress {
int storeId;
double latitude;
double longitude;
String streetNumber;
String streetName;
String city;
String locality;
String province;
String country;
String postalCode;
String formattedAddress;
int? storeId;
double? latitude;
double? longitude;
String? streetNumber;
String? streetName;
String? city;
String? locality;
String? province;
String? country;
String? postalCode;
String? formattedAddress;
LocatedAddress.fromJson(Map<String, dynamic> json)
: storeId = json['store_id'],

View File

@@ -11,33 +11,33 @@ import 'fulfillment.dart';
import 'user_position.dart';
class Order {
int id;
int userId;
int businessId;
Business businessInfo;
CartInfo cartInfo;
int status;
double originPrice;
double discountPrice;
double totalPrice;
String consignee;
String phone;
String address;
Address shippingAddress;
int payMethod;
String remark;
String orderNum;
int bookedAt;
int createdAt;
String shippingMethod;
int? id;
int? userId;
int? businessId;
Business? businessInfo;
CartInfo? cartInfo;
int? status;
double? originPrice;
double? discountPrice;
double? totalPrice;
String? consignee;
String? phone;
String? address;
Address? shippingAddress;
int? payMethod;
String? remark;
String? orderNum;
int? bookedAt;
int? createdAt;
String? shippingMethod;
String paymentStatus; // UNPAID, PAID, PARTIALPAID
double amountPaid;
List<Fulfillment> fulfillments;
String extraData;
bool hasComment;
double fee;
UserPosition shipperPosition;
DistanceInfo deliveryDistance;
double? amountPaid;
List<Fulfillment>? fulfillments;
String? extraData;
bool? hasComment;
double? fee;
UserPosition? shipperPosition;
DistanceInfo? deliveryDistance;
Order.fromJson(Map<String, dynamic> json)
: id = json['id'],
@@ -100,7 +100,7 @@ class Order {
double getSubtotal() {
double subtotal = 0.0;
for (CartLineItem lineItem in cartInfo.productList) {
for (CartLineItem lineItem in cartInfo?.productList ?? <CartLineItem>[]) {
subtotal += lineItem.getTotalPrice();
}
return subtotal;

View File

@@ -6,19 +6,19 @@ import 'package:flutter/cupertino.dart';
import '../generated/l10n.dart';
class PaymentPlatform {
int id;
String name;
String code;
String method;
String icon;
String xLogin;
String transactionKey;
String responseKey;
String squareAppId;
String squareAccessToken;
String squareLocationId;
String publishableKey;
String merchantId;
int? id;
String? name;
String? code;
String? method;
String? icon;
String? xLogin;
String? transactionKey;
String? responseKey;
String? squareAppId;
String? squareAccessToken;
String? squareLocationId;
String? publishableKey;
String? merchantId;
PaymentPlatform(this.code);

View File

@@ -1,7 +1,7 @@
class Position {
final double latitude;
final double longitude;
final double? latitude;
final double? longitude;
Position({this.latitude, this.longitude});

View File

@@ -5,23 +5,23 @@ import 'Subproduct.dart';
import 'product_attribute.dart';
class Product {
int id;
int businessId;
int categoryId;
String name;
double price;
double regularPrice;
String description;
String detailDescription;
String imagePath;
String secondImagePath;
double monthSales;
int rate;
double leftNum;
List<ProductAttribute> productAttributes;
bool nonInventory;
String extraData;
List<Subproduct> subproducts;
int? id;
int? businessId;
int? categoryId;
String? name;
double? price;
double? regularPrice;
String? description;
String? detailDescription;
String? imagePath;
String? secondImagePath;
double? monthSales;
int? rate;
double? leftNum;
List<ProductAttribute>? productAttributes;
bool? nonInventory;
String? extraData;
List<Subproduct>? subproducts;
Product(int id, int businessId, String name, double price, String description,
String imagePath, List<ProductAttribute> productAttributes) {

View File

@@ -4,14 +4,14 @@ import 'dart:convert';
import 'product_option.dart';
class ProductAttribute {
int id;
String name;
List<ProductOption> productOptions;
bool singleSelection;
bool byQuantity;
bool required;
String extra;
bool disabled;
int? id;
String? name;
List<ProductOption>? productOptions;
bool? singleSelection;
bool? byQuantity;
bool? required;
String? extra;
bool? disabled;
ProductAttribute.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -8,30 +8,30 @@ import 'product_attribute.dart';
import 'product_image.dart';
class ProductDetail {
int id;
String image;
List<ProductImage> images;
String sku;
String name;
double price;
double regularPrice;
String description;
String description2;
String detailDescription;
double monthSales;
int rate;
double leftNum;
List<ProductAttribute> productAttributes;
bool nonInventory;
String extraData;
String purchaseNote;
double weight;
double dimentionsLength;
double dimentionsWidth;
double dimentionsHeight;
bool reviewsAllowed;
List<Category> categories;
List<Subproduct> subproducts;
int? id;
String? image;
List<ProductImage>? images;
String? sku;
String? name;
double? price;
double? regularPrice;
String? description;
String? description2;
String? detailDescription;
double? monthSales;
int? rate;
double? leftNum;
List<ProductAttribute>? productAttributes;
bool? nonInventory;
String? extraData;
String? purchaseNote;
double? weight;
double? dimentionsLength;
double? dimentionsWidth;
double? dimentionsHeight;
bool? reviewsAllowed;
List<Category>? categories;
List<Subproduct>? subproducts;
ProductDetail.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -1,8 +1,8 @@
import 'dart:convert';
class ProductImage {
int id;
String image;
int? id;
String? image;
ProductImage.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -2,11 +2,11 @@
import 'dart:convert';
class ProductOption {
int id;
String name;
double adjustAmount;
String extra;
bool disabled;
int? id;
String? name;
double? adjustAmount;
String? extra;
bool? disabled;
ProductOption.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -4,9 +4,9 @@ import 'dart:convert';
import 'package:flutter/foundation.dart';
class ShippingRate {
String name;
double price;
List<Rate> rates;
String? name;
double? price;
List<Rate>? rates;
ShippingRate.fromJson(Map<String, dynamic> json)
: name = json['name'],
@@ -25,7 +25,7 @@ class ShippingRate {
other is ShippingRate &&
runtimeType == other.runtimeType &&
name == other.name &&
price.toStringAsFixed(2) == other.price.toStringAsFixed(2) &&
price?.toStringAsFixed(2) == other.price?.toStringAsFixed(2) &&
listEquals(rates, other.rates);
@override
@@ -41,8 +41,8 @@ class ShippingRate {
}
class Rate {
String name;
double rate;
String? name;
double? rate;
Rate.fromJson(Map<String, dynamic> json)
: name = json['name'],
@@ -59,7 +59,7 @@ class Rate {
other is Rate &&
runtimeType == other.runtimeType &&
name == other.name &&
rate.toStringAsFixed(2) == other.rate.toStringAsFixed(2);
rate?.toStringAsFixed(2) == other.rate?.toStringAsFixed(2);
@override
String toString() {

View File

@@ -4,9 +4,9 @@ import 'dart:convert';
import 'address.dart';
class Store {
int id;
String name;
Address address;
int? id;
String? name;
Address? address;
Store.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -1,12 +1,12 @@
import 'dart:convert';
class SimpleProduct {
int id;
String name;
double price;
double regularPrice;
String description;
String imagePath;
int? id;
String? name;
double? price;
double? regularPrice;
String? description;
String? imagePath;
SimpleProduct.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -2,8 +2,8 @@
import 'dart:convert';
class TextValue {
String text;
int value;
String? text;
int? value;
TextValue.fromJson(Map<String, dynamic> json)
: text = json['text'],

View File

@@ -4,10 +4,10 @@ import 'dart:convert';
import 'simple_business.dart';
class TicketFile {
int id;
String url;
String fileName;
String fileType;
int? id;
String? url;
String? fileName;
String? fileType;
TicketFile.fromJson(Map<String, dynamic> json)
: id = json['id'],
@@ -29,9 +29,9 @@ class TicketFile {
}
class Issue {
int id;
String msg;
List<TicketFile> files;
int? id;
String? msg;
List<TicketFile>? files;
Issue.fromJson(Map<String, dynamic> json)
: id = json['id'],
@@ -51,11 +51,11 @@ class Issue {
}
class FollowUp {
int id;
String msg;
String poster;
String createdAt;
List<TicketFile> files;
int? id;
String? msg;
String? poster;
String? createdAt;
List<TicketFile>? files;
FollowUp.fromJson(Map<String, dynamic> json)
: id = json['id'],
@@ -79,12 +79,12 @@ class FollowUp {
}
class Ticket {
int id;
Issue issue;
Store store;
List<FollowUp> followUps;
bool isClosed;
String createdAt;
int? id;
Issue? issue;
Store? store;
List<FollowUp>? followUps;
bool? isClosed;
String? createdAt;
Ticket.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -2,22 +2,22 @@
import 'dart:convert';
class User {
int id;
String username;
String nickname;
String mobile;
String email;
String avatarUrl;
int lastAddressId;
String passCode;
double credit;
double wallet;
int coupon;
int points;
int orderNum;
double pointsToCreditsConversionRate;
String contactNumber;
String flutterMiniStoreToken;
int? id;
String? username;
String? nickname;
String? mobile;
String? email;
String? avatarUrl;
int? lastAddressId;
String? passCode;
double? credit;
double? wallet;
int? coupon;
int? points;
int? orderNum;
double? pointsToCreditsConversionRate;
String? contactNumber;
String? flutterMiniStoreToken;
User.fromJson(Map<String, dynamic> json)
: id = json['id'],

View File

@@ -2,8 +2,8 @@
import 'dart:convert';
class UserPosition {
double lat;
double lng;
double? lat;
double? lng;
UserPosition.fromJson(Map<String, dynamic> json) :
lat = double.parse(json['lat'].toString()),

View File

@@ -4,8 +4,8 @@ import 'dart:convert';
import 'waiting_line_item.dart';
class WaitingLine {
List<WaitingLineItem> waitingLines;
String storeSn;
List<WaitingLineItem>? waitingLines;
String? storeSn;
WaitingLine.fromJson(Map<String, dynamic> json)
: waitingLines = (json['waiting_lines'] as List).map((i) => WaitingLineItem.fromJson(i)).toList(),

View File

@@ -1,11 +1,11 @@
import 'dart:convert';
class WaitingLineItem {
String deviceId;
String phone;
String createdAt;
int peopleCount;
int waitingNumber;
String? deviceId;
String? phone;
String? createdAt;
int? peopleCount;
int? waitingNumber;
WaitingLineItem.fromJson(Map<String, dynamic> json)
: deviceId = json['device_id'],