FIX_grid Details - Segment Changes

This commit is contained in:
sanjeev.p 2026-04-07 15:33:17 +05:30
parent 780159f380
commit c2521ed76b
8 changed files with 171 additions and 82 deletions

File diff suppressed because one or more lines are too long

View File

@ -938,6 +938,7 @@ class ApiService {
final searchTrimmed = search?.trim(); final searchTrimmed = search?.trim();
final loggedIdTrimmed = loggedId?.trim(); final loggedIdTrimmed = loggedId?.trim();
final endpoint = Uri.parse('${Env.apiUrl}grid'); final endpoint = Uri.parse('${Env.apiUrl}grid');
// final endpoint = Uri.parse('http://localhost/nhance_partner_be/grid');
final roleLower = roleTrimmed?.toLowerCase(); final roleLower = roleTrimmed?.toLowerCase();
final queryParameters = <String, String>{}; final queryParameters = <String, String>{};
@ -1086,7 +1087,6 @@ class ApiService {
} }
final url = Uri.parse('${Env.apiUrl}agent/exportRetentionRateExcel'); final url = Uri.parse('${Env.apiUrl}agent/exportRetentionRateExcel');
// final url = Uri.parse('http://localhost/nhance_partner_be/agent/exportRetentionRateExcel');
final headers = { final headers = {
'Authorization': 'Bearer ${_token ?? ''}', 'Authorization': 'Bearer ${_token ?? ''}',
'app-signature': Env.App_Signature, 'app-signature': Env.App_Signature,
@ -1122,7 +1122,6 @@ class ApiService {
} }
final url = Uri.parse('${Env.apiUrl}agent/importRetentionRateExcel'); final url = Uri.parse('${Env.apiUrl}agent/importRetentionRateExcel');
// final url = Uri.parse('http://localhost/nhance_partner_be/agent/importRetentionRateExcel');
try { try {
final request = http.MultipartRequest('POST', url); final request = http.MultipartRequest('POST', url);
request.headers.addAll({ request.headers.addAll({
@ -1141,6 +1140,15 @@ class ApiService {
filename: file.name, filename: file.name,
), ),
); );
// Backward/forward compatibility:
// some backend versions expect `retention_rate_excel`.
request.files.add(
http.MultipartFile.fromBytes(
'retention_rate_excel',
file.bytes!,
filename: file.name,
),
);
final streamedResponse = await request.send(); final streamedResponse = await request.send();
final responseBody = await streamedResponse.stream.bytesToString(); final responseBody = await streamedResponse.stream.bytesToString();
@ -1202,6 +1210,7 @@ class ApiService {
Future<Map<String, dynamic>> updateAgentVehicleRetention({ Future<Map<String, dynamic>> updateAgentVehicleRetention({
required String agentId, required String agentId,
required String vehicleTypeId, required String vehicleTypeId,
required String segmentId,
required String retentionRate, required String retentionRate,
required String updatedBy, required String updatedBy,
}) async { }) async {
@ -1217,6 +1226,7 @@ class ApiService {
final body = { final body = {
'agent_id': agentId, 'agent_id': agentId,
'vehicle_type_id': vehicleTypeId, 'vehicle_type_id': vehicleTypeId,
'segment_id': segmentId,
'retention_rate': retentionRate, 'retention_rate': retentionRate,
'updated_by': updatedBy, 'updated_by': updatedBy,
}; };
@ -1547,7 +1557,6 @@ class ApiService {
if (_token == null) await _initializeToken(); if (_token == null) await _initializeToken();
final url = Uri.parse('${Env.apiUrl}partner/$id/details'); final url = Uri.parse('${Env.apiUrl}partner/$id/details');
// final url = Uri.parse('http://localhost/nhance_partner_be/partner/$id/details');
final headers = { final headers = {
'Authorization': 'Bearer $_token', 'Authorization': 'Bearer $_token',
@ -1563,7 +1572,6 @@ class ApiService {
if (_token == null) await _initializeToken(); if (_token == null) await _initializeToken();
final url = Uri.parse('${Env.apiUrl}partner/$id/policies'); final url = Uri.parse('${Env.apiUrl}partner/$id/policies');
// final url = Uri.parse('http://localhost/nhance_partner_be/partner/$id/details/policies');
final headers = { final headers = {
'Authorization': 'Bearer $_token', 'Authorization': 'Bearer $_token',
@ -1583,7 +1591,7 @@ class ApiService {
if (_token == null) await _initializeToken(); if (_token == null) await _initializeToken();
final url = Uri.parse('${Env.apiUrl}partner/$id/renewals?days=$days'); final url = Uri.parse('${Env.apiUrl}partner/$id/renewals?days=$days');
// final url = Uri.parse('http://localhost/nhance_partner_be/partner/$id/renewals?days=$days');
final headers = { final headers = {
'Authorization': 'Bearer $_token', 'Authorization': 'Bearer $_token',
'app-signature': Env.App_Signature, 'app-signature': Env.App_Signature,
@ -1604,7 +1612,7 @@ class ApiService {
? '?financial_year=${Uri.encodeQueryComponent(financialYear)}' ? '?financial_year=${Uri.encodeQueryComponent(financialYear)}'
: ''; : '';
final url = Uri.parse('${Env.apiUrl}partner/$id/earnings$q'); final url = Uri.parse('${Env.apiUrl}partner/$id/earnings$q');
// final url = Uri.parse('http://localhost/nhance_partner_be/partner/$id/earnings$q');
final headers = { final headers = {
'Authorization': 'Bearer $_token', 'Authorization': 'Bearer $_token',
'app-signature': Env.App_Signature, 'app-signature': Env.App_Signature,
@ -2145,9 +2153,6 @@ class ApiService {
'${Env.apiUrl}invoice/getAgentUnusedCommissionList?manager_id=$id', '${Env.apiUrl}invoice/getAgentUnusedCommissionList?manager_id=$id',
); );
// url = Uri.parse(
// 'http://localhost/nhance_partner_be/invoice/getAgentUnusedCommissionList?manager_id=$id',
// );
print('fetchAGENTNameDropDown 2'); print('fetchAGENTNameDropDown 2');
final headers = { final headers = {
@ -2288,7 +2293,7 @@ class ApiService {
if (managerId != null) 'manager_id': managerId.toString(), if (managerId != null) 'manager_id': managerId.toString(),
}; };
final url = Uri.parse('${Env.apiUrl}invoice/view').replace( final url = Uri.parse('${Env.apiUrl}invoice/view').replace(
queryParameters: queryParameters, queryParameters: queryParameters,
); );
@ -2302,7 +2307,6 @@ class ApiService {
Future<Map<String, dynamic>> getCreateOrUpdate(data) async { Future<Map<String, dynamic>> getCreateOrUpdate(data) async {
final url = Uri.parse('${Env.apiUrl}invoice/create-or-update'); final url = Uri.parse('${Env.apiUrl}invoice/create-or-update');
// final url = Uri.parse('http://localhost/nhance_partner_be/invoice/create-or-update');
// final token = await getToken(); // Fetch token // final token = await getToken(); // Fetch token

View File

@ -188,14 +188,14 @@ class AgentListState extends ConsumerState<AgentList> {
if (mounted) { if (mounted) {
ToastHelper.showSuccessToast( ToastHelper.showSuccessToast(
context, context,
'Rentation rate Excel downloaded', 'Retention rate Excel downloaded',
); );
} }
} catch (e) { } catch (e) {
if (mounted) { if (mounted) {
ToastHelper.showErrorToast( ToastHelper.showErrorToast(
context, context,
'Failed to export rentation rate Excel', 'Failed to export retention rate Excel',
); );
} }
} }
@ -234,26 +234,30 @@ class AgentListState extends ConsumerState<AgentList> {
final report = (response['report'] is Map<String, dynamic>) final report = (response['report'] is Map<String, dynamic>)
? response['report'] as Map<String, dynamic> ? response['report'] as Map<String, dynamic>
: <String, dynamic>{}; : <String, dynamic>{};
final inserted = (data['inserted_cells'] ?? data['inserted_rows'] ?? 0);
final inserted = (data['inserted_cells'] ?? 0).toString(); final updated = (data['updated_cells'] ?? data['updated_rows'] ?? 0);
final updated = (data['updated_cells'] ?? 0).toString(); final message = (response['message'] ?? '').toString().trim();
if (mounted) { if (mounted) {
ToastHelper.showSuccessToast( ToastHelper.showSuccessToast(
context, context,
'Import done', message.isNotEmpty
? message
: 'Import done (Inserted: $inserted, Updated: $updated)',
); );
} }
// doN'T Delete This function And Related Codes if (report.isNotEmpty && mounted) {
// await _showRetentionImportReportDialog(data, report); await _showRetentionImportReportDialog(data, report);
}
refresh(); refresh();
} else { } else {
if (mounted) { if (mounted) {
ToastHelper.showErrorToast(context, 'Import failed'); final message = (response['message'] ?? 'Import failed').toString();
ToastHelper.showErrorToast(context, message);
} }
} }
} catch (e) { } catch (e) {
if (mounted) { if (mounted) {
ToastHelper.showErrorToast(context, 'Failed to import rentation rate'); ToastHelper.showErrorToast(context, 'Failed to import retention rate');
} }
} finally { } finally {
if (mounted) { if (mounted) {
@ -285,7 +289,14 @@ class AgentListState extends ConsumerState<AgentList> {
.where((e) => e.trim().isNotEmpty) .where((e) => e.trim().isNotEmpty)
.toList() ?? .toList() ??
<String>[]; <String>[];
final unknownVehicleTypes = (report['unknown_vehicle_types'] as List?) final unknownVehicleTypes = ((report['unknown_vehicle_types'] ??
report['unknown_vehicle_type_names']) as List?)
?.map((e) => e.toString())
.where((e) => e.trim().isNotEmpty)
.toList() ??
<String>[];
final unknownSegments = ((report['unknown_segments'] ??
report['unknown_segment_names']) as List?)
?.map((e) => e.toString()) ?.map((e) => e.toString())
.where((e) => e.trim().isNotEmpty) .where((e) => e.trim().isNotEmpty)
.toList() ?? .toList() ??
@ -322,13 +333,22 @@ class AgentListState extends ConsumerState<AgentList> {
if (unknownVehicleTypes.isNotEmpty) { if (unknownVehicleTypes.isNotEmpty) {
lines.add(''); lines.add('');
lines.add('Unknown Vehicle Types (header):'); lines.add('Unknown Vehicle Types:');
lines.addAll(unknownVehicleTypes.take(10).map((e) => '- $e')); lines.addAll(unknownVehicleTypes.take(10).map((e) => '- $e'));
if (unknownVehicleTypes.length > 10) { if (unknownVehicleTypes.length > 10) {
lines.add('- ...and ${unknownVehicleTypes.length - 10} more'); lines.add('- ...and ${unknownVehicleTypes.length - 10} more');
} }
} }
if (unknownSegments.isNotEmpty) {
lines.add('');
lines.add('Unknown Segments:');
lines.addAll(unknownSegments.take(10).map((e) => '- $e'));
if (unknownSegments.length > 10) {
lines.add('- ...and ${unknownSegments.length - 10} more');
}
}
if (invalidCells.isNotEmpty) { if (invalidCells.isNotEmpty) {
lines.add(''); lines.add('');
lines.add('Invalid Cell Samples:'); lines.add('Invalid Cell Samples:');
@ -366,7 +386,7 @@ class AgentListState extends ConsumerState<AgentList> {
context: context, context: context,
builder: (ctx) { builder: (ctx) {
return AlertDialog( return AlertDialog(
title: const Text('Rentation Rate Import Report'), title: const Text('Retention Rate Import Report'),
content: SizedBox( content: SizedBox(
width: 520, width: 520,
child: SingleChildScrollView( child: SingleChildScrollView(

View File

@ -75,7 +75,7 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
GlobalKey<DropdownSearchState<Map<String, dynamic>>>(); GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
List<Map<String, dynamic>> _vehicleTypes = []; List<Map<String, dynamic>> _vehicleTypes = [];
final Map<int, TextEditingController> _rateControllers = {}; final Map<String, TextEditingController> _rateControllers = {};
List<Map<String, dynamic>> _salesExecutives = []; List<Map<String, dynamic>> _salesExecutives = [];
dynamic _selectedSalesExecutiveId; dynamic _selectedSalesExecutiveId;
@ -157,35 +157,46 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
} catch (_) {} } catch (_) {}
} }
void _initRateControllersFromTypes({Map<int, String>? initial}) { String _retentionKey(int vehicleTypeId, int segmentId) => '${vehicleTypeId}_$segmentId';
int _readInt(dynamic value) => int.tryParse(value?.toString() ?? '') ?? 0;
String _displayVehicleSegment(Map<String, dynamic> vt) {
final name = (vt['vehicle_type'] ?? '-').toString();
final segment = (vt['segment'] ?? '').toString().trim();
if (segment.isEmpty) return name;
return '$name - $segment';
}
void _initRateControllersFromTypes({Map<String, String>? initial}) {
for (final c in _rateControllers.values) { for (final c in _rateControllers.values) {
c.dispose(); c.dispose();
} }
_rateControllers.clear(); _rateControllers.clear();
for (final vt in _vehicleTypes) { for (final vt in _vehicleTypes) {
final id = int.tryParse(vt['id'].toString()) ?? 0; final vehicleTypeId = _readInt(vt['vehicle_type_id'] ?? vt['id']);
if (id == 0) continue; final segmentId = _readInt(vt['segment_id']);
final text = initial?[id] ?? ''; if (vehicleTypeId == 0 || segmentId == 0) continue;
_rateControllers[id] = TextEditingController(text: text); final key = _retentionKey(vehicleTypeId, segmentId);
final text = initial?[key] ?? '';
_rateControllers[key] = TextEditingController(text: text);
} }
} }
/// Builds vehicle_type_id retention % text from [findAgent] (or compatible) payload. /// Builds (vehicle_type_id + segment_id) retention % text from [findAgent].
Map<int, String> _retentionMapFromAgentData(Map<String, dynamic> data) { Map<String, String> _retentionMapFromAgentData(Map<String, dynamic> data) {
final Map<int, String> initial = {}; final Map<String, String> initial = {};
final raw = data['retention_by_vehicle'] ?? data['retentionByVehicle']; final raw = data['retention_by_vehicle'] ?? data['retentionByVehicle'];
if (raw is! List) return initial; if (raw is! List) return initial;
for (final row in raw) { for (final row in raw) {
if (row is! Map) continue; if (row is! Map) continue;
final m = Map<String, dynamic>.from(row); final m = Map<String, dynamic>.from(row);
final vid = int.tryParse( final vid = _readInt(m['vehicle_type_id'] ?? m['vehicleTypeId']);
(m['vehicle_type_id'] ?? m['vehicleTypeId'] ?? '').toString(), final sid = _readInt(m['segment_id'] ?? m['segmentId']);
) ?? if (vid == 0 || sid == 0) continue;
0;
if (vid == 0) continue;
final rate = m['retention_rate'] ?? m['retentionRate']; final rate = m['retention_rate'] ?? m['retentionRate'];
if (rate == null) continue; if (rate == null) continue;
initial[vid] = rate.toString(); initial[_retentionKey(vid, sid)] = rate.toString();
} }
return initial; return initial;
} }
@ -238,9 +249,13 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
List<Map<String, dynamic>> get _filteredVehicleTypes { List<Map<String, dynamic>> get _filteredVehicleTypes {
final q = _retentionSearchCtrl.text.trim().toLowerCase(); final q = _retentionSearchCtrl.text.trim().toLowerCase();
if (q.isEmpty) return _vehicleTypes; if (q.isEmpty) return _vehicleTypes;
return _vehicleTypes final terms = q.split(RegExp(r'\s+')).where((t) => t.isNotEmpty).toList();
.where((vt) => (vt['vehicle_type'] ?? '').toString().toLowerCase().contains(q)) return _vehicleTypes.where((vt) {
.toList(); final vehicle = (vt['vehicle_type'] ?? '').toString().toLowerCase();
final segment = (vt['segment'] ?? '').toString().toLowerCase();
final searchable = '$vehicle $segment';
return terms.every(searchable.contains);
}).toList();
} }
@override @override
@ -261,16 +276,19 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
List<Map<String, dynamic>> _collectBulkRetentionPayload() { List<Map<String, dynamic>> _collectBulkRetentionPayload() {
final out = <Map<String, dynamic>>[]; final out = <Map<String, dynamic>>[];
for (final vt in _vehicleTypes) { for (final vt in _vehicleTypes) {
final id = int.tryParse(vt['id'].toString()) ?? 0; final vehicleTypeId = _readInt(vt['vehicle_type_id'] ?? vt['id']);
if (id == 0) continue; final segmentId = _readInt(vt['segment_id']);
final ctrl = _rateControllers[id]; if (vehicleTypeId == 0 || segmentId == 0) continue;
final key = _retentionKey(vehicleTypeId, segmentId);
final ctrl = _rateControllers[key];
if (ctrl == null) continue; if (ctrl == null) continue;
final t = ctrl.text.trim(); final t = ctrl.text.trim();
if (t.isEmpty) continue; if (t.isEmpty) continue;
final v = double.tryParse(t); final v = double.tryParse(t);
if (v == null || v < 0 || v > 100) continue; if (v == null || v < 0 || v > 100) continue;
out.add({ out.add({
'vehicle_type_id': id, 'vehicle_type_id': vehicleTypeId,
'segment_id': segmentId,
'retention_rate': v, 'retention_rate': v,
}); });
} }
@ -360,7 +378,7 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
return null; return null;
} }
Future<void> _saveRowRetention(int vehicleTypeId) async { Future<void> _saveRowRetention(Map<String, dynamic> vt) async {
if (!_retentionTableEnabled) { if (!_retentionTableEnabled) {
ToastHelper.showWarningToast( ToastHelper.showWarningToast(
context, context,
@ -369,7 +387,14 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
return; return;
} }
if (_savingAllRetention) return; if (_savingAllRetention) return;
final ctrl = _rateControllers[vehicleTypeId]; final vehicleTypeId = _readInt(vt['vehicle_type_id'] ?? vt['id']);
final segmentId = _readInt(vt['segment_id']);
if (vehicleTypeId == 0 || segmentId == 0) {
ToastHelper.showErrorToast(context, 'Vehicle type or segment missing');
return;
}
final key = _retentionKey(vehicleTypeId, segmentId);
final ctrl = _rateControllers[key];
if (ctrl == null) return; if (ctrl == null) return;
final t = ctrl.text.trim(); final t = ctrl.text.trim();
if (t.isEmpty) { if (t.isEmpty) {
@ -391,6 +416,7 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
final res = await _api.updateAgentVehicleRetention( final res = await _api.updateAgentVehicleRetention(
agentId: _loadedAgentPk!, agentId: _loadedAgentPk!,
vehicleTypeId: '$vehicleTypeId', vehicleTypeId: '$vehicleTypeId',
segmentId: '$segmentId',
retentionRate: t, retentionRate: t,
updatedBy: userId, updatedBy: userId,
); );
@ -1126,7 +1152,7 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
SizedBox( SizedBox(
width: 220, width: 220,
child: ThemedSearchField( child: ThemedSearchField(
hintText: 'Search vehicle type', hintText: 'Search vehicle type and segment',
backgroundColor: Colors.white, backgroundColor: Colors.white,
txtHeight: 34, txtHeight: 34,
controller: _retentionSearchCtrl, controller: _retentionSearchCtrl,
@ -1267,9 +1293,11 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
} }
Widget _retentionMobileCard(Map<String, dynamic> vt) { Widget _retentionMobileCard(Map<String, dynamic> vt) {
final id = int.tryParse(vt['id'].toString()) ?? 0; final vehicleTypeId = _readInt(vt['vehicle_type_id'] ?? vt['id']);
final name = (vt['vehicle_type'] ?? '-').toString(); final segmentId = _readInt(vt['segment_id']);
final ctrl = _rateControllers[id]; final key = _retentionKey(vehicleTypeId, segmentId);
final name = _displayVehicleSegment(vt);
final ctrl = _rateControllers[key];
if (ctrl == null) return const SizedBox.shrink(); if (ctrl == null) return const SizedBox.shrink();
return Padding( return Padding(
@ -1305,7 +1333,7 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
child: TextButton( child: TextButton(
onPressed: (_retentionTableEnabled && !_retentionActionsBusy) onPressed: (_retentionTableEnabled && !_retentionActionsBusy)
? () => _saveRowRetention(id) ? () => _saveRowRetention(vt)
: null, : null,
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: const Color(0xFF2E7D6E), foregroundColor: const Color(0xFF2E7D6E),
@ -1337,7 +1365,7 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
Expanded( Expanded(
flex: 5, flex: 5,
child: Text( child: Text(
'Vehicle type', 'Vehicle type / Segment',
style: _headerStyle, style: _headerStyle,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -1365,9 +1393,11 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
} }
Widget _retentionDataRow(Map<String, dynamic> vt) { Widget _retentionDataRow(Map<String, dynamic> vt) {
final id = int.tryParse(vt['id'].toString()) ?? 0; final vehicleTypeId = _readInt(vt['vehicle_type_id'] ?? vt['id']);
final name = (vt['vehicle_type'] ?? '-').toString(); final segmentId = _readInt(vt['segment_id']);
final ctrl = _rateControllers[id]; final key = _retentionKey(vehicleTypeId, segmentId);
final name = _displayVehicleSegment(vt);
final ctrl = _rateControllers[key];
if (ctrl == null) return const SizedBox.shrink(); if (ctrl == null) return const SizedBox.shrink();
return Container( return Container(
@ -1409,7 +1439,7 @@ class _AgentDetailsScreenState extends ConsumerState<AgentDetailsScreen> {
child: Center( child: Center(
child: TextButton( child: TextButton(
onPressed: (_retentionTableEnabled && !_retentionActionsBusy) onPressed: (_retentionTableEnabled && !_retentionActionsBusy)
? () => _saveRowRetention(id) ? () => _saveRowRetention(vt)
: null, : null,
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: const Color(0xFF2E7D6E), foregroundColor: const Color(0xFF2E7D6E),

View File

@ -444,6 +444,7 @@ class _RenewalAlertsCard extends StatelessWidget {
const SizedBox(width: 8), const SizedBox(width: 8),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text('Renewal Alerts', style: _chartHeader), Text('Renewal Alerts', style: _chartHeader),
Text( Text(
@ -512,6 +513,7 @@ class _RenewalAlertsCard extends StatelessWidget {
children: [ children: [
SizedBox(width: 40, child: Text('S.No', style: _tableHeadStyle)), SizedBox(width: 40, child: Text('S.No', style: _tableHeadStyle)),
Expanded(flex: 2, child: Text('Policy No.', style: _tableHeadStyle)), Expanded(flex: 2, child: Text('Policy No.', style: _tableHeadStyle)),
Expanded(flex: 2, child: Text('Vehicle Type', style: _tableHeadStyle)),
Expanded(flex: 2, child: Text('Policy Holder Name', style: _tableHeadStyle)), Expanded(flex: 2, child: Text('Policy Holder Name', style: _tableHeadStyle)),
Expanded(flex: 2, child: Text('Expiry Date', style: _tableHeadStyle)), Expanded(flex: 2, child: Text('Expiry Date', style: _tableHeadStyle)),
Expanded( Expanded(
@ -587,6 +589,14 @@ class _RenewalTableRow extends StatelessWidget {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
), ),
Expanded(
flex: 2,
child: Text(
renewal['vehicle_type']?.toString() ?? '--',
style: _tableTeal,
overflow: TextOverflow.ellipsis,
),
),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(

View File

@ -182,6 +182,9 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
(item['invoice_no'] ?? '-').toLowerCase().contains( (item['invoice_no'] ?? '-').toLowerCase().contains(
query.toLowerCase(), query.toLowerCase(),
) || ) ||
(item['vehicle_types'] ?? '-').toLowerCase().contains(
query.toLowerCase(),
) ||
(item['invoice_amount_indian_format'] ?? '-') (item['invoice_amount_indian_format'] ?? '-')
.toLowerCase() .toLowerCase()
.contains(query.toLowerCase()) || .contains(query.toLowerCase()) ||
@ -742,6 +745,7 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
displayHeaders: [ displayHeaders: [
"S.No", "S.No",
"Invoice No", "Invoice No",
"Vehicle Type",
"Invoice Date", "Invoice Date",
"Broker Name", "Broker Name",
"POS Name", "POS Name",
@ -756,6 +760,7 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
keys: [ keys: [
"id", "id",
"invoice_no", "invoice_no",
"vehicle_types",
"invoice_date", "invoice_date",
"broker_name", "broker_name",
"pos_name", "pos_name",
@ -789,6 +794,10 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
flex: 3, flex: 3,
child: Text('Invoice No', style: _headerStyle), child: Text('Invoice No', style: _headerStyle),
), ),
Expanded(
flex: 3,
child: Text('Vehicle Type', style: _headerStyle),
),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text('Broker Name', style: _headerStyle), child: Text('Broker Name', style: _headerStyle),
@ -885,6 +894,15 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
maxLines: 3, maxLines: 3,
), ),
), ),
Expanded(
flex: 3,
child: Text(
_displayText(item['vehicle_types']),
style: _dataBold,
softWrap: true,
maxLines: 3,
),
),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(

View File

@ -137,6 +137,7 @@ class _PayOutDetailsViewState extends ConsumerState<PayOutDetailsView> {
} }
filteredPolicies = masterPolicies.where((item) { filteredPolicies = masterPolicies.where((item) {
return (item['policy_no'] ?? '').toString().contains(q) || return (item['policy_no'] ?? '').toString().contains(q) ||
(item['vehicle_type'] ?? '').toString().contains(q) ||
(item['customer_name'] ?? '').toString().contains(q) || (item['customer_name'] ?? '').toString().contains(q) ||
(item['agent_name'] ?? '').toString().contains(q) || (item['agent_name'] ?? '').toString().contains(q) ||
(item['insurer_name'] ?? '').toString().contains(q) || (item['insurer_name'] ?? '').toString().contains(q) ||
@ -186,10 +187,11 @@ class _PayOutDetailsViewState extends ConsumerState<PayOutDetailsView> {
List<double> _columnWidths(double maxWidth) { List<double> _columnWidths(double maxWidth) {
const sidePadding = 32.0; // 16 left + 16 right const sidePadding = 32.0; // 16 left + 16 right
final usable = (maxWidth - sidePadding).clamp(720.0, 2000.0); final usable = (maxWidth - sidePadding).clamp(720.0, 2000.0);
const totalFlex = 2 + 14 + 10 + 20 + 16 + 11 + 11; const totalFlex = 2 + 14 + 12 + 10 + 20 + 16 + 11 + 11;
return [ return [
usable * (2 / totalFlex), // S.NO usable * (2 / totalFlex), // S.NO
usable * (14 / totalFlex), // POLICY NO usable * (14 / totalFlex), // POLICY NO
usable * (12 / totalFlex), // VEHICLE TYPE
usable * (10 / totalFlex), // POLICY DATE usable * (10 / totalFlex), // POLICY DATE
usable * (20 / totalFlex), // PARTNER usable * (20 / totalFlex), // PARTNER
usable * (16 / totalFlex), // CUSTOMER usable * (16 / totalFlex), // CUSTOMER
@ -252,11 +254,12 @@ class _PayOutDetailsViewState extends ConsumerState<PayOutDetailsView> {
children: [ children: [
_headerText('S.NO', w[0]), _headerText('S.NO', w[0]),
_headerText('POLICY NO', w[1]), _headerText('POLICY NO', w[1]),
_headerText('POLICY DATE', w[2]), _headerText('VEHICLE TYPE', w[2]),
_headerText('PARTNER', w[3]), _headerText('POLICY DATE', w[3]),
_headerText('CUSTOMER', w[4]), _headerText('PARTNER', w[4]),
_headerText('PREMIUM (₹)', w[5], align: TextAlign.right), _headerText('CUSTOMER', w[5]),
_headerText('PAYOUT (₹)', w[6], align: TextAlign.right), _headerText('PREMIUM (₹)', w[6], align: TextAlign.right),
_headerText('PAYOUT (₹)', w[7], align: TextAlign.right),
], ],
), ),
); );
@ -274,22 +277,23 @@ class _PayOutDetailsViewState extends ConsumerState<PayOutDetailsView> {
children: [ children: [
_cell('${index + 1}', w[0]), _cell('${index + 1}', w[0]),
_cell(p['policy_no']?.toString(), w[1]), _cell(p['policy_no']?.toString(), w[1]),
_cell(_formatDate(p['issued_date']?.toString()), w[2]), _cell(p['vehicle_type']?.toString(), w[2]),
_cell(_formatDate(p['issued_date']?.toString()), w[3]),
_cell( _cell(
(p['agent_code'] != null && p['agent_name'] != null) (p['agent_code'] != null && p['agent_name'] != null)
? '${p['agent_code']} - ${p['agent_name']}' ? '${p['agent_code']} - ${p['agent_name']}'
: (p['agent_name'] ?? '-').toString(), : (p['agent_name'] ?? '-').toString(),
w[3], w[4],
), ),
_cell(p['customer_name']?.toString(), w[4]), _cell(p['customer_name']?.toString(), w[5]),
_cell( _cell(
_amountText(p['premium_amount']), _amountText(p['premium_amount']),
w[5], w[6],
align: TextAlign.right, align: TextAlign.right,
), ),
_cell( _cell(
_amountText(p['commission_amount']), _amountText(p['commission_amount']),
w[6], w[7],
align: TextAlign.right, align: TextAlign.right,
color: const Color(0xFF009B77), color: const Color(0xFF009B77),
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -321,6 +325,7 @@ class _PayOutDetailsViewState extends ConsumerState<PayOutDetailsView> {
return { return {
'sno': 0, 'sno': 0,
'policy_no': p['policy_no'], 'policy_no': p['policy_no'],
'vehicle_type': p['vehicle_type'],
'policy_date': _formatDate(p['issued_date']?.toString()), 'policy_date': _formatDate(p['issued_date']?.toString()),
'partner': (p['agent_code'] != null && p['agent_name'] != null) 'partner': (p['agent_code'] != null && p['agent_name'] != null)
? '${p['agent_code']} - ${p['agent_name']}' ? '${p['agent_code']} - ${p['agent_name']}'
@ -431,6 +436,7 @@ class _PayOutDetailsViewState extends ConsumerState<PayOutDetailsView> {
displayHeaders: const [ displayHeaders: const [
'S.NO', 'S.NO',
'POLICY NO', 'POLICY NO',
'VEHICLE TYPE',
'POLICY DATE', 'POLICY DATE',
'PARTNER', 'PARTNER',
'CUSTOMER', 'CUSTOMER',
@ -440,6 +446,7 @@ class _PayOutDetailsViewState extends ConsumerState<PayOutDetailsView> {
keys: const [ keys: const [
'sno', 'sno',
'policy_no', 'policy_no',
'vehicle_type',
'policy_date', 'policy_date',
'partner', 'partner',
'customer', 'customer',

View File

@ -117,10 +117,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: characters name: characters
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.4.1"
charcode: charcode:
dependency: transitive dependency: transitive
description: description:
@ -780,26 +780,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.17" version: "0.12.19"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.11.1" version: "0.13.0"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.16.0" version: "1.17.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@ -1297,10 +1297,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.6" version: "0.7.10"
toastification: toastification:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1502,5 +1502,5 @@ packages:
source: hosted source: hosted
version: "3.1.3" version: "3.1.3"
sdks: sdks:
dart: ">=3.8.1 <4.0.0" dart: ">=3.9.0-0 <4.0.0"
flutter: ">=3.32.0" flutter: ">=3.32.0"