175 lines
5.7 KiB
Dart
175 lines
5.7 KiB
Dart
import 'package:intl/intl.dart';
|
|
import '../../inventory/domain/product.dart';
|
|
import '../../inventory/domain/inventory_item.dart';
|
|
import '../domain/label_document.dart';
|
|
|
|
class TemplateDataResolver {
|
|
static final NumberFormat _currencyFormatter = NumberFormat('#,##,##0.##');
|
|
|
|
/// Resolves a single field value from a Product (and optional InventoryItem)
|
|
static String? resolveFieldValue({
|
|
required String source,
|
|
required String fieldKey,
|
|
Product? product,
|
|
InventoryItem? inventoryItem,
|
|
}) {
|
|
if (product == null && inventoryItem == null) return null;
|
|
|
|
if (source == 'product' && product != null) {
|
|
switch (fieldKey) {
|
|
case 'name':
|
|
return product.name;
|
|
case 'sku':
|
|
return product.sku ?? (inventoryItem?.tagNumber ?? 'SKU-001');
|
|
case 'barcode':
|
|
return (product.barcode != null && product.barcode!.isNotEmpty)
|
|
? product.barcode
|
|
: (inventoryItem?.tagNumber ?? product.sku ?? '8901234567890');
|
|
case 'sellingPrice':
|
|
final price = product.sellingPrice ?? product.mrp;
|
|
return price != null ? _currencyFormatter.format(price) : null;
|
|
case 'mrp':
|
|
final price = product.mrp ?? product.sellingPrice;
|
|
return price != null ? _currencyFormatter.format(price) : null;
|
|
case 'weightInG':
|
|
final wt = inventoryItem?.grossWeight ?? product.weightInG;
|
|
return wt?.toStringAsFixed(2);
|
|
case 'hsnCode':
|
|
return product.hsnCode;
|
|
case 'gstRate':
|
|
return product.gstRate != null ? product.gstRate!.toStringAsFixed(0) : '3';
|
|
case 'brandName':
|
|
return product.brandName;
|
|
case 'material':
|
|
return product.material;
|
|
case 'size':
|
|
return product.size;
|
|
case 'color':
|
|
return product.color;
|
|
case 'manufacturerCode':
|
|
return inventoryItem?.huid ?? product.manufacturerCode;
|
|
case 'purityFactor':
|
|
if (inventoryItem?.purity != null) return inventoryItem!.purity;
|
|
return product.purityFactor != null
|
|
? '${(product.purityFactor! * 100).toStringAsFixed(1)}%'
|
|
: null;
|
|
case 'currentStock':
|
|
return product.currentStock?.toString();
|
|
case 'description':
|
|
return product.description;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
if (source == 'inventory' && inventoryItem != null) {
|
|
switch (fieldKey) {
|
|
case 'tagNumber':
|
|
return inventoryItem.tagNumber;
|
|
case 'huid':
|
|
return inventoryItem.huid;
|
|
case 'grossWeight':
|
|
return inventoryItem.grossWeight?.toStringAsFixed(3);
|
|
case 'netWeight':
|
|
return inventoryItem.netWeight?.toStringAsFixed(3);
|
|
case 'purity':
|
|
return inventoryItem.purity;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// Resolves an entire LabelDocument against sample data, returning a resolved copy
|
|
static LabelDocument resolveDocument({
|
|
required LabelDocument document,
|
|
Product? product,
|
|
InventoryItem? inventoryItem,
|
|
}) {
|
|
if (product == null && inventoryItem == null) {
|
|
return document;
|
|
}
|
|
|
|
final resolvedElements = <LabelElement>[];
|
|
|
|
for (final elem in document.elements) {
|
|
if (elem is DynamicTextElement) {
|
|
final rawVal = resolveFieldValue(
|
|
source: elem.source,
|
|
fieldKey: elem.fieldKey,
|
|
product: product,
|
|
inventoryItem: inventoryItem,
|
|
);
|
|
final formattedText = elem.formatValue(rawVal);
|
|
resolvedElements.add(
|
|
TextElement(
|
|
id: elem.id,
|
|
xMm: elem.xMm,
|
|
yMm: elem.yMm,
|
|
widthMm: elem.widthMm,
|
|
heightMm: elem.heightMm,
|
|
rotation: elem.rotation,
|
|
isLocked: elem.isLocked,
|
|
zIndex: elem.zIndex,
|
|
text: formattedText,
|
|
fontFamily: elem.fontFamily,
|
|
fontSizePt: elem.fontSizePt,
|
|
isBold: elem.isBold,
|
|
isItalic: elem.isItalic,
|
|
alignment: elem.alignment,
|
|
borderWidthMm: elem.borderWidthMm,
|
|
paddingMm: elem.paddingMm,
|
|
),
|
|
);
|
|
} else if (elem is BarcodeElement) {
|
|
if (elem.valueType == 'dynamic') {
|
|
final resolvedVal = resolveFieldValue(
|
|
source: elem.source,
|
|
fieldKey: elem.fieldKey,
|
|
product: product,
|
|
inventoryItem: inventoryItem,
|
|
) ?? elem.staticValue;
|
|
|
|
final effectiveBarcode = (resolvedVal.isNotEmpty ? resolvedVal : (product?.sku ?? '8901234567890'))
|
|
.replaceAll(RegExp(r'[^a-zA-Z0-9\-]'), '');
|
|
|
|
resolvedElements.add(
|
|
elem.copyWithPosition(
|
|
valueType: 'static',
|
|
staticValue: effectiveBarcode.isNotEmpty ? effectiveBarcode : '8901234567890',
|
|
),
|
|
);
|
|
} else {
|
|
resolvedElements.add(elem);
|
|
}
|
|
} else if (elem is QrCodeElement) {
|
|
if (elem.valueType == 'dynamic') {
|
|
final resolvedVal = resolveFieldValue(
|
|
source: elem.source,
|
|
fieldKey: elem.fieldKey,
|
|
product: product,
|
|
inventoryItem: inventoryItem,
|
|
) ?? elem.staticValue;
|
|
|
|
final effectiveQr = resolvedVal.isNotEmpty ? resolvedVal : (product?.sku ?? '8901234567890');
|
|
|
|
resolvedElements.add(
|
|
elem.copyWithPosition(
|
|
valueType: 'static',
|
|
staticValue: effectiveQr,
|
|
),
|
|
);
|
|
} else {
|
|
resolvedElements.add(elem);
|
|
}
|
|
} else {
|
|
resolvedElements.add(elem);
|
|
}
|
|
}
|
|
|
|
return document.copyWith(elements: resolvedElements);
|
|
}
|
|
}
|