import 'package:inventory_app/utils.dart'; class Product { Unit? unit; Unit? purchaseUnit; String? code; String? name; int? id; int? version; String? productTypeSelect; // must be int, not String int? familleProduit; // will be sent as object {id: X} int? sousFamilleProduit; // same String? internalDescription; // custom logic (not Axelor default field) String? serialNumber; String? description; MetaFile? picture; String? procurementMethodSelect = 'buy'; Product({ this.unit, this.purchaseUnit, this.code, this.name, this.id, this.version, this.productTypeSelect, // use 0,1,2 this.familleProduit, this.sousFamilleProduit, this.internalDescription, this.serialNumber, this.description, this.picture, this.procurementMethodSelect, }); Product.fromJson(Map json) { unit = json['unit'] != null ? Unit.fromJson(json['unit']) : null; purchaseUnit = json['purchaseUnit'] != null ? Unit.fromJson(json['purchaseUnit']) : null; code = json['code']; name = json['name']; id = json['id']; version = json['version']; productTypeSelect = json['productTypeSelect']; familleProduit = json['familleProduit']?['id']; // Axelor wraps it in object sousFamilleProduit = json['sousFamilleProduit']?['id']; internalDescription = json['internalDescription']; serialNumber = json['serialNumber']; description = json['description']; picture = json['picture'] != null ? MetaFile.fromJson(json['picture']) : null; procurementMethodSelect = json['procurementMethodSelect'] ?? 'buy'; } Map toJson() { final Map data = {}; if (unit != null) { data['unit'] = unit!.toJson(); } if (purchaseUnit != null) { data['purchaseUnit'] = purchaseUnit!.toJson(); } if (code != null) data['code'] = code; if (name != null) data['name'] = name; if (id != null) data['id'] = id; if (version != null) data['version'] = version; if (productTypeSelect != null) { data['productTypeSelect'] = productTypeSelect; // ✅ must be int } // ✅ Axelor expects {"id": X}, NOT raw int if (familleProduit != null) { data['familleProduit'] = {'id': familleProduit}; } if (sousFamilleProduit != null) { data['sousFamilleProduit'] = {'id': sousFamilleProduit}; } data['internalDescription'] = internalDescription; data['serialNumber'] = serialNumber; data['description'] = description; data['procurementMethodSelect'] = procurementMethodSelect; return data; } @override String toString() { return 'Product{unit: $unit, code: $code, name: $name, id: $id, version: $version, productTypeSelect: $productTypeSelect, familleProduit: $familleProduit, sousFamilleProduit: $sousFamilleProduit, internalDescription: $internalDescription, serialNumber: $serialNumber, description: $description}'; } /// 👇 Get full image URL (you can customize baseUrl to be from `AxelorClient.baseUrl`) String? get imageUrl { if (picture?.id != null) { return '${Utils.url}/ws/rest/com.axelor.meta.db.MetaFile/${picture!.id}/content/download'; } return null; } } class Unit { String? name; int? id; int? version; Unit({this.name, this.id, this.version}); Unit.fromJson(Map json) { name = json['name']; id = json['id']; version = json['version']; } Map toJson() { return {'name': name, 'id': id, 'version': version}; } } class MetaFile { String? fileName; int? id; int? version; MetaFile({this.fileName, this.id, this.version}); MetaFile.fromJson(Map json) { fileName = json['fileName']; id = json['id']; version = json['$version']; } Map toJson() { return {'fileName': fileName, 'id': id, '\$version': version}; } }