Location api change

This commit is contained in:
Surendiran 2026-07-20 12:12:20 +05:30
parent 4046633340
commit 1d44187942
4 changed files with 87 additions and 20 deletions

View File

@ -62,7 +62,10 @@ class MasterCrudRemoteDataSource {
final items = list
.whereType<Map<String, dynamic>>()
.map((item) => Map<String, dynamic>.from(item))
.map((item) => _sanitizeLocationRow(
definition,
Map<String, dynamic>.from(item),
))
.toList();
final pagination = parsePagination(
@ -104,7 +107,12 @@ class MasterCrudRemoteDataSource {
return list
.whereType<Map>()
.map((item) => Map<String, dynamic>.from(item))
.map(
(item) => _sanitizeLocationRow(
definition,
Map<String, dynamic>.from(item),
),
)
.where(isActiveOptionRow)
.toList();
}
@ -114,7 +122,7 @@ class MasterCrudRemoteDataSource {
String id,
) async {
final response = await dio.get('${definition.apiPath}/$id');
return _extractData(response.data);
return _sanitizeLocationRow(definition, _extractData(response.data));
}
Future<Map<String, dynamic>> create(
@ -125,7 +133,7 @@ class MasterCrudRemoteDataSource {
definition.apiPath,
data: payload..removeWhere((_, value) => value == null),
);
return _extractData(response.data);
return _sanitizeLocationRow(definition, _extractData(response.data));
}
Future<Map<String, dynamic>> update(
@ -137,7 +145,7 @@ class MasterCrudRemoteDataSource {
'${definition.apiPath}/$id',
data: payload..removeWhere((_, value) => value == null),
);
return _extractData(response.data);
return _sanitizeLocationRow(definition, _extractData(response.data));
}
Future<void> delete(MasterDefinition definition, String id) async {
@ -197,4 +205,16 @@ class MasterCrudRemoteDataSource {
if (data is Map<String, dynamic>) return Map<String, dynamic>.from(data);
return Map<String, dynamic>.from(body);
}
/// Locations API no longer nests warehouses under plants.
Map<String, dynamic> _sanitizeLocationRow(
MasterDefinition definition,
Map<String, dynamic> row,
) {
if (definition.id != 'locations') return row;
row.remove('parent_id');
row.remove('plant_id');
row.remove('plant');
return row;
}
}

View File

@ -34,7 +34,7 @@ class MasterFieldDef {
final bool showInForm;
/// When true, shown in the form but not editable (value set by other fields).
final bool readOnly;
/// Master key used to populate dropdown options (e.g. `plants` for plant_id).
/// Master key used to populate dropdown options (e.g. `locations` for FKs).
final String? optionsMasterKey;
/// Extra query parameters when loading [optionsMasterKey] options.
final Map<String, dynamic>? optionsQueryParams;
@ -48,7 +48,7 @@ class MasterFieldDef {
/// Show this field only when [visibleWhenFieldKey] equals [visibleWhenValue].
final String? visibleWhenFieldKey;
final String? visibleWhenValue;
/// Nested object key on list rows for display (e.g. `plant` for `parent_id`).
/// Nested object key on list rows for display (e.g. `gst_rate` for `gst_rate_id`).
final String? listNestedKey;
/// Cache key for dropdown option rows (includes query params when set).
@ -376,32 +376,51 @@ const masterDefinitions = <MasterDefinition>[
MasterFieldDef(key: 'code', label: 'Code', required: true, showInList: true),
MasterFieldDef(key: 'name', label: 'Name', required: true, showInList: true),
MasterFieldDef(
key: 'parent_id',
label: 'Parent Plant',
type: MasterFieldType.dropdown,
key: 'gstin',
label: 'GSTIN',
showInList: true,
optionsMasterKey: 'locations',
optionsQueryParams: const {'type': 'plant'},
listNestedKey: 'plant',
visibleWhenFieldKey: 'type',
visibleWhenValue: 'warehouse',
required: true,
visibleWhenValue: 'plant',
),
MasterFieldDef(
key: 'city',
label: 'City',
showInList: true,
visibleWhenFieldKey: 'type',
visibleWhenValue: 'plant',
),
MasterFieldDef(key: 'gstin', label: 'GSTIN', showInList: true),
MasterFieldDef(key: 'city', label: 'City', showInList: true),
MasterFieldDef(
key: 'state',
label: 'State',
type: MasterFieldType.dropdown,
optionsMasterKey: 'location_states',
showInList: true,
visibleWhenFieldKey: 'type',
visibleWhenValue: 'plant',
),
MasterFieldDef(
key: 'address',
label: 'Address',
multiline: true,
visibleWhenFieldKey: 'type',
visibleWhenValue: 'plant',
),
MasterFieldDef(
key: 'pincode',
label: 'Pincode',
visibleWhenFieldKey: 'type',
visibleWhenValue: 'plant',
),
MasterFieldDef(
key: 'phone',
label: 'Phone',
visibleWhenFieldKey: 'type',
visibleWhenValue: 'plant',
),
MasterFieldDef(key: 'address', label: 'Address', multiline: true),
MasterFieldDef(key: 'pincode', label: 'Pincode'),
MasterFieldDef(key: 'phone', label: 'Phone'),
MasterFieldDef(
key: 'location',
label: 'Location Detail',
showInList: true,
visibleWhenFieldKey: 'type',
visibleWhenValue: 'warehouse',
),

View File

@ -301,6 +301,8 @@ class MasterFormNotifier extends FamilyAsyncNotifier<MasterFormState, MasterForm
}
}
_sanitizeLocationValues(values);
// Load after values so Items category options use is_asset_item.
final dropdownOptions = await _loadDropdownOptions(values: values);
@ -455,6 +457,14 @@ class MasterFormNotifier extends FamilyAsyncNotifier<MasterFormState, MasterForm
}
}
/// Warehouses are no longer nested under plants drop obsolete keys.
void _sanitizeLocationValues(Map<String, dynamic> values) {
if (_definition.id != 'locations') return;
values.remove('parent_id');
values.remove('plant_id');
values.remove('plant');
}
void updateValue(String key, dynamic value) {
final current = state.valueOrNull;
if (current == null) return;
@ -469,6 +479,11 @@ class MasterFormNotifier extends FamilyAsyncNotifier<MasterFormState, MasterForm
_clearHiddenFieldValues(values);
}
if (key == 'type' && _definition.id == 'locations') {
_clearHiddenFieldValues(values);
_sanitizeLocationValues(values);
}
// Asset Item toggles Items category list between STOCK / ASSET
// and hides stock-only fields (min order qty / reorder level).
if (key == 'is_asset_item' && _definition.id == 'items') {
@ -551,6 +566,14 @@ class MasterFormNotifier extends FamilyAsyncNotifier<MasterFormState, MasterForm
MasterFieldType.text => value.toString().trim(),
};
}
// Never send plant nesting fields for locations (API breaking change).
if (_definition.id == 'locations') {
payload.remove('parent_id');
payload.remove('plant_id');
payload.remove('plant');
}
return payload;
}

View File

@ -72,6 +72,11 @@ class MasterRemoteDataSource {
for (final item in rows) {
if (!isActiveOptionRow(item)) continue;
// Ignore obsolete plant nesting fields if the API still returns them.
item.remove('parent_id');
item.remove('plant_id');
item.remove('plant');
final id = item['id']?.toString() ?? '';
final name = _optionLabel(item);
if (id.isEmpty || name.isEmpty) continue;