bharat_erp/lib/modules/master_data/domain/entities/master_definition.dart

495 lines
15 KiB
Dart

import 'package:flutter/material.dart';
enum MasterFieldType { text, number, boolean, dropdown }
const brandTypes = ['OWN', 'OEM', 'THIRD_PARTY'];
class MasterFieldDef {
const MasterFieldDef({
required this.key,
required this.label,
this.type = MasterFieldType.text,
this.required = false,
this.showInList = false,
this.optionsMasterKey,
this.staticOptions,
this.multiline = false,
});
final String key;
final String label;
final MasterFieldType type;
final bool required;
final bool showInList;
/// Master key used to populate dropdown options (e.g. `plants` for plant_id).
final String? optionsMasterKey;
/// Fixed dropdown choices (e.g. brand type) — no API lookup.
final List<String>? staticOptions;
final bool multiline;
}
class MasterDefinition {
const MasterDefinition({
required this.id,
required this.title,
required this.subtitle,
required this.category,
required this.routeKey,
required this.apiPath,
required this.module,
required this.icon,
required this.fields,
});
final String id;
final String title;
final String subtitle;
final String category;
final String routeKey;
final String apiPath;
final String module;
final IconData icon;
final List<MasterFieldDef> fields;
List<MasterFieldDef> get listFields =>
fields.where((field) => field.showInList).toList();
List<MasterFieldDef> get formFields => fields;
String listRoute(String base) => '$base/$routeKey';
String addRoute(String base) => '$base/$routeKey/add';
String editRoute(String base, String id) => '$base/$routeKey/$id/edit';
}
const _activeField = MasterFieldDef(
key: 'is_active',
label: 'Active',
type: MasterFieldType.boolean,
);
MasterDefinition? masterDefinitionById(String id) {
for (final def in masterDefinitions) {
if (def.id == id) return def;
}
return null;
}
MasterDefinition? masterDefinitionByRouteKey(String routeKey) {
for (final def in masterDefinitions) {
if (def.routeKey == routeKey) return def;
}
return null;
}
const masterDefinitions = <MasterDefinition>[
MasterDefinition(
id: 'uom',
title: 'UOM',
subtitle: 'Units of measure',
category: 'Inventory & Items',
routeKey: 'uom',
apiPath: '/masters/uom',
module: 'uom',
icon: Icons.straighten_outlined,
fields: [
MasterFieldDef(key: 'code', label: 'Code', required: true, showInList: true),
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
_activeField,
],
),
MasterDefinition(
id: 'item_categories',
title: 'Item Categories',
subtitle: 'Top-level item grouping',
category: 'Inventory & Items',
routeKey: 'item-categories',
apiPath: '/masters/item-categories',
module: 'item_categories',
icon: Icons.category_outlined,
fields: [
MasterFieldDef(key: 'code', label: 'Code', required: true, showInList: true),
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
_activeField,
],
),
MasterDefinition(
id: 'item_subcategories',
title: 'Item Sub Categories',
subtitle: 'Sub-grouping under item categories',
category: 'Inventory & Items',
routeKey: 'item-subcategories',
apiPath: '/masters/item-subcategories',
module: 'item_subcategories',
icon: Icons.subdirectory_arrow_right,
fields: [
MasterFieldDef(
key: 'item_category_id',
label: 'Item Category',
type: MasterFieldType.dropdown,
required: true,
showInList: true,
optionsMasterKey: 'item_categories',
),
MasterFieldDef(key: 'code', label: 'Code', required: true, showInList: true),
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
_activeField,
],
),
MasterDefinition(
id: 'items',
title: 'Items',
subtitle: 'Material and product master',
category: 'Inventory & Items',
routeKey: 'items',
apiPath: '/masters/items',
module: 'items',
icon: Icons.inventory_outlined,
fields: [
MasterFieldDef(key: 'item_code', label: 'Item Code', required: true, showInList: true),
MasterFieldDef(key: 'item_name', label: 'Item Name', required: true, showInList: true),
MasterFieldDef(
key: 'item_category_id',
label: 'Category',
type: MasterFieldType.dropdown,
required: true,
optionsMasterKey: 'item_categories',
),
MasterFieldDef(
key: 'item_subcategory_id',
label: 'Sub Category',
type: MasterFieldType.dropdown,
optionsMasterKey: 'item_subcategories',
),
MasterFieldDef(
key: 'uom_id',
label: 'UOM',
type: MasterFieldType.dropdown,
required: true,
optionsMasterKey: 'uom',
),
MasterFieldDef(
key: 'gst_rate_id',
label: 'GST Rate',
type: MasterFieldType.dropdown,
optionsMasterKey: 'gst_rates',
),
MasterFieldDef(
key: 'brand_id',
label: 'Brand',
type: MasterFieldType.dropdown,
optionsMasterKey: 'brands',
),
MasterFieldDef(
key: 'is_asset_item',
label: 'Asset Item',
type: MasterFieldType.boolean,
required: true,
),
MasterFieldDef(
key: 'min_order_qty',
label: 'Min Order Qty',
type: MasterFieldType.number,
required: true,
),
MasterFieldDef(
key: 'reorder_level',
label: 'Reorder Level',
type: MasterFieldType.number,
required: true,
),
MasterFieldDef(key: 'description', label: 'Description', multiline: true),
MasterFieldDef(key: 'specification', label: 'Specification', multiline: true),
_activeField,
],
),
MasterDefinition(
id: 'brands',
title: 'Brands',
subtitle: 'Own and third-party brands',
category: 'Inventory & Items',
routeKey: 'brands',
apiPath: '/masters/brands',
module: 'brands',
icon: Icons.loyalty_outlined,
fields: [
MasterFieldDef(key: 'code', label: 'Code', required: true, showInList: true),
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
MasterFieldDef(
key: 'brand_type',
label: 'Brand Type',
type: MasterFieldType.dropdown,
required: true,
showInList: true,
staticOptions: brandTypes,
),
MasterFieldDef(key: 'contact_person', label: 'Contact Person'),
MasterFieldDef(key: 'phone', label: 'Phone'),
MasterFieldDef(key: 'email', label: 'Email'),
_activeField,
],
),
MasterDefinition(
id: 'document_series',
title: 'Document Series',
subtitle: 'Numbering series for documents',
category: 'Finance & Terms',
routeKey: 'document-series',
apiPath: '/masters/document-series',
module: 'document_series',
icon: Icons.numbers_outlined,
fields: [
MasterFieldDef(key: 'code', label: 'Code', required: true, showInList: true),
MasterFieldDef(key: 'prefix', label: 'Prefix', required: true, showInList: true),
MasterFieldDef(
key: 'current_number',
label: 'Current Number',
type: MasterFieldType.number,
required: true,
showInList: true,
),
MasterFieldDef(
key: 'padding',
label: 'Padding',
type: MasterFieldType.number,
required: true,
),
MasterFieldDef(key: 'description', label: 'Description', multiline: true),
_activeField,
],
),
MasterDefinition(
id: 'plants',
title: 'Plants',
subtitle: 'Manufacturing plants and units',
category: 'Organization',
routeKey: 'plants',
apiPath: '/masters/plants',
module: 'plants',
icon: Icons.factory_outlined,
fields: [
MasterFieldDef(key: 'code', label: 'Code', required: true, showInList: true),
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
MasterFieldDef(key: 'gstin', label: 'GSTIN', showInList: true),
MasterFieldDef(key: 'city', label: 'City', showInList: true),
MasterFieldDef(key: 'state', label: 'State'),
MasterFieldDef(key: 'address', label: 'Address', multiline: true),
MasterFieldDef(key: 'pincode', label: 'Pincode'),
MasterFieldDef(key: 'phone', label: 'Phone'),
_activeField,
],
),
MasterDefinition(
id: 'warehouses',
title: 'Warehouse',
subtitle: 'Storage locations by plant',
category: 'Organization',
routeKey: 'warehouses',
apiPath: '/masters/warehouses',
module: 'warehouses',
icon: Icons.warehouse_outlined,
fields: [
MasterFieldDef(key: 'code', label: 'Code', required: true, showInList: true),
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
MasterFieldDef(
key: 'plant_id',
label: 'Plant',
type: MasterFieldType.dropdown,
required: true,
showInList: true,
optionsMasterKey: 'plants',
),
MasterFieldDef(key: 'location', label: 'Location'),
_activeField,
],
),
MasterDefinition(
id: 'designations',
title: 'Designations',
subtitle: 'Employee designations',
category: 'Organization',
routeKey: 'designations',
apiPath: '/masters/designations',
module: 'designations',
icon: Icons.badge_outlined,
fields: [
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
_activeField,
],
),
MasterDefinition(
id: 'departments',
title: 'Departments',
subtitle: 'Organisation departments',
category: 'Organization',
routeKey: 'departments',
apiPath: '/masters/departments',
module: 'departments',
icon: Icons.apartment_outlined,
fields: [
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
_activeField,
],
),
MasterDefinition(
id: 'asset_categories',
title: 'Asset Categories',
subtitle: 'Fixed asset classification',
category: 'Assets',
routeKey: 'asset-categories',
apiPath: '/masters/asset-categories',
module: 'asset_categories',
icon: Icons.precision_manufacturing_outlined,
fields: [
MasterFieldDef(key: 'code', label: 'Code', required: true, showInList: true),
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
MasterFieldDef(key: 'code_prefix', label: 'Code Prefix', required: true, showInList: true),
MasterFieldDef(
key: 'default_useful_life_years',
label: 'Useful Life (Years)',
type: MasterFieldType.number,
required: true,
),
MasterFieldDef(
key: 'default_depreciation_method',
label: 'Depreciation Method',
type: MasterFieldType.dropdown,
required: true,
showInList: true,
optionsMasterKey: 'asset_depreciation_methods',
),
_activeField,
],
),
MasterDefinition(
id: 'asset_subcategories',
title: 'Asset Subcategories',
subtitle: 'Sub-classification under asset categories',
category: 'Assets',
routeKey: 'asset-subcategories',
apiPath: '/masters/asset-subcategories',
module: 'asset_subcategories',
icon: Icons.category_outlined,
fields: [
MasterFieldDef(
key: 'asset_category_id',
label: 'Asset Category',
type: MasterFieldType.dropdown,
required: true,
showInList: true,
optionsMasterKey: 'asset_categories',
),
MasterFieldDef(key: 'code', label: 'Code', required: true, showInList: true),
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
_activeField,
],
),
MasterDefinition(
id: 'delivery_terms',
title: 'Delivery Terms',
subtitle: 'Delivery incoterms and terms',
category: 'Finance & Terms',
routeKey: 'delivery-terms',
apiPath: '/masters/delivery-terms',
module: 'delivery_terms',
icon: Icons.local_shipping_outlined,
fields: [
MasterFieldDef(key: 'code', label: 'Code', required: true, showInList: true),
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
MasterFieldDef(key: 'description', label: 'Description', multiline: true),
_activeField,
],
),
MasterDefinition(
id: 'payment_terms',
title: 'Payment Terms',
subtitle: 'Vendor payment terms',
category: 'Finance & Terms',
routeKey: 'payment-terms',
apiPath: '/masters/payment-terms',
module: 'payment_terms',
icon: Icons.payments_outlined,
fields: [
MasterFieldDef(key: 'code', label: 'Code', required: true, showInList: true),
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
MasterFieldDef(
key: 'credit_days',
label: 'Credit Days',
type: MasterFieldType.number,
required: true,
showInList: true,
),
MasterFieldDef(key: 'description', label: 'Description', multiline: true),
_activeField,
],
),
MasterDefinition(
id: 'gst_rates',
title: 'GST Rates',
subtitle: 'Tax rate master',
category: 'Finance & Terms',
routeKey: 'gst-rates',
apiPath: '/masters/gst-rates',
module: 'gst_rates',
icon: Icons.percent_outlined,
fields: [
MasterFieldDef(
key: 'rate_pct',
label: 'Rate (%)',
type: MasterFieldType.number,
required: true,
showInList: true,
),
MasterFieldDef(key: 'description', label: 'Description', showInList: true),
_activeField,
],
),
];
List<String> get masterCategories =>
masterDefinitions.map((def) => def.category).toSet().toList();
String masterRecordLabel(Map<String, dynamic> row) {
final ratePct = row['rate_pct'];
if (ratePct != null) {
final rate = ratePct is num
? ratePct.toDouble()
: double.tryParse(ratePct.toString());
if (rate != null) {
return rate % 1 == 0 ? '${rate.toInt()}%' : '$rate%';
}
}
for (final key in ['name', 'item_name', 'code', 'item_code', 'description']) {
final value = row[key];
if (value != null && value.toString().trim().isNotEmpty) {
return value.toString();
}
}
return row['id']?.toString() ?? 'Record';
}
String masterCellValue(Map<String, dynamic> row, MasterFieldDef field) {
final value = row[field.key];
if (value == null || value == '') return '';
if (field.type == MasterFieldType.boolean) {
return value == true ? 'Yes' : 'No';
}
if (field.type == MasterFieldType.dropdown) {
final label = row['${field.key}_label'];
if (label != null && label.toString().isNotEmpty) return label.toString();
if (field.staticOptions != null) {
return value.toString().replaceAll('_', ' ');
}
}
return value.toString();
}
String masterStatusValue(Map<String, dynamic> row) {
final active = row['is_active'];
if (active == false) return 'inactive';
return 'active';
}