191 lines
7.1 KiB
Dart
191 lines
7.1 KiB
Dart
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
|
|
part 'grn_model.freezed.dart';
|
|
part 'grn_model.g.dart';
|
|
|
|
String _idFromJson(Object? value) => value?.toString() ?? '';
|
|
|
|
int? _intFromJsonNullable(Object? value) {
|
|
if (value == null) return null;
|
|
if (value is int) return value;
|
|
if (value is num) return value.toInt();
|
|
return int.tryParse(value.toString());
|
|
}
|
|
|
|
double? _doubleFromJsonNullable(Object? value) {
|
|
if (value == null) return null;
|
|
if (value is double) return value;
|
|
if (value is num) return value.toDouble();
|
|
return double.tryParse(value.toString());
|
|
}
|
|
|
|
DateTime? _dateFromJsonNullable(Object? value) {
|
|
if (value == null) return null;
|
|
if (value is DateTime) return value;
|
|
return DateTime.tryParse(value.toString());
|
|
}
|
|
|
|
Object? _readNestedName(Map<dynamic, dynamic> json, String flatKey, String nestedKey) {
|
|
final flat = json[flatKey];
|
|
if (flat is String && flat.isNotEmpty) return flat;
|
|
final nested = json[nestedKey];
|
|
if (nested is Map) {
|
|
return nested['name'] ?? nested['vendor_name'];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
Object? _readVendorName(Map<dynamic, dynamic> json, String key) =>
|
|
_readNestedName(json, 'vendor_name', 'vendor');
|
|
|
|
Object? _readWarehouseName(Map<dynamic, dynamic> json, String key) =>
|
|
_readNestedName(json, 'warehouse_name', 'warehouse');
|
|
|
|
Object? _readPoNumber(Map<dynamic, dynamic> json, String key) {
|
|
final grnNumber = json['grn_number'];
|
|
if (grnNumber != null && grnNumber.toString().trim().isNotEmpty) {
|
|
return grnNumber.toString();
|
|
}
|
|
final grnNo = json['grn_no'];
|
|
if (grnNo != null && grnNo.toString().trim().isNotEmpty) {
|
|
return grnNo.toString();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
Object? _readPoRefNumber(Map<dynamic, dynamic> json, String key) {
|
|
final flat = json['po_number'];
|
|
if (flat is String && flat.isNotEmpty) return flat;
|
|
final nested = json['purchase_order'] ?? json['po'];
|
|
if (nested is Map) {
|
|
return nested['po_number'] ?? nested['po_no'];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
Object? _readItemName(Map<dynamic, dynamic> json, String key) {
|
|
final flat = json['item_name'];
|
|
if (flat is String && flat.isNotEmpty) return flat;
|
|
final nested = json['item'];
|
|
if (nested is Map) return nested['name'] ?? nested['item_name'];
|
|
return null;
|
|
}
|
|
|
|
Object? _readItemCode(Map<dynamic, dynamic> json, String key) {
|
|
final flat = json['item_code'];
|
|
if (flat is String && flat.isNotEmpty) return flat;
|
|
final nested = json['item'];
|
|
if (nested is Map) return nested['code'] ?? nested['item_code'];
|
|
return null;
|
|
}
|
|
|
|
Object? _readUomName(Map<dynamic, dynamic> json, String key) {
|
|
final flat = json['uom_name'];
|
|
if (flat is String && flat.isNotEmpty) return flat;
|
|
final nested = json['uom'];
|
|
if (nested is Map) return nested['name'];
|
|
return null;
|
|
}
|
|
|
|
@freezed
|
|
class GrnModel with _$GrnModel {
|
|
const GrnModel._();
|
|
|
|
const factory GrnModel({
|
|
@JsonKey(fromJson: _idFromJson) required String id,
|
|
@JsonKey(name: 'grn_number', readValue: _readPoNumber) String? grnNumber,
|
|
@JsonKey(name: 'grn_date', fromJson: _dateFromJsonNullable) DateTime? grnDate,
|
|
@Default('POSTED') String status,
|
|
@JsonKey(name: 'po_id', fromJson: _intFromJsonNullable) int? poId,
|
|
@JsonKey(name: 'po_number', readValue: _readPoRefNumber) String? poNumber,
|
|
@JsonKey(name: 'vendor_id', fromJson: _intFromJsonNullable) int? vendorId,
|
|
@JsonKey(name: 'vendor_name', readValue: _readVendorName) String? vendorName,
|
|
@JsonKey(name: 'warehouse_id', fromJson: _intFromJsonNullable) int? warehouseId,
|
|
@JsonKey(name: 'warehouse_name', readValue: _readWarehouseName) String? warehouseName,
|
|
@JsonKey(name: 'vendor_invoice_no') String? vendorInvoiceNo,
|
|
@JsonKey(name: 'vendor_invoice_date', fromJson: _dateFromJsonNullable)
|
|
DateTime? vendorInvoiceDate,
|
|
@JsonKey(name: 'vendor_invoice_amount', fromJson: _doubleFromJsonNullable)
|
|
double? vendorInvoiceAmount,
|
|
@JsonKey(name: 'vehicle_no') String? vehicleNo,
|
|
@JsonKey(name: 'lr_no') String? lrNo,
|
|
@JsonKey(name: 'lr_date', fromJson: _dateFromJsonNullable) DateTime? lrDate,
|
|
@JsonKey(name: 'received_by', fromJson: _intFromJsonNullable) int? receivedBy,
|
|
@JsonKey(name: 'quality_checked_by', fromJson: _intFromJsonNullable)
|
|
int? qualityCheckedBy,
|
|
String? remarks,
|
|
@JsonKey(name: 'cancellation_reason') String? cancellationReason,
|
|
@JsonKey(name: 'created_at', fromJson: _dateFromJsonNullable) DateTime? createdAt,
|
|
@JsonKey(name: 'updated_at', fromJson: _dateFromJsonNullable) DateTime? updatedAt,
|
|
@Default([]) List<GrnItemModel> items,
|
|
}) = _GrnModel;
|
|
|
|
factory GrnModel.fromJson(Map<String, dynamic> json) => _$GrnModelFromJson(json);
|
|
|
|
bool get canEdit => status.toUpperCase() == 'POSTED';
|
|
|
|
bool get canCancel => status.toUpperCase() == 'POSTED';
|
|
}
|
|
|
|
@freezed
|
|
class GrnItemModel with _$GrnItemModel {
|
|
const factory GrnItemModel({
|
|
@JsonKey(fromJson: _idFromJson) required String id,
|
|
@JsonKey(name: 'grn_id', fromJson: _idFromJson) String? grnId,
|
|
@JsonKey(name: 'po_item_id', fromJson: _intFromJsonNullable) int? poItemId,
|
|
@JsonKey(name: 'item_id', fromJson: _intFromJsonNullable) int? itemId,
|
|
@JsonKey(name: 'item_code', readValue: _readItemCode) String? itemCode,
|
|
@JsonKey(name: 'item_name', readValue: _readItemName) String? itemName,
|
|
@JsonKey(name: 'line_no', fromJson: _intFromJsonNullable) int? lineNo,
|
|
@JsonKey(name: 'current_qty', fromJson: _doubleFromJsonNullable) double? currentQty,
|
|
@JsonKey(name: 'accepted_qty', fromJson: _doubleFromJsonNullable) double? acceptedQty,
|
|
@JsonKey(name: 'damaged_qty', fromJson: _doubleFromJsonNullable) double? damagedQty,
|
|
@JsonKey(name: 'short_qty', fromJson: _doubleFromJsonNullable) double? shortQty,
|
|
@JsonKey(name: 'excess_qty', fromJson: _doubleFromJsonNullable) double? excessQty,
|
|
@JsonKey(name: 'rejected_qty', fromJson: _doubleFromJsonNullable) double? rejectedQty,
|
|
@JsonKey(name: 'rejection_reason') String? rejectionReason,
|
|
@JsonKey(fromJson: _doubleFromJsonNullable) double? rate,
|
|
@JsonKey(name: 'batch_no') String? batchNo,
|
|
@JsonKey(name: 'mfg_date', fromJson: _dateFromJsonNullable) DateTime? mfgDate,
|
|
@JsonKey(name: 'expiry_date', fromJson: _dateFromJsonNullable) DateTime? expiryDate,
|
|
@JsonKey(name: 'storage_location') String? storageLocation,
|
|
@JsonKey(name: 'asset_category_id', fromJson: _intFromJsonNullable)
|
|
int? assetCategoryId,
|
|
@JsonKey(name: 'uom_id', fromJson: _intFromJsonNullable) int? uomId,
|
|
@JsonKey(name: 'uom_name', readValue: _readUomName) String? uomName,
|
|
String? remarks,
|
|
}) = _GrnItemModel;
|
|
|
|
factory GrnItemModel.fromJson(Map<String, dynamic> json) =>
|
|
_$GrnItemModelFromJson(json);
|
|
}
|
|
|
|
@freezed
|
|
class GrnListQuery with _$GrnListQuery {
|
|
const factory GrnListQuery({
|
|
@Default(1) int page,
|
|
@Default(20) int limit,
|
|
String? search,
|
|
String? status,
|
|
int? poId,
|
|
int? vendorId,
|
|
int? warehouseId,
|
|
String? dateFrom,
|
|
String? dateTo,
|
|
}) = _GrnListQuery;
|
|
}
|
|
|
|
const grnStatusOptions = [
|
|
('POSTED', 'Posted'),
|
|
('CANCELLED', 'Cancelled'),
|
|
];
|
|
|
|
String grnStatusLabel(String? value) {
|
|
if (value == null) return '—';
|
|
return grnStatusOptions
|
|
.where((e) => e.$1 == value.toUpperCase())
|
|
.map((e) => e.$2)
|
|
.firstOrNull ??
|
|
value.replaceAll('_', ' ');
|
|
}
|