Commit b35acfea authored by Sai Srinivas's avatar Sai Srinivas
Browse files

local fix

parents ebb11608 2a087139
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<uses-feature <uses-feature
android:name="android.hardware.camera" android:name="android.hardware.camera"
...@@ -12,16 +14,18 @@ ...@@ -12,16 +14,18 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID" /> <uses-permission android:name="com.google.android.gms.permission.AD_ID" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission tools:node="remove" android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission tools:node="remove" android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission tools:node="remove" android:name="android.permission.READ_MEDIA_AUDIO"/>
<uses-permission tools:node="remove" android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application <application
android:name="${applicationName}" android:name="${applicationName}"
...@@ -77,6 +81,12 @@ ...@@ -77,6 +81,12 @@
</intent-filter> </intent-filter>
</activity> </activity>
<service
android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
android:foregroundServiceType="location"
android:exported="false"/>
<meta-data <meta-data
android:name="flutter_deeplinking_enabled" android:name="flutter_deeplinking_enabled"
android:value="true" /> android:value="true" />
......
<svg id="Layer_1" enable-background="new 0 0 64 64" height="64" viewBox="0 0 64 64" width="64" xmlns="http://www.w3.org/2000/svg"><g><g id="ARC_17_"><g><path d="m31.996 31.008c-3.292 0-6.583-1.09-9.33-3.271-.433-.344-.504-.973-.161-1.406.345-.432.973-.502 1.405-.16 4.761 3.783 11.412 3.783 16.171 0 .432-.344 1.062-.271 1.405.16.344.434.271 1.063-.161 1.406-2.746 2.181-6.038 3.271-9.329 3.271z"/></g></g><g id="ARC_18_"><g><path d="m16.307 41.711c-.455 0-.866-.313-.973-.773-1.432-6.156 1.748-12.424 7.561-14.904.509-.217 1.096.02 1.313.527.217.508-.02 1.096-.527 1.313-4.919 2.098-7.61 7.402-6.398 12.611.125.537-.209 1.074-.748 1.199-.077.019-.153.027-.228.027z"/></g></g><g id="ARC_19_"><g><path d="m47.684 41.711c-.075 0-.151-.008-.228-.027-.538-.125-.873-.662-.747-1.199 1.212-5.209-1.479-10.514-6.398-12.611-.508-.217-.744-.805-.527-1.313.217-.51.809-.744 1.313-.527 5.813 2.48 8.994 8.748 7.561 14.904-.109.46-.52.773-.974.773z"/></g></g><g id="CIRCLE_14_"><g><path d="m32.013 26.967c-2.701 0-5.284-.963-7.273-2.709-3.782-3.32-4.823-8.957-2.475-13.398 1.881-3.561 5.723-5.861 9.788-5.861.888 0 1.772.107 2.629.324 4.817 1.209 8.314 5.695 8.314 10.668 0 3.559-1.735 6.916-4.642 8.979-1.844 1.305-4.038 1.997-6.341 1.997zm.039-19.969c-3.333 0-6.48 1.881-8.019 4.795-1.92 3.635-1.068 8.244 2.026 10.963 1.624 1.426 3.738 2.211 5.954 2.211 1.888 0 3.68-.563 5.184-1.629 2.379-1.689 3.799-4.436 3.799-7.348 0-4.068-2.86-7.74-6.801-8.729-.699-.175-1.419-.263-2.143-.263z"/></g></g><g id="ARC_20_"><g><path d="m24.573 43.184c-.034 0-.067-.002-.102-.006-2.83-.287-5.66-.791-8.412-1.498-.535-.139-.857-.684-.719-1.219.137-.535.684-.857 1.217-.719 2.655.684 5.386 1.17 8.115 1.445.55.057.95.547.895 1.096-.052.516-.487.901-.994.901z"/></g></g><g id="ARC_21_"><g><path d="m39.418 43.184c-.507 0-.941-.385-.994-.9-.056-.549.345-1.039.895-1.096 2.73-.275 5.46-.762 8.115-1.445.529-.137 1.08.184 1.218.719s-.185 1.08-.72 1.219c-2.752.707-5.582 1.211-8.412 1.498-.035.003-.069.005-.102.005z"/></g></g><g id="LINE_65_"><g><path d="m31.995 53.99c-.195 0-.392-.057-.565-.176-.455-.313-.571-.936-.258-1.391l7.423-10.807c.312-.455.938-.57 1.391-.258.455.313.57.936.258 1.391l-7.424 10.808c-.194.283-.507.433-.825.433z"/></g></g><g id="LINE_66_"><g><path d="m31.997 53.99c-.318 0-.631-.15-.825-.434l-7.424-10.806c-.313-.455-.197-1.078.258-1.391.457-.314 1.078-.197 1.391.258l7.424 10.807c.312.455.197 1.078-.258 1.391-.174.119-.372.175-.566.175z"/></g></g><g id="LWPOLYLINE_14_"><g><path d="m32.453 59.002c-.709 0-1.429-.012-2.159-.037-4.484-.15-8.824-.424-12.622-2.088-.71-.311-2.386-1.189-2.613-2.623-.083-.527-.001-1.32.866-2.09 2.129-1.893 5.448-2.318 8.114-2.66l.896-.117c.541-.07 1.052.309 1.126.855s-.308 1.053-.855 1.127l-.913.119c-2.394.307-5.372.688-7.039 2.17-.177.156-.223.264-.22.283.034.213.553.715 1.44 1.104 3.473 1.521 7.604 1.777 11.886 1.922 4.494.148 8.578-.178 12.126-.98 3.9-.879 4.438-1.734 4.508-1.898.011-.025.029-.07-.06-.217-.367-.598-1.497-.996-2.245-1.26-1.851-.652-3.845-.959-5.896-1.242-.548-.074-.93-.578-.854-1.125.074-.547.577-.938 1.126-.855 2.157.297 4.262.621 6.289 1.336 1.014.357 2.548.898 3.285 2.102.518.846.393 1.576.196 2.041-.554 1.311-2.415 2.283-5.856 3.059-3.175.717-6.699 1.074-10.526 1.074z"/></g></g></g></svg>
\ No newline at end of file
...@@ -9,7 +9,7 @@ class FollowupListResponse { ...@@ -9,7 +9,7 @@ class FollowupListResponse {
if (json['list'] != null) { if (json['list'] != null) {
list = <Followuplist>[]; list = <Followuplist>[];
json['list'].forEach((v) { json['list'].forEach((v) {
list!.add(Followuplist.fromJson(v)); list!.add(new Followuplist.fromJson(v));
}); });
} }
error = json['error']; error = json['error'];
...@@ -17,12 +17,12 @@ class FollowupListResponse { ...@@ -17,12 +17,12 @@ class FollowupListResponse {
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{}; final Map<String, dynamic> data = new Map<String, dynamic>();
if (list != null) { if (this.list != null) {
data['list'] = list!.map((v) => v.toJson()).toList(); data['list'] = this.list!.map((v) => v.toJson()).toList();
} }
data['error'] = error; data['error'] = this.error;
data['session_exists'] = sessionExists; data['session_exists'] = this.sessionExists;
return data; return data;
} }
} }
...@@ -42,21 +42,20 @@ class Followuplist { ...@@ -42,21 +42,20 @@ class Followuplist {
String? time; String? time;
String? ename; String? ename;
Followuplist({ Followuplist(
this.id, {this.id,
this.empId, this.empId,
this.compId, this.compId,
this.inTime, this.inTime,
this.outTime, this.outTime,
this.feedback, this.feedback,
this.type, this.type,
this.date, this.date,
this.fsrNo, this.fsrNo,
this.fsrExt, this.fsrExt,
this.runningHrs, this.runningHrs,
this.time, this.time,
this.ename, this.ename});
});
Followuplist.fromJson(Map<String, dynamic> json) { Followuplist.fromJson(Map<String, dynamic> json) {
id = json['id']; id = json['id'];
...@@ -75,20 +74,20 @@ class Followuplist { ...@@ -75,20 +74,20 @@ class Followuplist {
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{}; final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = id; data['id'] = this.id;
data['emp_id'] = empId; data['emp_id'] = this.empId;
data['comp_id'] = compId; data['comp_id'] = this.compId;
data['in_time'] = inTime; data['in_time'] = this.inTime;
data['out_time'] = outTime; data['out_time'] = this.outTime;
data['feedback'] = feedback; data['feedback'] = this.feedback;
data['type'] = type; data['type'] = this.type;
data['date'] = date; data['date'] = this.date;
data['fsr_no'] = fsrNo; data['fsr_no'] = this.fsrNo;
data['fsr_ext'] = fsrExt; data['fsr_ext'] = this.fsrExt;
data['running_hrs'] = runningHrs; data['running_hrs'] = this.runningHrs;
data['time'] = time; data['time'] = this.time;
data['ename'] = ename; data['ename'] = this.ename;
return data; return data;
} }
} }
class ServiceComplaintBillListResponse {
List<ComplaintList>? complaintList;
int? error;
int? sessionExists;
ServiceComplaintBillListResponse(
{this.complaintList, this.error, this.sessionExists});
ServiceComplaintBillListResponse.fromJson(Map<String, dynamic> json) {
if (json['complaint_list'] != null) {
complaintList = <ComplaintList>[];
json['complaint_list'].forEach((v) {
complaintList!.add(new ComplaintList.fromJson(v));
});
}
error = json['error'];
sessionExists = json['session_exists'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.complaintList != null) {
data['complaint_list'] =
this.complaintList!.map((v) => v.toJson()).toList();
}
data['error'] = this.error;
data['session_exists'] = this.sessionExists;
return data;
}
}
class ComplaintList {
String? billId;
String? totalAmount;
String? rawAmount;
String? narration;
String? billDate;
String? dueDate;
String? billPaid;
ComplaintList(
{this.billId,
this.totalAmount,
this.rawAmount,
this.narration,
this.billDate,
this.dueDate,
this.billPaid});
ComplaintList.fromJson(Map<String, dynamic> json) {
billId = json['bill_id'];
totalAmount = json['total_amount'];
rawAmount = json['raw_amount'];
narration = json['narration'];
billDate = json['bill_date'];
dueDate = json['due_date'];
billPaid = json['bill_paid'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['bill_id'] = this.billId;
data['total_amount'] = this.totalAmount;
data['raw_amount'] = this.rawAmount;
data['narration'] = this.narration;
data['bill_date'] = this.billDate;
data['due_date'] = this.dueDate;
data['bill_paid'] = this.billPaid;
return data;
}
}
class EditCommonAccFormDetailsResponse {
List<AccountList>? accountList;
String? error;
String? message;
int? sessionExists;
EditCommonAccFormDetailsResponse(
{this.accountList, this.error, this.message, this.sessionExists});
EditCommonAccFormDetailsResponse.fromJson(Map<String, dynamic> json) {
if (json['account_list'] != null) {
accountList = <AccountList>[];
json['account_list'].forEach((v) {
accountList!.add(new AccountList.fromJson(v));
});
}
error = json['error'];
message = json['message'];
sessionExists = json['session_exists'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.accountList != null) {
data['account_list'] = this.accountList!.map((v) => v.toJson()).toList();
}
data['error'] = this.error;
data['message'] = this.message;
data['session_exists'] = this.sessionExists;
return data;
}
}
class AccountList {
String? id;
String? isPaymentAccount;
String? createdEmployeeId;
String? type;
String? refId;
String? name;
String? subLocality;
String? district;
String? state;
String? address;
String? datetime;
String? empId;
String? bankName;
String? bankBranchName;
String? bankIfscCode;
String? bankAccountHolderName;
String? bankAccountNumber;
String? bankUpiId;
String? bankUpiName;
String? gstNumber;
Null? cashfreeAccountId;
String? isGstNumberVerified;
String? isBankAccountVerified;
String? remarks;
String? isExists;
String? createdDatetime;
String? updatedDatetime;
String? mob1;
String? email;
String? contactName;
AccountList(
{this.id,
this.isPaymentAccount,
this.createdEmployeeId,
this.type,
this.refId,
this.name,
this.subLocality,
this.district,
this.state,
this.address,
this.datetime,
this.empId,
this.bankName,
this.bankBranchName,
this.bankIfscCode,
this.bankAccountHolderName,
this.bankAccountNumber,
this.bankUpiId,
this.bankUpiName,
this.gstNumber,
this.cashfreeAccountId,
this.isGstNumberVerified,
this.isBankAccountVerified,
this.remarks,
this.isExists,
this.createdDatetime,
this.updatedDatetime,
this.mob1,
this.email,
this.contactName});
AccountList.fromJson(Map<String, dynamic> json) {
id = json['id'];
isPaymentAccount = json['is_payment_account'];
createdEmployeeId = json['created_employee_id'];
type = json['type'];
refId = json['ref_id'];
name = json['name'];
subLocality = json['sub_locality'];
district = json['district'];
state = json['state'];
address = json['address'];
datetime = json['datetime'];
empId = json['emp_id'];
bankName = json['bank_name'];
bankBranchName = json['bank_branch_name'];
bankIfscCode = json['bank_ifsc_code'];
bankAccountHolderName = json['bank_account_holder_name'];
bankAccountNumber = json['bank_account_number'];
bankUpiId = json['bank_upi_id'];
bankUpiName = json['bank_upi_name'];
gstNumber = json['gst_number'];
cashfreeAccountId = json['cashfree_account_id'];
isGstNumberVerified = json['is_gst_number_verified'];
isBankAccountVerified = json['is_bank_account_verified'];
remarks = json['remarks'];
isExists = json['is_exists'];
createdDatetime = json['created_datetime'];
updatedDatetime = json['updated_datetime'];
mob1 = json['mob1'];
email = json['email'];
contactName = json['contact_name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['is_payment_account'] = this.isPaymentAccount;
data['created_employee_id'] = this.createdEmployeeId;
data['type'] = this.type;
data['ref_id'] = this.refId;
data['name'] = this.name;
data['sub_locality'] = this.subLocality;
data['district'] = this.district;
data['state'] = this.state;
data['address'] = this.address;
data['datetime'] = this.datetime;
data['emp_id'] = this.empId;
data['bank_name'] = this.bankName;
data['bank_branch_name'] = this.bankBranchName;
data['bank_ifsc_code'] = this.bankIfscCode;
data['bank_account_holder_name'] = this.bankAccountHolderName;
data['bank_account_number'] = this.bankAccountNumber;
data['bank_upi_id'] = this.bankUpiId;
data['bank_upi_name'] = this.bankUpiName;
data['gst_number'] = this.gstNumber;
data['cashfree_account_id'] = this.cashfreeAccountId;
data['is_gst_number_verified'] = this.isGstNumberVerified;
data['is_bank_account_verified'] = this.isBankAccountVerified;
data['remarks'] = this.remarks;
data['is_exists'] = this.isExists;
data['created_datetime'] = this.createdDatetime;
data['updated_datetime'] = this.updatedDatetime;
data['mob1'] = this.mob1;
data['email'] = this.email;
data['contact_name'] = this.contactName;
return data;
}
}
class ValidateBankAccountDetailsResponse {
String? nameAtBank;
String? bankName;
String? branch;
String? error;
String? message;
int? sessionExists;
ValidateBankAccountDetailsResponse(
{this.nameAtBank,
this.bankName,
this.branch,
this.error,
this.message,
this.sessionExists});
ValidateBankAccountDetailsResponse.fromJson(Map<String, dynamic> json) {
nameAtBank = json['name_at_bank'];
bankName = json['bank_name'];
branch = json['branch'];
error = json['error'];
message = json['message'];
sessionExists = json['session_exists'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name_at_bank'] = this.nameAtBank;
data['bank_name'] = this.bankName;
data['branch'] = this.branch;
data['error'] = this.error;
data['message'] = this.message;
data['session_exists'] = this.sessionExists;
return data;
}
}
class ValidateGstNumResponse {
String? legalNameOfBusiness;
String? address;
String? error;
String? message;
int? sessionExists;
ValidateGstNumResponse(
{this.legalNameOfBusiness,
this.address,
this.error,
this.message,
this.sessionExists});
ValidateGstNumResponse.fromJson(Map<String, dynamic> json) {
legalNameOfBusiness = json['legal_name_of_business'];
address = json['address'];
error = json['error'];
message = json['message'];
sessionExists = json['session_exists'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['legal_name_of_business'] = this.legalNameOfBusiness;
data['address'] = this.address;
data['error'] = this.error;
data['message'] = this.message;
data['session_exists'] = this.sessionExists;
return data;
}
}
class CommonResponse { class CommonResponse {
String? error; String? error;
String? message; String? message;
String? qrCode;
String? qrId;
int? sessionExists; int? sessionExists;
CommonResponse({this.error, this.message, this.sessionExists}); CommonResponse({this.error, this.message, this.sessionExists});
CommonResponse.fromJson(Map<String, dynamic> json) { CommonResponse.fromJson(Map<String, dynamic> json) {
error = json['error']; error = json['error'];
qrCode = json['qr_code'];
qrId = json['razorpay_order_id'];
message = json['message']; message = json['message'];
sessionExists = json['session_exists']; sessionExists = json['session_exists'];
} }
...@@ -15,6 +18,8 @@ class CommonResponse { ...@@ -15,6 +18,8 @@ class CommonResponse {
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{}; final Map<String, dynamic> data = <String, dynamic>{};
data['error'] = error; data['error'] = error;
data['qr_code'] = qrCode;
data['razorpay_order_id'] = qrId;
data['message'] = message; data['message'] = message;
data['session_exists'] = sessionExists; data['session_exists'] = sessionExists;
return data; return data;
......
...@@ -14,6 +14,7 @@ import 'package:provider/provider.dart'; ...@@ -14,6 +14,7 @@ import 'package:provider/provider.dart';
import '../Utils/BackgroundLocationService.dart'; import '../Utils/BackgroundLocationService.dart';
import '../Utils/SharedpreferencesService.dart'; import '../Utils/SharedpreferencesService.dart';
import '../Utils/backgroundServiceNew.dart';
import '../Utils/background_service.dart'; import '../Utils/background_service.dart';
import '../Utils/commonServices.dart'; import '../Utils/commonServices.dart';
import '../services/api_calling.dart'; import '../services/api_calling.dart';
...@@ -229,6 +230,8 @@ class CheckInOutProvider with ChangeNotifier { ...@@ -229,6 +230,8 @@ class CheckInOutProvider with ChangeNotifier {
if (data.error == 0) { if (data.error == 0) {
toast(context, "CheckedIn Successfully"); toast(context, "CheckedIn Successfully");
await BackgroundLocationService.startLocationService(context); await BackgroundLocationService.startLocationService(context);
await BackgroundLocationServiceNew.init();
await BackgroundLocationServiceNew.start();
locationController.clear(); locationController.clear();
dispose(); dispose();
Navigator.pop(context, true); Navigator.pop(context, true);
...@@ -266,6 +269,7 @@ class CheckInOutProvider with ChangeNotifier { ...@@ -266,6 +269,7 @@ class CheckInOutProvider with ChangeNotifier {
if (data.error == 0) { if (data.error == 0) {
toast(context, "Check-Out Successful"); toast(context, "Check-Out Successful");
await BackgroundLocationService.stopLocationService(); await BackgroundLocationService.stopLocationService();
await BackgroundLocationServiceNew.stop();
locationController.clear(); locationController.clear();
dispose(); dispose();
Navigator.pop(context, true); Navigator.pop(context, true);
......
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:generp/Utils/SharedpreferencesService.dart'; import 'package:generp/Utils/SharedpreferencesService.dart';
import 'package:generp/Utils/backgroundServiceNew.dart';
import 'package:generp/screens/LoginScreen.dart'; import 'package:generp/screens/LoginScreen.dart';
import 'package:generp/services/api_calling.dart'; import 'package:generp/services/api_calling.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
...@@ -77,6 +78,8 @@ class HomescreenNotifier extends ChangeNotifier { ...@@ -77,6 +78,8 @@ class HomescreenNotifier extends ChangeNotifier {
var lastLocationTime = await SharedpreferencesService().getString( var lastLocationTime = await SharedpreferencesService().getString(
"lastLocationTime", "lastLocationTime",
); );
notifyListeners(); notifyListeners();
print("lastLocationTime:$lastLocationTime"); print("lastLocationTime:$lastLocationTime");
...@@ -112,6 +115,7 @@ class HomescreenNotifier extends ChangeNotifier { ...@@ -112,6 +115,7 @@ class HomescreenNotifier extends ChangeNotifier {
if (_att_status == 0) { if (_att_status == 0) {
webSocketManager.close(); webSocketManager.close();
await BackgroundLocationService.stopLocationService(); await BackgroundLocationService.stopLocationService();
BackgroundLocationServiceNew.stop();
_onlineStatus = "Offline"; _onlineStatus = "Offline";
...@@ -151,11 +155,14 @@ class HomescreenNotifier extends ChangeNotifier { ...@@ -151,11 +155,14 @@ class HomescreenNotifier extends ChangeNotifier {
// print("Status knlknn offine"); // print("Status knlknn offine");
} }
await BackgroundLocationService.startLocationService(context); await BackgroundLocationService.startLocationService(context);
await BackgroundLocationServiceNew.init();
await BackgroundLocationServiceNew.start();
// print("setstatus:$setstatus"); // print("setstatus:$setstatus");
} else if (_att_status == 2) { } else if (_att_status == 2) {
// print("att_status:$att_status"); // print("att_status:$att_status");
webSocketManager.close(); webSocketManager.close();
await BackgroundLocationService.stopLocationService(); await BackgroundLocationService.stopLocationService();
await BackgroundLocationServiceNew.stop();
_onlineStatus = "Offline"; _onlineStatus = "Offline";
......
...@@ -5,6 +5,7 @@ import 'package:generp/screens/LoginScreen.dart'; ...@@ -5,6 +5,7 @@ import 'package:generp/screens/LoginScreen.dart';
import 'package:generp/services/api_calling.dart'; import 'package:generp/services/api_calling.dart';
import '../Utils/BackgroundLocationService.dart'; import '../Utils/BackgroundLocationService.dart';
import '../Utils/backgroundServiceNew.dart';
class LogoutNotifier extends ChangeNotifier { class LogoutNotifier extends ChangeNotifier {
bool _logoutButtonClicked = false; bool _logoutButtonClicked = false;
...@@ -33,6 +34,8 @@ class LogoutNotifier extends ChangeNotifier { ...@@ -33,6 +34,8 @@ class LogoutNotifier extends ChangeNotifier {
_isLoading = false; _isLoading = false;
_logoutButtonClicked = false; _logoutButtonClicked = false;
await BackgroundLocationService.stopLocationService(); await BackgroundLocationService.stopLocationService();
await BackgroundLocationServiceNew.stop();
SharedpreferencesService().clearPreferences(); SharedpreferencesService().clearPreferences();
Navigator.push( Navigator.push(
context, context,
......
...@@ -208,6 +208,7 @@ class Paymentdetailsprovider extends ChangeNotifier { ...@@ -208,6 +208,7 @@ class Paymentdetailsprovider extends ChangeNotifier {
_imageName = null; _imageName = null;
_image_picked = 0; _image_picked = 0;
resetErrors();
notifyListeners(); notifyListeners();
} else {} } else {}
} else { } else {
...@@ -775,6 +776,22 @@ class Paymentdetailsprovider extends ChangeNotifier { ...@@ -775,6 +776,22 @@ class Paymentdetailsprovider extends ChangeNotifier {
} }
} }
void resetErrors() {
nameError = null;
designationError = null;
mobError = null;
altMobError = null;
telError = null;
emailError = null;
selectContactError = null;
selectPaymentError = null;
selectAmountError = null;
ReferenceError = null;
imageError = null;
notifyListeners();
}
resetAddContect() { resetAddContect() {
Amountcontroller.clear(); Amountcontroller.clear();
Referencecontroller.clear(); Referencecontroller.clear();
......
...@@ -17,6 +17,7 @@ import '../Utils/commonServices.dart'; ...@@ -17,6 +17,7 @@ import '../Utils/commonServices.dart';
import '../screens/splash.dart'; import '../screens/splash.dart';
class Pendingcomplaintsprovider extends ChangeNotifier { class Pendingcomplaintsprovider extends ChangeNotifier {
TextEditingController fsrNumberController = TextEditingController(); TextEditingController fsrNumberController = TextEditingController();
TextEditingController runningHoursController = TextEditingController(); TextEditingController runningHoursController = TextEditingController();
TextEditingController feedbackController = TextEditingController(); TextEditingController feedbackController = TextEditingController();
......
import 'dart:async';
import 'package:flutter/material.dart';
import '../Models/ordersModels/commonResponse.dart';
import '../Utils/custom_snackbar.dart';
import '../services/api_calling.dart';
class QrProvider extends ChangeNotifier {
CommonResponse? _qrResponse;
bool _isLoading = false;
String? _errorMessage;
int _secondsLeft = 120; // 2 minutes
CommonResponse? get qrResponse => _qrResponse;
bool get isLoading => _isLoading;
String? get errorMessage => _errorMessage;
int get secondsLeft => _secondsLeft;
Timer? _timer;
Future<void> fetchRazorpayQr({
required String sessionId,
required String empId,
required String amount,
required String refType,
required String refId,
}) async {
_isLoading = true;
_errorMessage = null;
notifyListeners();
try {
final response = await ApiCalling.fetchRazorpayUpiQrApi(
sessionId,
empId,
amount,
refType,
refId,
);
if (response != null && response.error == "0") {
_qrResponse = response;
_startTimer();
} else {
_errorMessage = response?.message ?? "Something went wrong";
}
} catch (e) {
_errorMessage = e.toString();
} finally {
_isLoading = false;
notifyListeners();
}
}
void _startTimer() {
_secondsLeft = 120;
_timer?.cancel();
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (_secondsLeft > 0) {
_secondsLeft--;
notifyListeners();
} else {
timer.cancel();
}
});
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
bool _isPaymentUpdating = false;
bool get isPaymentUpdating => _isPaymentUpdating;
set isPaymentUpdating(bool value) {
_isPaymentUpdating = value;
notifyListeners();
}
/// Fetch Razorpay QR Payment Status
/// NOTE: This method no longer shows snackbars itself. It simply returns the response.
Future<CommonResponse?> fetchRazorpayUpiQrStatus({
required BuildContext context,
required String sessionId,
required String empId,
required String razorpayOrderId,
}) async {
try {
isPaymentUpdating = true;
final response = await ApiCalling.fetchRazorpayUpiQrStatusApi(
sessionId,
empId,
razorpayOrderId,
);
if (response != null) {
if (response.sessionExists == 1 && response.error == "0") {
debugPrint("Payment Status: ${response.message}");
} else {
// IMPORTANT: do not show UI here (no repeated warnings).
// The caller (screen) should decide when to show failure messages.
debugPrint("Payment still pending or failed: ${response.message}");
}
} else {
debugPrint("Null response from Razorpay QR Status API");
}
return response;
} catch (e) {
debugPrint("fetchRazorpayUpiQrStatus error: $e");
return null;
} finally {
isPaymentUpdating = false;
}
}
}
...@@ -4,6 +4,7 @@ import 'package:generp/services/api_calling.dart'; ...@@ -4,6 +4,7 @@ import 'package:generp/services/api_calling.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../Models/FollowUpResponse.dart'; import '../Models/FollowUpResponse.dart';
import '../Models/ServiceComplaintBillListResponse.dart';
import '../Models/ViewVisitDetailsResponseNew.dart'; import '../Models/ViewVisitDetailsResponseNew.dart';
import '../Utils/commonServices.dart'; import '../Utils/commonServices.dart';
...@@ -14,26 +15,79 @@ class Visitdetailsprovider extends ChangeNotifier { ...@@ -14,26 +15,79 @@ class Visitdetailsprovider extends ChangeNotifier {
GeneratorDetails _generatorDetails = GeneratorDetails(); GeneratorDetails _generatorDetails = GeneratorDetails();
ComplaintDetailsNew _complaintDetailsNew = ComplaintDetailsNew(); ComplaintDetailsNew _complaintDetailsNew = ComplaintDetailsNew();
List<Followuplist> _followupList = []; List<Followuplist> _followupList = [];
List<ComplaintList> _complaintList = [];
bool _isLoading = false; bool _isLoading = false;
CustomerDetails get customerDetails => _customerDetails; CustomerDetails get customerDetails => _customerDetails;
GeneratorDetails get generatorDetails => _generatorDetails; GeneratorDetails get generatorDetails => _generatorDetails;
ComplaintDetailsNew get complaintDetailsNew => _complaintDetailsNew; ComplaintDetailsNew get complaintDetailsNew => _complaintDetailsNew;
List<Followuplist> get followUpList => _followupList; List<Followuplist> get followUpList => _followupList;
List<ComplaintList> get complaintList => _complaintList;
bool get isLoading => _isLoading; bool get isLoading => _isLoading;
bool get showMoreDetails => _showMoreDetails; bool get showMoreDetails => _showMoreDetails;
// ==== FIX FOR THE CRASH ====
bool _disposed = false;
@override
void dispose() {
_disposed = true;
super.dispose();
}
void safeNotifyListeners() {
if (!_disposed) notifyListeners();
}
// ===========================
set showMoreDetails(bool value) { set showMoreDetails(bool value) {
_showMoreDetails = value; _showMoreDetails = value;
notifyListeners(); safeNotifyListeners();
} }
Future<void> LoadVisitDetailsAPI(BuildContext context, ComplaintID) async { ServiceComplaintBillListResponse? complaintBillListResponse;
String? error;
Future<void> serviceComplaintBillList(BuildContext context, String complaintId) async {
try { try {
var HomeProvider = Provider.of<HomescreenNotifier>( var homeProvider = Provider.of<HomescreenNotifier>(context, listen: false);
context,
listen: false, _isLoading = true;
safeNotifyListeners();
final data = await ApiCalling.serviceComplaintBillListAPI(
homeProvider.empId,
homeProvider.session,
complaintId,
); );
if (data != null) {
if (data.error == 0) {
_complaintList = data.complaintList ?? [];
_isLoading = false;
safeNotifyListeners();
} else {
toast(context, "Something Went Wrong, Please try again!");
}
} else {
toast(context, "No response From the server, Please try Again!");
}
complaintBillListResponse = data;
error = null;
} catch (e) {
error = e.toString();
complaintBillListResponse = null;
} finally {
_isLoading = false;
safeNotifyListeners();
}
}
Future<void> LoadVisitDetailsAPI(BuildContext context, ComplaintID) async {
try {
var HomeProvider = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.loadVisitDetailsAPI( final data = await ApiCalling.loadVisitDetailsAPI(
HomeProvider.empId, HomeProvider.empId,
HomeProvider.session, HomeProvider.session,
...@@ -42,31 +96,26 @@ class Visitdetailsprovider extends ChangeNotifier { ...@@ -42,31 +96,26 @@ class Visitdetailsprovider extends ChangeNotifier {
if (data != null) { if (data != null) {
if (data.error == 0) { if (data.error == 0) {
// complaintdetails = data.complaintDetails!;
_customerDetails = data.customerDetails!; _customerDetails = data.customerDetails!;
_generatorDetails = data.generatorDetails!; _generatorDetails = data.generatorDetails!;
_complaintDetailsNew = data.complaintDetailsNew!; _complaintDetailsNew = data.complaintDetailsNew!;
_isLoading = false; _isLoading = false;
notifyListeners(); safeNotifyListeners();
} else { } else {
toast(context, "Something Went Wrong, Please try again!"); toast(context, "Something Went Wrong, Please try again!");
print("error");
} }
} else { } else {
toast(context, "No response From the server, Please try Again!"); toast(context, "No response From the server, Please try Again!");
print("error2");
} }
} on Error catch (e) { } catch (e) {
print(e.toString()); print(e.toString());
} }
} }
Future<void> LoadFollowupListAPI(BuildContext context, ComplaintID) async { Future<void> LoadFollowupListAPI(BuildContext context, ComplaintID) async {
try { try {
var HomeProvider = Provider.of<HomescreenNotifier>( var HomeProvider = Provider.of<HomescreenNotifier>(context, listen: false);
context,
listen: false,
);
final data = await ApiCalling.loadFollowupListAPI( final data = await ApiCalling.loadFollowupListAPI(
HomeProvider.empId, HomeProvider.empId,
HomeProvider.session, HomeProvider.session,
...@@ -75,20 +124,19 @@ class Visitdetailsprovider extends ChangeNotifier { ...@@ -75,20 +124,19 @@ class Visitdetailsprovider extends ChangeNotifier {
if (data != null) { if (data != null) {
if (data.error == 0) { if (data.error == 0) {
// complaintdetails = data.complaintDetails!;
_followupList = data.list ?? []; _followupList = data.list ?? [];
_isLoading = false; _isLoading = false;
notifyListeners(); safeNotifyListeners();
} else { } else {
toast(context, "Something Went Wrong, Please try again!"); toast(context, "Something Went Wrong, Please try again!");
print("error");
} }
} else { } else {
toast(context, "No response From the server, Please try Again!"); toast(context, "No response From the server, Please try Again!");
print("error2");
} }
} on Error catch (e) { } catch (e) {
print(e.toString()); print(e.toString());
} }
} }
} }
//
//
// import 'package:flutter/cupertino.dart';
// import 'package:generp/Models/ordersModels/commonResponse.dart';
// import 'package:generp/services/api_calling.dart';
//
// class EditCommonAccountProvider extends ChangeNotifier{
// bool isLoading = false;
// String? errorMessage;
// CommonResponse? updateResponse;
//
// Future<void> updateAccountForm() async{
//
// try{
// isLoading = true;
// errorMessage = null;
// notifyListeners();
//
// updateResponse = await ApiCalling.commonUpdateAccountDetailsAPI(
// empId,
// sessionId,
// type,
// name,
// mob1,
// mob2,
// tel,
// email,
// designation,
// address,
// state,
// district,
// subLocality,
// bankName,
// branchName,
// bankIfscCode,
// accHolderName,
// bankAccNumber,
// bankUpiId
// );
//
// if (updateResponse == null){
// errorMessage = "No Response from server";
// }
// }
//
//
// }
//
// }
\ No newline at end of file
...@@ -7,6 +7,8 @@ import '../../Models/commonModels/commonAccountdetailsResponse.dart'; ...@@ -7,6 +7,8 @@ import '../../Models/commonModels/commonAccountdetailsResponse.dart';
class Accountdetailsprovider extends ChangeNotifier { class Accountdetailsprovider extends ChangeNotifier {
bool _showMoreDetails = false; bool _showMoreDetails = false;
bool _isLoading = false;
bool get isLoading => _isLoading;
AccountDetails _accountDetails = AccountDetails(); AccountDetails _accountDetails = AccountDetails();
BalanceDetails _balanceDetails = BalanceDetails(); BalanceDetails _balanceDetails = BalanceDetails();
...@@ -27,6 +29,8 @@ class Accountdetailsprovider extends ChangeNotifier { ...@@ -27,6 +29,8 @@ class Accountdetailsprovider extends ChangeNotifier {
} }
Future<void> accountdetailsAPIFunction(context, accountID) async { Future<void> accountdetailsAPIFunction(context, accountID) async {
_isLoading = true;
notifyListeners();
try { try {
var prov = Provider.of<HomescreenNotifier>(context, listen: false); var prov = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.commonAccountDetailsAPI( final data = await ApiCalling.commonAccountDetailsAPI(
...@@ -56,6 +60,8 @@ class Accountdetailsprovider extends ChangeNotifier { ...@@ -56,6 +60,8 @@ class Accountdetailsprovider extends ChangeNotifier {
} }
} }
} catch (e) {} } catch (e) {}
_isLoading = false;
notifyListeners();
} }
Map<String, List<LedgerList>> groupByDate(List<LedgerList> list) { Map<String, List<LedgerList>> groupByDate(List<LedgerList> list) {
......
// accountsListProvider.dart
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:generp/Models/ordersModels/commonResponse.dart';
import 'package:generp/Notifiers/HomeScreenNotifier.dart'; import 'package:generp/Notifiers/HomeScreenNotifier.dart';
import 'package:generp/Utils/commonServices.dart'; import 'package:generp/Utils/commonServices.dart';
import 'package:generp/Utils/custom_snackbar.dart';
import 'package:generp/screens/commom/accountsListDetails.dart'; import 'package:generp/screens/commom/accountsListDetails.dart';
import 'package:generp/screens/finance/financeDashboard.dart'; import 'package:generp/screens/finance/financeDashboard.dart';
import 'package:generp/services/api_calling.dart'; import 'package:generp/services/api_calling.dart';
...@@ -12,6 +15,8 @@ import '../../Models/commonModels/DistrictsResponse.dart'; ...@@ -12,6 +15,8 @@ import '../../Models/commonModels/DistrictsResponse.dart';
import '../../Models/commonModels/SubLocationsResponse.dart'; import '../../Models/commonModels/SubLocationsResponse.dart';
import '../../Models/commonModels/commonAccountlistResponse.dart'; import '../../Models/commonModels/commonAccountlistResponse.dart';
import '../../Models/commonModels/commonAddAccountsViewResponse.dart'; import '../../Models/commonModels/commonAddAccountsViewResponse.dart';
import '../../Models/financeModels/ValidateBankAccountDetailsResponse.dart';
import '../../Models/financeModels/ValidateGstNumResponse.dart';
class Accountslistprovider extends ChangeNotifier { class Accountslistprovider extends ChangeNotifier {
TextEditingController nameController = TextEditingController(); TextEditingController nameController = TextEditingController();
...@@ -21,11 +26,11 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -21,11 +26,11 @@ class Accountslistprovider extends ChangeNotifier {
TextEditingController branchNameController = TextEditingController(); TextEditingController branchNameController = TextEditingController();
TextEditingController bankIfscCotroller = TextEditingController(); TextEditingController bankIfscCotroller = TextEditingController();
TextEditingController bankHolderNameController = TextEditingController(); TextEditingController bankHolderNameController = TextEditingController();
TextEditingController gstNumberController = TextEditingController();
TextEditingController bankAcNumberController = TextEditingController(); TextEditingController bankAcNumberController = TextEditingController();
TextEditingController bankUpiController = TextEditingController(); TextEditingController bankUpiController = TextEditingController();
TextEditingController contactPersonController = TextEditingController(); TextEditingController contactPersonController = TextEditingController();
TextEditingController contectPersonDesignationController = TextEditingController contectPersonDesignationController = TextEditingController();
TextEditingController();
TextEditingController contectPersonAltMobController = TextEditingController(); TextEditingController contectPersonAltMobController = TextEditingController();
TextEditingController contectPersonTeleController = TextEditingController(); TextEditingController contectPersonTeleController = TextEditingController();
TextEditingController contectPersonMailController = TextEditingController(); TextEditingController contectPersonMailController = TextEditingController();
...@@ -43,6 +48,7 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -43,6 +48,7 @@ class Accountslistprovider extends ChangeNotifier {
String? districtError; String? districtError;
String? localityError; String? localityError;
String? addressError; String? addressError;
String? gstNumberError;
String? banknameError; String? banknameError;
String? bankBranchError; String? bankBranchError;
String? bankIFSCError; String? bankIFSCError;
...@@ -98,6 +104,12 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -98,6 +104,12 @@ class Accountslistprovider extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
ValidateGstNumResponse? gstResponse;
commonAddAccountsViewResponse? commonResponse;
ValidateBankAccountDetailsResponse? bankResponse;
String? errorMessage;
States? _selectedState; States? _selectedState;
Districts? _selectedDistricts; Districts? _selectedDistricts;
SubLocations? _selectedSubLocations; SubLocations? _selectedSubLocations;
...@@ -132,6 +144,12 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -132,6 +144,12 @@ class Accountslistprovider extends ChangeNotifier {
String? get selectedAccountType => _selectedAccountType; String? get selectedAccountType => _selectedAccountType;
// --- NEW: setter for isLoading so callers can do `isLoading = true;` ---
set isLoading(bool value) {
_isLoading = value;
notifyListeners();
}
set selectedAccountType(String? value) { set selectedAccountType(String? value) {
_selectedAccountType = value; _selectedAccountType = value;
accountError = null; accountError = null;
...@@ -140,24 +158,24 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -140,24 +158,24 @@ class Accountslistprovider extends ChangeNotifier {
set selectedState(States? value) { set selectedState(States? value) {
_selectedState = value; _selectedState = value;
_selectedStateID = value!.id; _selectedStateID = value?.id;
_selectedStateValue = value.name; _selectedStateValue = value?.name;
stateError = null; stateError = null;
notifyListeners(); notifyListeners();
} }
set selectedDistricts(Districts? value) { set selectedDistricts(Districts? value) {
_selectedDistricts = value; _selectedDistricts = value;
_selectedDistrictID = value!.id; _selectedDistrictID = value?.id;
_selectedDistrictValue = value.district; _selectedDistrictValue = value?.district;
districtError = null; districtError = null;
notifyListeners(); notifyListeners();
} }
set selectedSubLocations(SubLocations? value) { set selectedSubLocations(SubLocations? value) {
_selectedSubLocations = value; _selectedSubLocations = value;
_selectedSubLocID = value!.id; _selectedSubLocID = value?.id;
_selectedSubLocValue = value.subLocality!; _selectedSubLocValue = value?.subLocality;
localityError = null; localityError = null;
notifyListeners(); notifyListeners();
} }
...@@ -192,6 +210,8 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -192,6 +210,8 @@ class Accountslistprovider extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
// ---------- API / data loading ----------
Future<void> addCommonAccountViewAPI(context) async { Future<void> addCommonAccountViewAPI(context) async {
try { try {
var homeProv = Provider.of<HomescreenNotifier>(context, listen: false); var homeProv = Provider.of<HomescreenNotifier>(context, listen: false);
...@@ -205,12 +225,15 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -205,12 +225,15 @@ class Accountslistprovider extends ChangeNotifier {
if (data != null) { if (data != null) {
if (data.error == "0") { if (data.error == "0") {
ChechkDropdownValues(); ChechkDropdownValues();
_accountTypes = data.accountTypes!; _accountTypes = data.accountTypes ?? [];
_states = data.states!; _states = data.states ?? [];
notifyListeners(); notifyListeners();
} }
} }
} catch (e) {} } catch (e) {
// keep quiet but log in debug
if (kDebugMode) debugPrint('addCommonAccountViewAPI error: $e');
}
} }
Future<void> getDistrictAPI(context, stateID) async { Future<void> getDistrictAPI(context, stateID) async {
...@@ -225,11 +248,13 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -225,11 +248,13 @@ class Accountslistprovider extends ChangeNotifier {
); );
if (data != null) { if (data != null) {
if (data.error == "0") { if (data.error == "0") {
_districts = data.districts!; _districts = data.districts ?? [];
notifyListeners(); notifyListeners();
} }
} }
} catch (e) {} } catch (e) {
if (kDebugMode) debugPrint('getDistrictAPI error: $e');
}
} }
Future<void> getSubLocationAPI(context, districtID) async { Future<void> getSubLocationAPI(context, districtID) async {
...@@ -244,11 +269,13 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -244,11 +269,13 @@ class Accountslistprovider extends ChangeNotifier {
); );
if (data != null) { if (data != null) {
if (data.error == "0") { if (data.error == "0") {
_subLocations = data.subLocations!; _subLocations = data.subLocations ?? [];
notifyListeners(); notifyListeners();
} }
} }
} catch (e) {} } catch (e) {
if (kDebugMode) debugPrint('getSubLocationAPI error: $e');
}
} }
Future<void> checkInputsAPI(context, type, value) async { Future<void> checkInputsAPI(context, type, value) async {
...@@ -260,6 +287,7 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -260,6 +287,7 @@ class Accountslistprovider extends ChangeNotifier {
type, type,
value, value,
); );
commonResponse =data;
if (data != null) { if (data != null) {
if (data.error == "0") { if (data.error == "0") {
nameError = null; nameError = null;
...@@ -272,12 +300,310 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -272,12 +300,310 @@ class Accountslistprovider extends ChangeNotifier {
mobileError = data.message ?? ""; mobileError = data.message ?? "";
} }
notifyListeners(); notifyListeners();
// toast(context, data.message);
} }
} }
} catch (e) {} } catch (e) {
if (kDebugMode) debugPrint('checkInputsAPI error: $e');
}
}
/// Validate GST Number
/// Returns true if validated successfully (and sets gstResponse). Caller can await.
Future<bool> validateGstNumber(
String empId, String sessionId, String gstNumber) async {
// if empty — don't call API; clear any previous errors/responses
if (gstNumber.trim().isEmpty) {
gstResponse = null;
gstNumberError = null;
notifyListeners();
return false;
}
try {
isLoading = true;
errorMessage = null;
// call API
final response = await ApiCalling.validateGstNumberApi(
empId,
sessionId,
gstNumber,
);
// assign
gstResponse = response;
if (response == null) {
gstNumberError = "Failed to validate GST number";
notifyListeners();
return false;
}
// Response object expected to contain `error` and `address` and `legal_name_of_business`
if (response.error == "0") {
gstNumberError = null;
// Optionally update address or other fields in UI (UI will read gstResponse)
notifyListeners();
return true;
} else {
// API returned invalid GST
gstNumberError = response.message ?? "Invalid GST number";
notifyListeners();
return false;
}
} catch (e) {
gstNumberError = "Error validating GST: ${e.toString()}";
if (kDebugMode) debugPrint('validateGstNumber error: $e');
notifyListeners();
return false;
} finally {
isLoading = false;
notifyListeners();
}
}
/// Validate Bank Account Details
/// Returns true if validated successfully (and sets bankResponse). Caller can await.
Future<bool> validateBankDetails(
String empId, String sessionId, String accountNumber) async {
// require accountNumber and IFSC to be present
final ifsc = bankIfscCotroller.text.trim();
if (accountNumber.trim().isEmpty || ifsc.isEmpty) {
// clear previous bankResponse if user cleared input
bankResponse = null;
bankAcNumberError = null;
bankIFSCError = null;
notifyListeners();
return false;
}
// basic IFSC format check (caller/UI also checks) — we trust UI but double-check
final reg = RegExp(r'^[A-Za-z]{4}0[A-Za-z0-9]{6}$');
if (!reg.hasMatch(ifsc)) {
bankIFSCError = "Invalid IFSC format";
notifyListeners();
return false;
}
try {
isLoading = true;
errorMessage = null;
// call API - pass account number and IFSC from controller (some APIs require both)
final response = await ApiCalling.validateBankAccountDetailsApi(
empId,
sessionId,
accountNumber,
ifsc,
);
bankResponse = response;
if (response == null) {
bankAcNumberError = "Failed to validate bank account";
notifyListeners();
return false;
}
if (response.error == "0") {
// success — populate fields in UI from the provider.bankResponse (UI will take the values)
bankAcNumberError = null;
bankIFSCError = null;
banknameError = null;
bankBranchError = null;
bankHolderNameError = null;
notifyListeners();
return true;
} else {
// error returned
bankAcNumberError = response.message ?? "Invalid account details";
notifyListeners();
return false;
}
} catch (e) {
bankAcNumberError = "Error validating account: ${e.toString()}";
if (kDebugMode) debugPrint('validateBankDetails error: $e');
notifyListeners();
return false;
} finally {
isLoading = false;
notifyListeners();
}
}
Future<void> checkAndApplyGst(BuildContext context, String gstNumber) async {
// clear previous GST error when user actively changed
gstNumberError = null;
notifyListeners();
final trimmed = gstNumber.trim();
if (trimmed.isEmpty) {
// user cleared GST: clear response + errors
gstResponse = null;
gstNumberError = null;
notifyListeners();
return;
}
try {
isLoading = true;
final homeProv = Provider.of<HomescreenNotifier>(context, listen: false);
final resp = await ApiCalling.validateGstNumberApi(
homeProv.empId,
homeProv.session,
trimmed,
);
gstResponse = resp;
if (resp == null) {
gstNumberError = "Failed to validate GST number";
notifyListeners();
return;
}
if (resp.error == "0") {
// success -> autofill address and compare company name
// Use response field names you mentioned: legal_name_of_business and address
final apiName = (resp.legalNameOfBusiness ?? "").trim();
final apiAddress = (resp.address ?? "").trim();
// Autofill/override address in Step 2
if (apiAddress.isNotEmpty) {
// Only override if response contains useful address
addressController.text = apiAddress;
}
// Compare company name vs gst name
final enteredName = (nameController.text ?? "").trim();
debugPrint("################# Entered text: $enteredName \n response name: $apiName");
if (apiName.isNotEmpty && enteredName.isNotEmpty) {
if (apiName.toLowerCase() != enteredName.toLowerCase()) {
// Set error on step 1
nameError = "Company name does not match GST record ('$apiName'). Please correct.";
} else {
nameError = null;
}
}
gstNumberError = null;
notifyListeners();
return;
} else {
// API returned invalid GST
gstNumberError = resp.message ?? "Invalid GST number";
notifyListeners();
return;
}
} catch (e) {
gstNumberError = "Error validating GST";
if (kDebugMode) debugPrint("checkAndApplyGst error: $e");
notifyListeners();
return;
} finally {
isLoading = false;
notifyListeners();
}
}
void recheckNameWithGst() {
if (gstResponse == null) return;
final apiName = (gstResponse?.legalNameOfBusiness ?? "").trim();
final enteredName = nameController.text.trim();
if (apiName.isNotEmpty && enteredName.isNotEmpty) {
if (apiName.toLowerCase() != enteredName.toLowerCase()) {
nameError = "Company name does not match GST record ('$apiName')";
} else {
nameError = null;
}
}
notifyListeners();
}
/// New helper: check bank account + ifsc and call bank API when both present.
/// Called by UI when user finishes account/ifsc input or when IFSC changes.
Future<void> checkAndApplyBank(BuildContext context, String accountNumber) async {
bankAcNumberError = null;
bankIFSCError = null;
notifyListeners();
final acc = accountNumber.trim();
final ifsc = bankIfscCotroller.text.trim();
if (acc.isEmpty && ifsc.isEmpty) {
// user cleared both
bankResponse = null;
bankAcNumberError = null;
bankIFSCError = null;
notifyListeners();
return;
}
// If account entered, IFSC required
if (acc.isNotEmpty && ifsc.isEmpty) {
bankIFSCError = "IFSC is required when account number is entered";
notifyListeners();
return;
}
// validate IFSC format (basic)
final ifscReg = RegExp(r'^[A-Za-z]{4}0[A-Za-z0-9]{6}$');
if (ifsc.isNotEmpty && !ifscReg.hasMatch(ifsc)) {
bankIFSCError = "Invalid IFSC format";
notifyListeners();
return;
}
if (acc.isNotEmpty && ifsc.isNotEmpty) {
try {
isLoading = true;
final homeProv = Provider.of<HomescreenNotifier>(context, listen: false);
final resp = await ApiCalling.validateBankAccountDetailsApi(
homeProv.empId,
homeProv.session,
acc,
ifsc,
);
bankResponse = resp;
if (resp == null) {
bankAcNumberError = "Failed to validate bank details";
notifyListeners();
return;
}
if (resp.error == "0") {
// success -> autofill bank fields
bankNameController.text = resp.bankName ?? bankNameController.text;
branchNameController.text = resp.branch ?? branchNameController.text;
bankHolderNameController.text = resp.nameAtBank ?? bankHolderNameController.text;
// clear errors
bankAcNumberError = null;
bankIFSCError = null;
banknameError = null;
bankBranchError = null;
bankHolderNameError = null;
notifyListeners();
return;
} else {
bankAcNumberError = resp.message ?? "Invalid account details";
notifyListeners();
return;
}
} catch (e) {
bankAcNumberError = "Error validating bank: ${e.toString()}";
if (kDebugMode) debugPrint("checkAndApplyBank error: $e");
notifyListeners();
return;
} finally {
isLoading = false;
notifyListeners();
}
}
} }
bool hasFilledAdditionalDetails = false; bool hasFilledAdditionalDetails = false;
bool _submitClicked = false; bool _submitClicked = false;
...@@ -292,7 +618,6 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -292,7 +618,6 @@ class Accountslistprovider extends ChangeNotifier {
Future<void> submitCommonAccountsAPI(context, from) async { Future<void> submitCommonAccountsAPI(context, from) async {
try { try {
if (!validatereceiptForm(context)) { if (!validatereceiptForm(context)) {
// _submitClicked = false;
return; return;
} }
_submitClicked = true; _submitClicked = true;
...@@ -327,14 +652,12 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -327,14 +652,12 @@ class Accountslistprovider extends ChangeNotifier {
if (from == "Requesition") { if (from == "Requesition") {
Navigator.pop(context, res); Navigator.pop(context, res);
} else if (from == "Dashboard") { } else if (from == "Dashboard") {
print("here");
Navigator.pushAndRemoveUntil( Navigator.pushAndRemoveUntil(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => Accountslistdetails(accountID: data.id), builder: (context) => Accountslistdetails(accountID: data.id),
), ),
(Route<dynamic> route) { (Route<dynamic> route) {
return route.settings.arguments == 'Financedashboard'; return route.settings.arguments == 'Financedashboard';
}, },
); );
...@@ -360,7 +683,7 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -360,7 +683,7 @@ class Accountslistprovider extends ChangeNotifier {
} }
} }
bool validateStep1() { bool validateStep1(BuildContext context) {
accountError = null; accountError = null;
nameError = null; nameError = null;
mobileError = null; mobileError = null;
...@@ -374,11 +697,53 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -374,11 +697,53 @@ class Accountslistprovider extends ChangeNotifier {
nameError = "Please Enter a Name"; nameError = "Please Enter a Name";
isValid = false; isValid = false;
} }
if (mobileController.text.trim().isNotEmpty && if (nameError != null && nameError != "") {
mobileController.text.length < 10) { isValid = false;
}
if (mobileController.text.trim().isNotEmpty && mobileController.text.length < 10) {
mobileError = "Mobile Number should be 10 digits"; mobileError = "Mobile Number should be 10 digits";
isValid = false; isValid = false;
} }
if (gstResponse != null){
final apiName = (gstResponse?.legalNameOfBusiness ?? "").trim();
final enteredName = nameController.text.trim();
if (apiName.isNotEmpty && enteredName.isNotEmpty) {
if (apiName.toLowerCase() != enteredName.toLowerCase()) {
final msg = "Company name does not match GST record ('$apiName')";
CustomSnackBar.showWarning(context: context, message: msg);
isValid = false;
} else {
isValid = true;
nameError = null;
}
}
}
if (commonResponse != null){
final message = (commonResponse?.message ?? "").trim();
final enteredName = nameController.text.trim();
if (message != "Can Proceed" ) {
isValid = false;
CustomSnackBar.showWarning(context: context, message: message);
} else {
isValid = true;
}
}
final apiName = (gstResponse?.legalNameOfBusiness ?? "").trim();
final enteredName = nameController.text.trim();
if (apiName.isNotEmpty && enteredName.isNotEmpty) {
if (apiName.toLowerCase() != enteredName.toLowerCase()) {
nameError = "Company name does not match GST record ('$apiName')";
} else {
nameError = null;
}
}
if (mobileController.text.trim().isEmpty) { if (mobileController.text.trim().isEmpty) {
mobileError = "Please Enter Mobile Number"; mobileError = "Please Enter Mobile Number";
isValid = false; isValid = false;
...@@ -392,109 +757,67 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -392,109 +757,67 @@ class Accountslistprovider extends ChangeNotifier {
return isValid; return isValid;
} }
bool validateStep2() { bool validateStep2() {
stateError = null; stateError = null;
districtError = null; districtError = null;
localityError = null; localityError = null;
addressError = null; addressError = null;
bool isValid = true; bool isValid = true;
// if (_selectedState == null || _selectedStateID!.isEmpty) { // optional step — you commented it optional. Keep commented validations deactivated.
// stateError = "Please select a State";
// isValid = false;
// }
// if (_selectedDistricts == null || _selectedDistrictID!.isEmpty) {
// districtError = "Please select a District";
// isValid = false;
// }
// if (_selectedSubLocations == null || _selectedSubLocID!.isEmpty) {
// localityError = "Please select a Locality";
// isValid = false;
// }
// if (addressController.text.trim().isEmpty) {
// addressError = "Please Enter an Address";
// isValid = false;
// }
_submitClicked = false; _submitClicked = false;
notifyListeners(); notifyListeners();
return isValid; return isValid;
} }
bool validateStep3() { bool validateStep3(BuildContext context) {
banknameError = null; banknameError = null;
bankBranchError = null; bankBranchError = null;
bankIFSCError = null; bankIFSCError = null;
bankHolderNameError = null; bankHolderNameError = null;
bankAcNumberError = null; bankAcNumberError = null;
upiError = null; upiError = null;
gstNumberError = null;
bool isValid = true; bool isValid = true;
// if (bankNameController.text
// .trim()
// .isEmpty) {
// banknameError = "Please Enter a Bank Name";
// isValid = false;
// }
//
// if (branchNameController.text
// .trim()
// .isEmpty) {
// bankBranchError = "Please Enter Branch Name";
// isValid = false;
// }
// if (bankIfscCotroller.text
// .trim()
// .isEmpty) {
// bankIFSCError = "Please Enter Bank IFSC";
// isValid = false;
// }
// if (bankHolderNameController.text
// .trim()
// .isEmpty) {
// bankHolderNameError = "Please Enter Account Holder Name";
// isValid = false;
// }
// if (bankAcNumberController.text
// .trim()
// .isEmpty) {
// bankAcNumberError = "Please Enter Bank Account Number";
// isValid = false;
// }
// if (bankUpiController.text
// .trim()
// .isEmpty) {
// upiError = "Please Enter UPI ID";
// isValid = false;
// }
_submitClicked = false; _submitClicked = false;
if (gstResponse != null){
final apiName = (gstResponse?.legalNameOfBusiness ?? "").trim();
final enteredName = nameController.text.trim();
if (apiName.isNotEmpty && enteredName.isNotEmpty) {
if (apiName.toLowerCase() != enteredName.toLowerCase()) {
final msg = "Company name does not match GST record ('$apiName')";
CustomSnackBar.showWarning(context: context, message: msg);
isValid = false;
} else {
isValid = true;
nameError = null;
}
}
}
notifyListeners(); notifyListeners();
return isValid; return isValid;
} }
bool validateStep4() { bool validateStep4() {
bool isValid = true; bool isValid = true;
// if (contectPersonDesignationController.text
// .trim()
// .isEmpty) {
// desigantionError = "Please Enter Designation";
// isValid = false;
// }
// if (contectPersonAltMobController.text
// .trim()
// .isEmpty) {
// altMobError = "Please Enter Mobile Number";
// isValid = false;
// }
//
// }
// if (contectPersonTeleController.text.trim().isEmpty) {
// teleError= "Please Enter Telephone"; isValid = false;
// }
// if (contectPersonMailController.text.trim().isEmpty) {
// teleError= "Please Enter"; isValid = false;
// }
_submitClicked = false; _submitClicked = false;
notifyListeners(); if (gstResponse != null){
final apiName = (gstResponse?.legalNameOfBusiness ?? "").trim();
final enteredName = nameController.text.trim();
if (apiName.isNotEmpty && enteredName.isNotEmpty) {
if (apiName.toLowerCase() != enteredName.toLowerCase()) {
isValid = false;
} else {
isValid = true;
nameError = null;
}
}
}
notifyListeners();
return isValid; return isValid;
} }
...@@ -507,6 +830,7 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -507,6 +830,7 @@ class Accountslistprovider extends ChangeNotifier {
localityError = null; localityError = null;
addressError = null; addressError = null;
banknameError = null; banknameError = null;
gstNumberError = null;
bankBranchError = null; bankBranchError = null;
bankIFSCError = null; bankIFSCError = null;
bankHolderNameError = null; bankHolderNameError = null;
...@@ -535,94 +859,32 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -535,94 +859,32 @@ class Accountslistprovider extends ChangeNotifier {
contactPersonError = "Please Enter Contact Person Name"; contactPersonError = "Please Enter Contact Person Name";
isValid = false; isValid = false;
} }
//
// if (commonResponse != null){
// if (!_isVisible && !hasFilledAdditionalDetails) { final message = (commonResponse?.message ?? "").trim();
// addMoreDetailsError = "Please Add More Details to Continue"; final enteredName = nameController.text.trim();
// isValid = false;
// } if (message != "Can Proceed" ) {
// if(_isVisible) { isValid = false;
// CustomSnackBar.showWarning(context: context, message: message);
// if (_selectedState == null || _selectedStateID!.isEmpty) { } else {
// stateError = "Please select a State"; isValid = true;
// isValid = false; }
// } }
// if (_selectedDistricts == null || _selectedDistrictID!.isEmpty) { final apiName = (gstResponse?.legalNameOfBusiness ?? "").trim();
// districtError = "Please select a District"; final enteredName = nameController.text.trim();
// isValid = false;
// } if (apiName.isNotEmpty && enteredName.isNotEmpty) {
// if (_selectedSubLocations == null || _selectedSubLocID!.isEmpty) { if (apiName.toLowerCase() != enteredName.toLowerCase()) {
// localityError = "Please select a Locality"; isValid = false;
// isValid = false; CustomSnackBar.showWarning(context: context, message: "Company name does not match GST record ('$apiName')");
// } nameError = "Company name does not match GST record ('$apiName')";
// if (addressController.text.trim().isEmpty) { } else {
// addressError = "Please Enter an Address"; isValid = true;
// isValid = false; nameError = null;
// } }
// if (bankNameController.text }
// .trim()
// .isEmpty) {
// banknameError = "Please Enter a Bank Name";
// isValid = false;
// }
//
// if (branchNameController.text
// .trim()
// .isEmpty) {
// bankBranchError = "Please Enter Branch Name";
// isValid = false;
// }
// if (bankIfscCotroller.text
// .trim()
// .isEmpty) {
// bankIFSCError = "Please Enter Bank IFSC";
// isValid = false;
// }
// if (bankHolderNameController.text
// .trim()
// .isEmpty) {
// bankHolderNameError = "Please Enter Account Holder Name";
// isValid = false;
// }
// if (bankAcNumberController.text
// .trim()
// .isEmpty) {
// bankAcNumberError = "Please Enter Bank Account Number";
// isValid = false;
// }
// if (bankUpiController.text
// .trim()
// .isEmpty) {
// upiError = "Please Enter UPI ID";
// isValid = false;
// }
// if (contactPersonController.text
// .trim()
// .isEmpty) {
// contactPersonError = "Please Enter Contact Person Name";
// isValid = false;
// }
// if (contectPersonDesignationController.text
// .trim()
// .isEmpty) {
// desigantionError = "Please Enter Designation";
// isValid = false;
// }
// if (contectPersonAltMobController.text
// .trim()
// .isEmpty) {
// altMobError = "Please Enter Mobile Number";
// isValid = false;
// }
//
// }
// if (contectPersonTeleController.text.trim().isEmpty) {
// teleError= "Please Enter Telephone"; isValid = false;
// }
// if (contectPersonMailController.text.trim().isEmpty) {
// teleError= "Please Enter"; isValid = false;
// }
_submitClicked = false; _submitClicked = false;
notifyListeners(); notifyListeners();
return isValid; return isValid;
...@@ -645,67 +907,64 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -645,67 +907,64 @@ class Accountslistprovider extends ChangeNotifier {
void updateBankName(String value) { void updateBankName(String value) {
banknameError = null; banknameError = null;
notifyListeners();
}
/// simplified update - kept for compatibility if UI uses it
void updateGSTNumber(String value) {
// just clear the error when user edits GST
gstNumberError = null;
notifyListeners(); notifyListeners();
} }
void updateBankBranch(String value) { void updateBankBranch(String value) {
bankBranchError = null; bankBranchError = null;
notifyListeners(); notifyListeners();
} }
void updateIFSC(String value) { void updateIFSC(String value) {
bankIFSCError = null; bankIFSCError = null;
notifyListeners(); notifyListeners();
} }
void updateHolder(String value) { void updateHolder(String value) {
bankHolderNameError = null; bankHolderNameError = null;
notifyListeners(); notifyListeners();
} }
void updateNumber(String value) { void updateNumber(String value) {
bankAcNumberError = null; bankAcNumberError = null;
notifyListeners(); notifyListeners();
} }
void updateUPI(String value) { void updateUPI(String value) {
upiError = null; upiError = null;
notifyListeners(); notifyListeners();
} }
void updateContactPerson(String value) { void updateContactPerson(String value) {
contactPersonError = null; contactPersonError = null;
notifyListeners(); notifyListeners();
} }
void updateDesignation(String value) { void updateDesignation(String value) {
desigantionError = null; desigantionError = null;
notifyListeners(); notifyListeners();
} }
void updateAltMobile(String value) { void updateAltMobile(String value) {
altMobError = null; altMobError = null;
notifyListeners(); notifyListeners();
} }
void updateTeleMobile(String value) { void updateTeleMobile(String value) {
teleError = null; teleError = null;
notifyListeners(); notifyListeners();
} }
void updateMail(String value) { void updateMail(String value) {
mailError = null; mailError = null;
notifyListeners(); notifyListeners();
} }
...@@ -717,14 +976,11 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -717,14 +976,11 @@ class Accountslistprovider extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
String? _errorMessage;
String? get errorMessage => _errorMessage;
// Common Account list provider // Common Account list provider
Future<void> commonAccountListAPIFunction( Future<void> commonAccountListAPIFunction(
BuildContext context, { BuildContext context, {
bool append = false, bool append = false,
}) async { }) async {
try { try {
var prov = Provider.of<HomescreenNotifier>(context, listen: false); var prov = Provider.of<HomescreenNotifier>(context, listen: false);
...@@ -747,19 +1003,13 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -747,19 +1003,13 @@ class Accountslistprovider extends ChangeNotifier {
companyNameController.text, companyNameController.text,
mobileNumberController.text, mobileNumberController.text,
); );
debugPrint( debugPrint('empId: ${prov.empId}, session: ${prov.session}, pageNumber: $_pageNum');
'empId: ${prov.empId}, session: ${prov.session}, pageNumber: $_pageNum',
);
if (data != null && data.error == "0") { if (data != null && data.error == "0") {
if (data.accountList != null) { if (data.accountList != null) {
if (append) { if (append) {
// Append with deduplication
final existingIds = _accountsList.map((e) => e.id).toSet(); final existingIds = _accountsList.map((e) => e.id).toSet();
final newItems = final newItems = data.accountList!.where((item) => !existingIds.contains(item.id)).toList();
data.accountList!
.where((item) => !existingIds.contains(item.id))
.toList();
_accountsList.addAll(newItems); _accountsList.addAll(newItems);
} else { } else {
_accountsList = data.accountList!; _accountsList = data.accountList!;
...@@ -779,7 +1029,7 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -779,7 +1029,7 @@ class Accountslistprovider extends ChangeNotifier {
} }
resetValues() { resetValues() {
print("rv"); if (kDebugMode) debugPrint("rv");
_selectedAccountType = null; _selectedAccountType = null;
_selectedState = null; _selectedState = null;
_selectedDistricts = null; _selectedDistricts = null;
...@@ -791,6 +1041,10 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -791,6 +1041,10 @@ class Accountslistprovider extends ChangeNotifier {
_selectedSubLocID = null; _selectedSubLocID = null;
_selectedSubLocValue = null; _selectedSubLocValue = null;
gstResponse = null;
bankResponse = null;
errorMessage = null;
_isVisible = false; _isVisible = false;
stateSearchController.clear(); stateSearchController.clear();
districtSearchController.clear(); districtSearchController.clear();
...@@ -819,6 +1073,7 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -819,6 +1073,7 @@ class Accountslistprovider extends ChangeNotifier {
localityError = null; localityError = null;
addressError = null; addressError = null;
banknameError = null; banknameError = null;
gstNumberError = null;
bankBranchError = null; bankBranchError = null;
bankIFSCError = null; bankIFSCError = null;
bankHolderNameError = null; bankHolderNameError = null;
...@@ -836,21 +1091,18 @@ class Accountslistprovider extends ChangeNotifier { ...@@ -836,21 +1091,18 @@ class Accountslistprovider extends ChangeNotifier {
} }
void ChechkDropdownValues() { void ChechkDropdownValues() {
if (!_accountTypes.contains(_selectedAccountType) && if (!_accountTypes.contains(_selectedAccountType) && _selectedAccountType != null) {
_selectedAccountType != null) {
_selectedAccountType = null; _selectedAccountType = null;
} }
if (!_states.contains(_selectedState) && _selectedState != null) { if (!_states.contains(_selectedState) && _selectedState != null) {
_selectedStateID = null; _selectedStateID = null;
_selectedStateValue = null; _selectedStateValue = null;
} }
if (!_districts.contains(_selectedDistricts) && if (!_districts.contains(_selectedDistricts) && _selectedDistricts != null) {
_selectedDistricts != null) {
_selectedDistrictID = null; _selectedDistrictID = null;
_selectedDistrictValue = null; _selectedDistrictValue = null;
} }
if (!_subLocations.contains(_selectedSubLocations) && if (!_subLocations.contains(_selectedSubLocations) && _selectedSubLocations != null) {
_selectedSubLocations != null) {
_selectedSubLocID = null; _selectedSubLocID = null;
_selectedSubLocValue = null; _selectedSubLocValue = null;
} }
......
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:generp/Notifiers/HomeScreenNotifier.dart';
import 'package:generp/services/api_calling.dart';
import 'package:generp/Utils/commonServices.dart';
import 'package:provider/provider.dart';
import '../../Models/commonModels/DistrictsResponse.dart';
import '../../Models/commonModels/EditCommonAccFormDetailsResponse.dart';
import '../../Models/commonModels/SubLocationsResponse.dart';
import '../../Models/financeModels/ValidateBankAccountDetailsResponse.dart';
import '../../Models/financeModels/ValidateGstNumResponse.dart';
import '../../Models/commonModels/commonAddAccountsViewResponse.dart';
class EditCommonAccountProvider extends ChangeNotifier {
// --- Text controllers used by edit form (only required ones) ---
final TextEditingController nameController = TextEditingController();
final TextEditingController mobileController = TextEditingController();
final TextEditingController addressController = TextEditingController();
final TextEditingController bankNameController = TextEditingController();
final TextEditingController branchNameController = TextEditingController();
final TextEditingController bankIfscCotroller = TextEditingController();
final TextEditingController bankHolderNameController = TextEditingController();
final TextEditingController gstNumberController = TextEditingController();
final TextEditingController bankAcNumberController = TextEditingController();
final TextEditingController bankUpiController = TextEditingController();
// contact person details (kept because your form uses them)
final TextEditingController contactPersonController = TextEditingController();
// final TextEditingController contectPersonDesignationController = TextEditingController();
// final TextEditingController contectPersonAltMobController = TextEditingController();
// final TextEditingController contectPersonTeleController = TextEditingController();
final TextEditingController contectPersonMailController = TextEditingController();
// small search controllers for dropdown search widgets
final TextEditingController stateSearchController = TextEditingController();
final TextEditingController districtSearchController = TextEditingController();
final TextEditingController subLocSearchController = TextEditingController();
// --- simple error strings for UI ---
String? accountError;
String? nameError;
String? mobileError;
String? stateError;
String? districtError;
String? localityError;
String? addressError;
String? gstNumberError;
String? banknameError;
String? bankBranchError;
String? bankIFSCError;
String? bankHolderNameError;
String? bankAcNumberError;
String? upiError;
String? contactPersonError;
String? desigantionError;
String? altMobError;
String? teleError;
String? mailError;
String? addMoreDetailsError;
// --- dropdown lists (populated from addCommonAccountView API) ---
List<String> _accountTypes = [];
List<States> _states = [];
List<Districts> _districts = [];
List<SubLocations> _subLocations = [];
// selection holders
String? _selectedAccountType;
States? _selectedState;
Districts? _selectedDistricts;
SubLocations? _selectedSubLocations;
// IDs / values (strings) used when sending API
String? _selectedStateID;
String? _selectedDistrictID;
String? _selectedSubLocID;
// responses from validation APIs
ValidateGstNumResponse? gstResponse;
ValidateBankAccountDetailsResponse? bankResponse;
commonAddAccountsViewResponse? commonResponse;
// loading & submit state
bool _isLoading = false;
bool _isSubmitting = false;
String? updateErrorMessage;
// getters
bool get isLoading => _isLoading;
bool get isSubmitting => _isSubmitting;
List<States> get states => _states;
List<Districts> get districts => _districts;
List<SubLocations> get subLocations => _subLocations;
String? get selectedAccountType => _selectedAccountType;
States? get selectedState => _selectedState;
Districts? get selectedDistricts => _selectedDistricts;
SubLocations? get selectedSubLocations => _selectedSubLocations;
String? get selectedStateID => _selectedStateID;
String? get selectedDistrictId => _selectedDistrictID;
String? get selectedSubLocID => _selectedSubLocID;
bool _submitClicked = false;
bool get submitClickced => _submitClicked;
set submitClickced(bool value) {
_submitClicked = value;
notifyListeners();
}
// --- setters that clear corresponding errors and notify ---
set selectedAccountType(String? v) {
_selectedAccountType = v;
accountError = null;
notifyListeners();
}
set selectedState(States? v) {
_selectedState = v;
_selectedStateID = v?.id;
stateError = null;
// clear dependent district/subLocation when state changes
_districts.clear();
_selectedDistricts = null;
_selectedDistrictID = null;
_subLocations.clear();
_selectedSubLocations = null;
_selectedSubLocID = null;
notifyListeners();
}
set selectedDistricts(Districts? v) {
_selectedDistricts = v;
_selectedDistrictID = v?.id;
districtError = null;
_subLocations.clear();
_selectedSubLocations = null;
_selectedSubLocID = null;
notifyListeners();
}
set selectedSubLocations(SubLocations? v) {
_selectedSubLocations = v;
_selectedSubLocID = v?.id;
localityError = null;
notifyListeners();
}
set isLoading(bool v) {
_isLoading = v;
notifyListeners();
}
EditCommonAccFormDetailsResponse? detailsListResponse;
// LOAD ACCOUNT DETAILS + PREFILL ALL FIELDS
// ==========================================================
Future<bool> loadAccountDetailsForEdit(
BuildContext context,
String accountId,
) async {
try {
isLoading = true;
notifyListeners();
final homeProv = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.commonAccountDetailsListAPI(
homeProv.empId,
homeProv.session,
accountId,
);
detailsListResponse =data;
if (data == null || data.error != "0") {
updateErrorMessage = data?.message ?? "Failed to load account details";
isLoading = false;
notifyListeners();
return false;
}
// Expecting at least one account in the list; take the first.
if (data.accountList == null || data.accountList!.isEmpty) {
updateErrorMessage = "No account data returned";
isLoading = false;
notifyListeners();
return false;
}
final acc = data.accountList!.first;
// 1) PREFILL TEXT CONTROLLERS
// ---------------------------
nameController.text = acc.name ?? "";
mobileController.text = acc.mob1 ?? "";
addressController.text = acc.address ?? "";
bankNameController.text = acc.bankName ?? "";
branchNameController.text = acc.bankBranchName ?? "";
bankIfscCotroller.text = acc.bankIfscCode ?? "";
bankHolderNameController.text = acc.bankAccountHolderName ?? "";
bankAcNumberController.text = acc.bankAccountNumber ?? "";
bankUpiController.text = acc.bankUpiId ?? "";
gstNumberController.text = acc.gstNumber ?? "";
// contact person (if API has contact_name)
contactPersonController.text = acc.contactName ?? "";
// Other contact fields in API aren't present — keep empty or preserve existing
contectPersonMailController.text = acc.email ?? "";
// ---------------------------
// 2) PREFILL ACCOUNT TYPE
// ---------------------------
selectedAccountType = acc.type;
// ---------------------------
// 3) LOAD DROPDOWNS (account types, states)
// ---------------------------
await addCommonAccountViewAPI(context);
// ---------------------------
// 4) SELECT STATE (by name)
// ---------------------------
if (acc.state != null && acc.state!.trim().isNotEmpty) {
final matchState = _states.firstWhere(
(s) => (s.name ?? "").toLowerCase() == acc.state!.trim().toLowerCase(),
orElse: () => States(id: null, name: null),
);
if (matchState.id != null) {
// use setter so it clears errors and resets dependent lists
selectedState = matchState;
_selectedStateID = matchState.id;
// load districts for this state
await getDistrictAPI(context, matchState.id);
}
}
// ---------------------------
// 5) SELECT DISTRICT (by name)
// ---------------------------
if (acc.district != null && acc.district!.trim().isNotEmpty && _districts.isNotEmpty) {
final matchDist = _districts.firstWhere(
(d) => (d.district ?? "").toLowerCase() == acc.district!.trim().toLowerCase(),
orElse: () => Districts(id: null, district: null),
);
if (matchDist.id != null) {
selectedDistricts = matchDist;
_selectedDistrictID = matchDist.id;
// load sub-localities for this district
await getSubLocationAPI(context, matchDist.id);
}
}
// ---------------------------
// 6) SELECT SUB-LOCALITY (by name)
// ---------------------------
if (acc.subLocality != null && acc.subLocality!.trim().isNotEmpty && _subLocations.isNotEmpty) {
final matchSub = _subLocations.firstWhere(
(s) => (s.subLocality ?? "").toLowerCase() == acc.subLocality!.trim().toLowerCase(),
orElse: () => SubLocations(id: null, subLocality: null),
);
if (matchSub.id != null) {
selectedSubLocations = matchSub;
_selectedSubLocID = matchSub.id;
}
}
// everything loaded
isLoading = false;
notifyListeners();
return true;
} catch (e, s) {
if (kDebugMode) debugPrint("loadAccountDetailsForEdit ERROR => $e\n$s");
updateErrorMessage = e.toString();
isLoading = false;
notifyListeners();
return false;
}
}
Future<void> getDistrictAPI(context, stateID) async {
try {
var homeProv = Provider.of<HomescreenNotifier>(context, listen: false);
_districts.clear();
notifyListeners();
final data = await ApiCalling.commonAddAccountViewDistrictAPI(
homeProv.empId,
homeProv.session,
stateID,
);
if (data != null) {
if (data.error == "0") {
_districts = data.districts ?? [];
notifyListeners();
}
}
} catch (e) {
if (kDebugMode) debugPrint('getDistrictAPI error: $e');
}
}
Future<void> getSubLocationAPI(context, districtID) async {
try {
var homeProv = Provider.of<HomescreenNotifier>(context, listen: false);
_subLocations.clear();
notifyListeners();
final data = await ApiCalling.commonAddAccountViewSubLocationAPI(
homeProv.empId,
homeProv.session,
districtID,
);
if (data != null) {
if (data.error == "0") {
_subLocations = data.subLocations ?? [];
notifyListeners();
}
}
} catch (e) {
if (kDebugMode) debugPrint('getSubLocationAPI error: $e');
}
}
// --- API: load data needed to populate dropdowns (account types, states) ---
Future<void> addCommonAccountViewAPI(BuildContext context) async {
try {
isLoading = true;
var homeProv = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.commonAddAccountViewAPI(homeProv.empId, homeProv.session);
_accountTypes.clear();
_states.clear();
if (data != null && data.error == "0") {
_accountTypes = data.accountTypes ?? [];
_states = data.states ?? [];
commonResponse = data;
}
} catch (e) {
if (kDebugMode) debugPrint('addCommonAccountViewAPI error: $e');
} finally {
isLoading = false;
notifyListeners();
}
}
// --- GST validation: calls API and sets gstResponse; returns true if valid ---
Future<bool> validateGstNumber(String empId, String sessionId, String gstNumber) async {
if (gstNumber.trim().isEmpty) {
gstResponse = null;
gstNumberError = null;
notifyListeners();
return false;
}
try {
isLoading = true;
final response = await ApiCalling.validateGstNumberApi(empId, sessionId, gstNumber.trim());
gstResponse = response;
if (response == null) {
gstNumberError = "Failed to validate GST number";
notifyListeners();
return false;
}
if (response.error == "0") {
gstNumberError = null;
notifyListeners();
return true;
} else {
gstNumberError = response.message ?? "Invalid GST number";
notifyListeners();
return false;
}
} catch (e) {
gstNumberError = "Error validating GST: ${e.toString()}";
if (kDebugMode) debugPrint('validateGstNumber error: $e');
notifyListeners();
return false;
} finally {
isLoading = false;
notifyListeners();
}
}
// --- Bank validation: requires both account number and IFSC ---
Future<bool> validateBankDetails(String empId, String sessionId, String accountNumber) async {
final ifsc = bankIfscCotroller.text.trim();
final accList = detailsListResponse?.accountList!.first;
if (accountNumber.trim().isEmpty || ifsc.isEmpty) {
bankResponse = null;
bankAcNumberError = null;
bankIFSCError = null;
bankNameController.text = "";
branchNameController.text = "";
bankHolderNameController.text = "";
bankNameController.text = accList?.bankName ?? "";
branchNameController.text = accList?.bankBranchName ?? "";
bankHolderNameController.text = accList?.bankAccountHolderName ?? "";
notifyListeners();
return false;
}
if (bankAcNumberController.text.isEmpty || bankIfscCotroller.text.isEmpty) {
bankNameController.text = "";
branchNameController.text = "";
bankHolderNameController.text = "";
bankNameController.text = accList?.bankName ?? "";
branchNameController.text = accList?.bankBranchName ?? "";
bankHolderNameController.text = accList?.bankAccountHolderName ?? "";
notifyListeners();
return false;
}
final reg = RegExp(r'^[A-Za-z]{4}0[A-Za-z0-9]{6}$');
if (!reg.hasMatch(ifsc)) {
bankIFSCError = "Invalid IFSC format";
notifyListeners();
return false;
}
try {
isLoading = true;
final response = await ApiCalling.validateBankAccountDetailsApi(empId, sessionId, accountNumber.trim(), ifsc);
bankResponse = response;
if (response == null) {
bankAcNumberError = "Failed to validate bank account";
notifyListeners();
return false;
}
if (response.error == "0") {
bankAcNumberError = null;
bankIFSCError = null;
notifyListeners();
return true;
} else {
bankAcNumberError = response.message ?? "Invalid account details";
notifyListeners();
return false;
}
} catch (e) {
bankAcNumberError = "Error validating account: ${e.toString()}";
if (kDebugMode) debugPrint('validateBankDetails error: $e');
notifyListeners();
return false;
} finally {
isLoading = false;
notifyListeners();
}
}
// --- Combines validation and applies response (autofill) for GST ---
Future<void> checkAndApplyGst(BuildContext context, String gstNumber) async {
gstNumberError = null;
notifyListeners();
final trimmed = gstNumber.trim();
if (trimmed.isEmpty) {
gstResponse = null;
gstNumberError = null;
notifyListeners();
return;
}
try {
isLoading = true;
final homeProv = Provider.of<HomescreenNotifier>(context, listen: false);
final resp = await ApiCalling.validateGstNumberApi(homeProv.empId, homeProv.session, trimmed);
gstResponse = resp;
if (resp == null) {
gstNumberError = "Failed to validate GST number";
notifyListeners();
return;
}
if (resp.error == "0") {
// autofill address if available
final apiAddress = (resp.address ?? "").trim();
final apiName = (resp.legalNameOfBusiness ?? "").trim();
if (apiAddress.isNotEmpty) {
addressController.text = apiAddress;
}
// compare company name and set error if mismatch
final enteredName = nameController.text.trim();
if (apiName.isNotEmpty && enteredName.isNotEmpty) {
if (apiName.toLowerCase() != enteredName.toLowerCase()) {
nameError = "Name Does not match with GST Legal Name : ('$apiName').";
} else {
nameError = null;
}
}
gstNumberError = null;
notifyListeners();
return;
} else {
_submitClicked = false;
gstNumberError = resp.message ?? "Invalid GST number";
notifyListeners();
return;
}
} catch (e) {
gstNumberError = "Error validating GST";
if (kDebugMode) debugPrint("checkAndApplyGst error: $e");
notifyListeners();
return;
} finally {
isLoading = false;
notifyListeners();
}
}
// --- Combines validation and applies response (autofill) for Bank ---
Future<void> checkAndApplyBank(BuildContext context, String accountNumber) async {
bankAcNumberError = null;
bankIFSCError = null;
notifyListeners();
final acc = accountNumber.trim();
final ifsc = bankIfscCotroller.text.trim();
if (acc.isEmpty && ifsc.isEmpty) {
bankResponse = null;
bankAcNumberError = null;
bankIFSCError = null;
notifyListeners();
return;
}
// If account entered, IFSC required
if (acc.isNotEmpty && ifsc.isEmpty) {
bankIFSCError = "IFSC is required when account number is entered";
notifyListeners();
return;
}
// validate IFSC format
final ifscReg = RegExp(r'^[A-Za-z]{4}0[A-Za-z0-9]{6}$');
if (ifsc.isNotEmpty && !ifscReg.hasMatch(ifsc)) {
bankIFSCError = "Invalid IFSC format";
notifyListeners();
return;
}
if (acc.isNotEmpty && ifsc.isNotEmpty) {
try {
isLoading = true;
final homeProv = Provider.of<HomescreenNotifier>(context, listen: false);
final resp = await ApiCalling.validateBankAccountDetailsApi(homeProv.empId, homeProv.session, acc, ifsc);
bankResponse = resp;
if (resp == null) {
bankAcNumberError = "Failed to validate bank details";
notifyListeners();
return;
}
if (resp.error == "0") {
// autofill bank fields from response
bankNameController.text = resp.bankName ?? bankNameController.text;
branchNameController.text = resp.branch ?? branchNameController.text;
bankHolderNameController.text = resp.nameAtBank ?? bankHolderNameController.text;
bankAcNumberError = null;
bankIFSCError = null;
banknameError = null;
bankBranchError = null;
bankHolderNameError = null;
notifyListeners();
return;
} else {
bankAcNumberError = resp.message ?? "Invalid account details";
notifyListeners();
return;
}
} catch (e) {
bankAcNumberError = "Error validating bank: ${e.toString()}";
if (kDebugMode) debugPrint("checkAndApplyBank error: $e");
notifyListeners();
return;
} finally {
isLoading = false;
notifyListeners();
}
}
}
// --- Re-compare company name with GST (UI calls this on name change) ---
void recheckNameWithGst() {
if (gstResponse == null) return;
final apiName = (gstResponse?.legalNameOfBusiness ?? "").trim();
final enteredName = nameController.text.trim();
if (apiName.isNotEmpty && enteredName.isNotEmpty) {
if (apiName.toLowerCase() != enteredName.toLowerCase()) {
nameError = "Name Does not match with GST Legal Name : ('$apiName').";
} else {
nameError = null;
}
}
notifyListeners();
}
Future<void> checkInputsAPI(context, type, value) async {
try {
var homeProv = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.commonAddAccountCheckInputsAPI(
homeProv.empId,
homeProv.session,
type,
value,
);
commonResponse =data;
if (data != null) {
if (data.error == "0") {
nameError = null;
mobileError = null;
notifyListeners();
} else if (data.error == "1") {
if (data.message?.contains("name already exists") ?? false) {
nameError = data.message ?? "";
} else {
mobileError = data.message ?? "";
}
notifyListeners();
}
}
} catch (e) {
if (kDebugMode) debugPrint('checkInputsAPI error: $e');
}
}
// --- Submit (update) API function (calls your existing commonUpdateAccountDetailsAPI) ---
Future<bool> updateAccountDetailsAPIFunction(
BuildContext context, {
required String accId,
required String name,
required String mob1,
String? mob2,
String? tel,
String? email,
String? designation,
String? address,
String? state,
String? district,
String? subLocality,
String? bankName,
String? branchName,
String? bankIfscCode,
String? accHolderName,
String? bankAccNumber,
String? bankUpiId,
}) async {
try {
_isSubmitting = true;
updateErrorMessage = null;
notifyListeners();
var prov = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.commonUpdateAccountDetailsAPI(
prov.empId,
prov.session,
accId,
name,
mob1,
mob2 ?? '',
tel ?? '',
email ?? '',
designation ?? '',
address ?? '',
state ?? '',
district ?? '',
subLocality ?? '',
bankName ?? '',
branchName ?? '',
bankIfscCode ?? '',
accHolderName ?? '',
bankAccNumber ?? '',
bankUpiId ?? '',
);
if (data == null) {
updateErrorMessage = "No response from server";
_isSubmitting = false;
notifyListeners();
return false;
}
if (data.error == "0" || data.error == 0) {
toast(context, data.message ?? "Updated successfully");
_isSubmitting = false;
notifyListeners();
return true;
} else {
updateErrorMessage = data.message ?? "Failed to update account";
_isSubmitting = false;
notifyListeners();
return false;
}
} catch (e, s) {
if (kDebugMode) debugPrint("updateAccountDetailsAPIFunction error: $e\n$s");
updateErrorMessage = e.toString();
_isSubmitting = false;
notifyListeners();
return false;
}
}
bool _isGstValidFormat(String gst) {
gst = gst.trim().toUpperCase();
final reg = RegExp(r'^[0-3][0-9][A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$');
return reg.hasMatch(gst);
}
// --- Simple validation (keeps same logic as your UI expects) ---
bool validateStep1(BuildContext context) {
accountError = null;
nameError = null;
mobileError = null;
gstNumberError = null;
contactPersonError = null;
bool isValid = true;
if (_selectedAccountType == null || _selectedAccountType!.isEmpty) {
accountError = "Please select an Account";
isValid = false;
}
if (nameController.text.trim().isEmpty) {
nameError = "Please Enter a Name";
isValid = false;
}
if(gstNumberController.text.trim().isNotEmpty){
final gst = gstNumberController.text.trim();
if (!_isGstValidFormat(gst)) {
gstNumberError = "Invalid GST format";notifyListeners();
isValid = false;
}
}
if(gstNumberController.text.isEmpty){
final accList = detailsListResponse?.accountList!.first;
final gst = gstNumberController.text.trim();
addressController.text = accList?.address ?? "";
}
if (nameError != null && nameError!.isNotEmpty) {
isValid = false;
}
if (mobileController.text.trim().isNotEmpty && mobileController.text.length < 10) {
mobileError = "Mobile Number should be 10 digits";
isValid = false;
}
if (mobileController.text.trim().isEmpty) {
mobileError = "Please Enter Mobile Number";
isValid = false;
}
if (contactPersonController.text.trim().isEmpty) {
contactPersonError = "Please Enter Contact Person Name";
isValid = false;
}
// GST vs name check if gstResponse present
if (gstResponse != null) {
final apiName = (gstResponse?.legalNameOfBusiness ?? "").trim();
final enteredName = nameController.text.trim();
if (apiName.isNotEmpty && enteredName.isNotEmpty) {
if (apiName.toLowerCase() != enteredName.toLowerCase()) {
nameError = "Company name does not match GST record ('$apiName')";
isValid = false;
} else {
nameError = null;
}
}
}
notifyListeners();
return isValid;
}
bool validateStep() {
final accList = detailsListResponse?.accountList!.first;
if (gstNumberController.text.isEmpty) {
final gst = gstNumberController.text.trim();
addressController.text = accList?.address ?? "";
}
notifyListeners();
return false;
}
bool validateStep3() {
final accList = detailsListResponse?.accountList!.first;
if (bankAcNumberController.text.isEmpty || bankIfscCotroller.text.isEmpty) {
bankNameController.text = "";
branchNameController.text = "";
bankHolderNameController.text = "";
bankNameController.text = accList?.bankName ?? "";
branchNameController.text = accList?.bankBranchName ?? "";
bankHolderNameController.text = accList?.bankAccountHolderName ?? "";
notifyListeners();
return false;
}
bool isValid = true;
// optional step — you commented it optional. Keep commented validations deactivated.
_submitClicked = false;
notifyListeners();
return isValid;
}
// Full form final validation before submit
bool validatereceiptForm(BuildContext context) {
// reset error holders
accountError = null; nameError = null; mobileError = null;
stateError = null; districtError = null; localityError = null; addressError = null;
banknameError = null; gstNumberError = null; bankBranchError = null; bankIFSCError = null;
bankHolderNameError = null; bankAcNumberError = null; upiError = null;
contactPersonError = null; desigantionError = null; altMobError = null; teleError = null; mailError = null;
bool isValid = true;
if (_selectedAccountType == null || _selectedAccountType!.isEmpty) {
accountError = "Please select an Account";
isValid = false;
}
if (nameController.text.trim().isEmpty) {
nameError = "Please Enter a Name";
isValid = false;
}
if (mobileController.text.trim().isEmpty) {
mobileError = "Please Enter Mobile Number";
isValid = false;
}
if (contactPersonController.text.trim().isEmpty) {
contactPersonError = "Please Enter Contact Person Name";
isValid = false;
}
// GST check
final apiName = (gstResponse?.legalNameOfBusiness ?? "").trim();
final enteredName = nameController.text.trim();
if (apiName.isNotEmpty && enteredName.isNotEmpty) {
if (apiName.toLowerCase() != enteredName.toLowerCase()) {
isValid = false;
nameError = "Company name does not match GST record ('$apiName')";
}
}
notifyListeners();
return isValid;
}
// --- update helper setters to clear errors on edit ---
void updateName(String value) {
nameError = null;
notifyListeners();
}
void updateMobile(String value) {
mobileError = null;
notifyListeners();
}
void updateAddress(String value) {
addressError = null;
notifyListeners();
}
void updateBankName(String value) {
banknameError = null;
notifyListeners();
}
void updateGSTNumber(String value) {
gstNumberError = null;
notifyListeners();
}
void updateBankBranch(String value) {
bankBranchError = null;
notifyListeners();
}
void updateIFSC(String value) {
bankIFSCError = null;
notifyListeners();
}
void updateHolder(String value) {
bankHolderNameError = null;
notifyListeners();
}
void updateNumber(String value) {
bankAcNumberError = null;
notifyListeners();
}
void updateUPI(String value) {
upiError = null;
notifyListeners();
}
void updateContactPerson(String value) {
contactPersonError = null;
notifyListeners();
}
void updateDesignation(String value) {
desigantionError = null;
notifyListeners();
}
void updateAltMobile(String value) {
altMobError = null;
notifyListeners();
}
void updateTeleMobile(String value) {
teleError = null;
notifyListeners();
}
void updateMail(String value) {
mailError = null;
notifyListeners();
}
// --- Reset values used by Edit form (clears controllers + errors + selections) ---
void resetValues() {
_selectedAccountType = null;
_selectedState = null;
_selectedDistricts = null;
_selectedSubLocations = null;
_selectedStateID = null;
_selectedDistrictID = null;
_selectedSubLocID = null;
gstResponse = null;
bankResponse = null;
commonResponse = null;
updateErrorMessage = null;
_isLoading = false;
_isSubmitting = false;
stateSearchController.clear();
districtSearchController.clear();
subLocSearchController.clear();
nameController.clear();
mobileController.clear();
addressController.clear();
bankNameController.clear();
branchNameController.clear();
bankIfscCotroller.clear();
bankHolderNameController.clear();
bankAcNumberController.clear();
bankUpiController.clear();
contactPersonController.clear();
contectPersonMailController.clear();
accountError = null;
nameError = null;
mobileError = null;
stateError = null;
districtError = null;
localityError = null;
addressError = null;
banknameError = null;
gstNumberError = null;
bankBranchError = null;
bankIFSCError = null;
bankHolderNameError = null;
bankAcNumberError = null;
upiError = null;
contactPersonError = null;
desigantionError = null;
altMobError = null;
teleError = null;
mailError = null;
addMoreDetailsError = null;
notifyListeners();
}
// dispose controllers when provider is disposed (optional)
@override
void dispose() {
nameController.dispose();
mobileController.dispose();
addressController.dispose();
bankNameController.dispose();
branchNameController.dispose();
bankIfscCotroller.dispose();
bankHolderNameController.dispose();
gstNumberController.dispose();
bankAcNumberController.dispose();
bankUpiController.dispose();
contactPersonController.dispose();
contectPersonMailController.dispose();
stateSearchController.dispose();
districtSearchController.dispose();
subLocSearchController.dispose();
super.dispose();
}
}
import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:generp/Notifiers/HomeScreenNotifier.dart';
import 'package:generp/Utils/SharedpreferencesService.dart';
import 'package:generp/screens/LoginScreen.dart';
import 'package:generp/services/api_calling.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:image_picker/image_picker.dart';
import 'package:geocoding/geocoding.dart' as geocoding;
import 'package:location/location.dart' as Location;
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import '../../Models/NearbyGeneratorsResponse.dart';
import '../../Utils/commonServices.dart';
class CrmNearByGeneratorsProvider extends ChangeNotifier {
final ImagePicker _picker = ImagePicker();
List<Nearbygenerators> _generatorslist = [];
final TextEditingController _locationController = TextEditingController();
final String _googleApikey = "AIzaSyBGzvgMMKwPBAANTwaoRsAnrCpiWCj8wVs";
GoogleMapController? _mapController;
CameraPosition? _cameraPosition;
final LatLng _startLocation = const LatLng(
17.439112226708446,
78.43292499146135,
);
String _latlongs = "";
List<Marker> _markers = [];
List<String> _addresses = [];
Location.LocationData? _currentLocation;
bool _isLocationEnabled = false;
bool _hasLocationPermission = false;
Timer? _timer;
File? _image;
bool _isLoading = true;
String _selectedItem = 'Active';
double _currentValue = 1.0;
Timer? _debounceTimer;
List<Nearbygenerators> get generatorsList => _generatorslist;
TextEditingController get LocationController => _locationController;
String get googleAPIKey => _googleApikey;
GoogleMapController? get mapController => _mapController;
CameraPosition? get cameraPosition => _cameraPosition;
LatLng get startLocation => _startLocation;
String get latlongs => _latlongs;
List<Marker> get markers => _markers;
List<String> get addresses => _addresses;
Location.LocationData? get currentLocation => _currentLocation;
bool get isLocationEnabled => _isLocationEnabled;
bool get hasLocationPermission => _hasLocationPermission;
bool get isLoading => _isLoading;
Timer? get timer => _timer;
File? get image => _image;
String get selectedItem => _selectedItem;
double get currentValue => _currentValue;
set currentValue(value) {
_currentValue = value;
notifyListeners();
}
set selectedItem(String value) {
_selectedItem = value;
notifyListeners();
}
set markers(List<Marker> value) {
_markers = value;
notifyListeners();
}
set mapController(value) {
_mapController = value;
notifyListeners();
}
void resetAll() {
_currentValue = 1.0;
_selectedItem = "";
_markers = [];
_addresses = [];
}
Future<void> getLocationPermission(context) async {
// Check if location services are enabled
_isLocationEnabled = await Geolocator.isLocationServiceEnabled();
// Check if the app has been granted location permission
LocationPermission permission = await Geolocator.checkPermission();
_hasLocationPermission =
permission == LocationPermission.always ||
permission == LocationPermission.whileInUse;
final Location.Location location = Location.Location();
bool serviceEnabled;
Location.PermissionStatus permissionGranted;
serviceEnabled = await location.serviceEnabled();
if (!serviceEnabled) {
serviceEnabled = await location.requestService();
if (!serviceEnabled) {
return;
}
}
_isLoading = false;
permissionGranted = (await location.hasPermission());
if (permissionGranted == PermissionStatus) {
permissionGranted = (await location.requestPermission());
if (permissionGranted != PermissionStatus) {
return;
}
}
final Location.LocationData locData = await location.getLocation();
_currentLocation = locData;
if (_currentLocation != null) {
_mapController?.animateCamera(
CameraUpdate.newLatLng(
LatLng(_currentLocation!.latitude!, _currentLocation!.longitude!),
),
);
final lat = _currentLocation!.latitude;
final lang = _currentLocation!.longitude!;
_latlongs = '$lat,$lang';
LoadNearbyGeneratorsAPI(context, _currentValue);
}
}
void onCameraMove(context, CameraPosition position) {
_timer?.cancel(); // Cancel any previous timer
_timer = Timer(Duration(seconds: 1), () {
getLocationPermission(context);
});
}
void debounce(VoidCallback callback, Duration duration) {
_debounceTimer?.cancel();
_debounceTimer = Timer(duration, callback);
}
Future<void> LoadNearbyGeneratorsAPI(BuildContext context, radius) async {
if (_latlongs.isEmpty || _currentValue <= 0) {
print(
"Invalid parameters: latlongs=$_latlongs, currentValue=$_currentValue",
);
return;
}
try {
var provider = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.loadCrmNearbyGeneratorsAPI(
provider.empId,
provider.session,
_latlongs,
_currentValue,
_selectedItem,
);
if (data != null) {
if (data.sessionExists == 1) {
if (data.error == 0) {
_generatorslist = data.list!;
await updateMarkersFromApiResponse(context, data.list!);
_isLoading = false;
notifyListeners();
} else {}
} else {
// SharedpreferencesService().clearPreferences();
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => LoginScreen()),
// );
}
} else {
toast(context, "Something went wrong, Please try again.");
}
} on Exception catch (e) {
print("$e");
}
}
Future<void> updateMarkersFromApiResponse(
BuildContext context,
List<Nearbygenerators> generatorslist,
) async {
_markers = await createMarkersFromApiResponse(context, generatorslist);
_addresses.clear();
await Future.forEach(generatorslist, (store) async {
String address = await _getAddressFromLatLng(store.loc);
_addresses.add(address);
});
notifyListeners();
// for (int i = 0; i < _addresses.length; i++) {
// //print('List of Addresses:' "${addresses[i]}");
// // print('List of Addresses:' "${addresses[1]}" );
// }
}
Future<List<Marker>> createMarkersFromApiResponse(
BuildContext context,
List<Nearbygenerators> generatorslist,
) async {
List<Marker> markers = [];
// print("Hello Nutsby!");
ByteData data = await rootBundle.load("assets/images/dg_set.png");
Uint8List bytes = data.buffer.asUint8List();
await Future.forEach(generatorslist, (generator) async {
ui.Codec codec = await ui.instantiateImageCodec(
bytes,
targetWidth: 75,
targetHeight: 95,
);
ui.FrameInfo fi = await codec.getNextFrame();
Uint8List resizedBytes =
(await fi.image.toByteData(
format: ui.ImageByteFormat.png,
))!.buffer.asUint8List();
markers.add(
Marker(
markerId: MarkerId(generator.generatorId.toString()),
position: _parseLatLng(generator.loc),
icon: BitmapDescriptor.fromBytes(resizedBytes),
infoWindow: InfoWindow(
onTap: () {
print("INFO WINDOW TAP");
},
title: "Customer Name: ${generator.accName}",
snippet: "Product Name: ${generator.productName}",
),
zIndex: 100,
),
);
});
return markers;
}
LatLng _parseLatLng(String? location) {
if (location != null) {
List<String> parts = location.split(',');
if (parts.length == 2) {
double lat = double.tryParse(parts[0]) ?? 0.0;
double lng = double.tryParse(parts[1]) ?? 0.0;
return LatLng(lat, lng);
}
}
return const LatLng(0.0, 0.0);
}
Future<String> _getAddressFromLatLng(String? location) async {
if (location != null) {
List<String> parts = location.split(',');
if (parts.length == 2) {
double lat = double.tryParse(parts[0]) ?? 0.0;
double lng = double.tryParse(parts[1]) ?? 0.0;
List<geocoding.Placemark> placemarks = await geocoding
.placemarkFromCoordinates(lat, lng);
if (placemarks.isNotEmpty) {
final placemark = placemarks.first;
String address =
'${placemark.street ?? ''}, '
'${placemark.thoroughfare ?? ''} '
// '${placemark.subThoroughfare ?? ''}, '
// '${placemark.name ?? ''}, '
'${placemark.subLocality ?? ''}, '
'${placemark.locality ?? ''}, '
'${placemark.administrativeArea ?? ''}, '
'${placemark.subAdministrativeArea ?? ''} '
'${placemark.postalCode ?? ''}, '
'${placemark.country ?? ''}';
return address.trim();
}
}
}
return "Address not found";
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment