import 'dart:io'; import 'package:camera/camera.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:generp/Models/financeModels/paymentRequisitionDetailsResponse.dart'; import 'package:generp/Notifiers/HomeScreenNotifier.dart'; import 'package:generp/Utils/commonServices.dart'; import 'package:generp/services/api_calling.dart'; import 'package:image_picker/image_picker.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'approveRejectPaymentRequestResponse.dart'; class Requesitionlidtdetailsprovider extends ChangeNotifier { bool _showMoreDetails = false; final numberFormat = NumberFormat.decimalPattern(); TextEditingController requestedAmount = TextEditingController(); TextEditingController approvedAmountReadonly = TextEditingController(); TextEditingController proposedPaymentAccount = TextEditingController(); TextEditingController approvedAmount = TextEditingController(); TextEditingController accountName = TextEditingController(); TextEditingController branch = TextEditingController(); TextEditingController requestingPurpose = TextEditingController(); TextEditingController description = TextEditingController(); TextEditingController amount = TextEditingController(); TextEditingController paymentMode = TextEditingController(); TextEditingController bankUpiID = TextEditingController(); TextEditingController bankName = TextEditingController(); TextEditingController bankBranchName = TextEditingController(); TextEditingController bankAccountNumber = TextEditingController(); TextEditingController bankIfscCode = TextEditingController(); TextEditingController bankHolderName = TextEditingController(); TextEditingController paymentAccountSearchController = TextEditingController(); TextEditingController editPaymentRequestedAmountController = TextEditingController(); TextEditingController editPaymentRequestedEditableAmountController = TextEditingController(); bool _editPaymentProcessLoading = false; String? editableAmountError; String? proposedAmountError; PaymentDetails _paymentDetails = PaymentDetails(); RequestDetails _requestDetails = RequestDetails(); PaymentRequestDetails _paymentRequestDetails = PaymentRequestDetails(); PaymentAccounts? _selectedPaymentAccounts; List _paymentModes = []; List _paymentAccounts = []; var _selectedValue; var _selectedID; List _headings = []; List _subHeadings = []; String? FileError; var _image_picked = 0; final ImagePicker _picker = ImagePicker(); File? _image; File? _imageName; get image_picked => _image_picked; bool get showMoreDetails => _showMoreDetails; bool get editPaymentProcessLoading => _editPaymentProcessLoading; int get imagePicked => _image_picked; File? get imagePath => _imageName; File? get imageFilePath => _image; set editPaymentProcessLoading(bool value) { _editPaymentProcessLoading = value; notifyListeners(); } set imagePicked(int value) { _image_picked = value; notifyListeners(); } set imagePath(File? value) { _imageName = value; notifyListeners(); } set imageFilePath(File? value) { _image = value; notifyListeners(); } set showMoreDetails(bool value) { _showMoreDetails = value; notifyListeners(); } PaymentDetails get paymentsDetails => _paymentDetails; RequestDetails get requestsDetails => _requestDetails; List get paymentsAccounts => _paymentAccounts; List get paymentsModes => _paymentModes; PaymentRequestDetails get paymentsReqDetails => _paymentRequestDetails; PaymentAccounts? get selectedPaymentAccounts => _selectedPaymentAccounts; get selectedValue => _selectedValue; get selectedID => _selectedID; List get subHeadings => _subHeadings; set subHeadings(List value) { _subHeadings = value; notifyListeners(); } List get Headings => _headings; set selectedPaymentAccounts(PaymentAccounts? value) { _selectedPaymentAccounts = value; _selectedValue = value!.name!; _selectedID = value.id; selectpaymentAccountError = null; notifyListeners(); } set selectedValue(value) { _selectedValue = value; notifyListeners(); } set selectedID(value) { _selectedID = value; notifyListeners(); } imgFromCamera(context) async { // Capture a photo try { final XFile? galleryImage = await _picker.pickImage( source: ImageSource.camera, imageQuality: 50, ); debugPrint("added"); _image = File(galleryImage!.path); _imageName = File(galleryImage.name); _image_picked = 1; FileError = null; notifyListeners(); } catch (e) { debugPrint("mmmm: ${e.toString()}"); } } imgFromGallery(context) async { // Pick an image try { final XFile? galleryImage = await _picker.pickImage( source: ImageSource.gallery, ); final bytes = (await galleryImage?.readAsBytes())?.lengthInBytes; final kb = bytes! / 1024; final mb = kb / 1024; debugPrint("Jenny: bytes:$bytes, kb:$kb, mb: $mb"); _image = File(galleryImage!.path); _imageName = File(galleryImage.name); _image_picked = 1; FileError = null; notifyListeners(); // var file = FlutterImageCompress.compressWithFile(galleryImage!.path); } catch (e) { debugPrint("mmmm: ${e.toString()}"); } } Future paymentRequesitionDetails(context, paymentRequestId) async { try { var provider = Provider.of(context, listen: false); final data = await ApiCalling.paymentRequestionDetailsAPI( provider.empId, provider.session, paymentRequestId, ); if (data != null) { if (data.error == "0") { _headings = [ "Requested Account", "Proposed Account Name", "Branch", "Requesting Propose", "Payment Mode", "Created Employee", "Attachment", "Requested Date", "Note", "Level 1 Remarks", "Level 1 Approved By", "Level 2 Remarks", "Level 2 Approved By", "Approved Amount", "Created Date/Time", "Updated Date/Time", ]; _paymentDetails = data.paymentDetails ?? PaymentDetails( accountId: "-", accountName: "-", amount: "-", attachmentDirFilePath: "-", attachmentViewFileName: "-", bankAccountHolderName: "-", bankAccountNumber: "-", bankBranchName: "-", bankIfscCode: "-", bankName: "-", bankUpiId: "-", createdDatetime: "-", createdEmployeeId: "-", description: "-", id: "-", isExists: "-", mode: "-", paymentAccountId: "-", paymentAccountName: "-", paymentDate: "-", paymentEmployeeName: "-", paymentModeId: "-", paymentReferenceNumber: "-", paymentRemarks: "-", refId: "-", refType: "-", updatedDatetime: "-", ); _requestDetails = data.requestDetails ?? RequestDetails( updatedDatetime: "-", id: "-", description: "-", createdDatetime: "-", attachmentViewFileName: "-", attachmentDirFilePath: "-", amount: "-", accountName: "-", accountId: "-", branch: "-", createdEmployee: "-", date: "-", isProcessedPaymentRequest: "-", level1ApprovalRemarks: "-", level1Employee: "-", level2ApprovalRemarks: "-", level2Employee: "-", proposedAccount: "-", proposedAccountId: "-", requestedAmount: "-", requestingPurpose: "-", requestMode: "-", status: "-", transDis: "-", ); _subHeadings = [ _requestDetails.accountName ?? "-", _requestDetails.proposedAccount ?? "-", _requestDetails.branch ?? "-", _requestDetails.requestingPurpose ?? "-", _requestDetails.requestMode ?? "-", _requestDetails.createdEmployee ?? "-", _requestDetails.attachmentViewFileName ?? "-", _requestDetails.date ?? "-", _requestDetails.description ?? "-", _requestDetails.level1ApprovalRemarks ?? "-", _requestDetails.level1Employee ?? "-", _requestDetails.level2ApprovalRemarks ?? "-", _requestDetails.level2Employee ?? "-", _requestDetails.amount ?? "-", _requestDetails.createdDatetime ?? "-", _requestDetails.updatedDatetime ?? "-", ]; print("here 2121"); preValues(); notifyListeners(); } } } catch (e) {} } preValues() { print("here 212ssass1"); requestedAmount.text = _requestDetails.requestedAmount ?? "-"; proposedPaymentAccount.text = _requestDetails.proposedAccount ?? "-"; approvedAmountReadonly.text = _requestDetails.formattedAmount ?? "-"; approvedAmount.text = _requestDetails.amount ?? "-"; accountName.text = _requestDetails.accountName ?? "-"; branch.text = _requestDetails.branch ?? "-"; requestingPurpose.text = _requestDetails.requestingPurpose ?? "-"; description.text = _requestDetails.description ?? "-"; amount.text = _requestDetails.amount ?? "-"; paymentMode.text = _requestDetails.requestMode ?? "-"; bankUpiID.text = _requestDetails.bankUpiId ?? "-"; bankName.text = _requestDetails.bankName ?? "-"; bankBranchName.text = _requestDetails.bankBranchname ?? "-"; bankAccountNumber.text = _requestDetails.bankAccountNumber ?? "-"; bankIfscCode.text = _requestDetails.bankIfscCode ?? "-"; bankHolderName.text = _requestDetails.bankAccountHolderName ?? "-"; notifyListeners(); } Future approveRejectPaymentRequestAPIFunction( context, paymentRequestId, ) async { try { var provider = Provider.of(context, listen: false); final data = await ApiCalling.approveRejectPaymentRequestAPI( provider.empId, provider.session, paymentRequestId, ); if (data != null) { if (data.error == "0") { _paymentModes = data.paymentModes!; _paymentAccounts = data.paymentAccounts!; _paymentRequestDetails = data.paymentRequestDetails!; notifyListeners(); } } } catch (e) {} } String? remarksError; String? ApprovedAmountError; String? selectpaymentAccountError; bool _submitClicked = false; bool get submitClicked => _submitClicked; set submitClicked(bool value) { _submitClicked = value; notifyListeners(); } Future paymentrequisitionRejectSubmitAPIFunction( context, mode, paymentRequestId, approveRemarks, ) async { try { if (approveRemarks.toString().trim().isEmpty) { remarksError = "Please Enter Remarks"; notifyListeners(); // toast(context,"Enter Remarks"); return; } var provider = Provider.of(context, listen: false); final data = await ApiCalling.RejectPaymentRequestSubmitAPI( provider.empId, provider.session, mode, paymentRequestId, approveRemarks, ); if (data != null) { if (data.error == "0") { paymentRequesitionDetails(context, paymentRequestId); resetAll(); toast(context, data.message); Navigator.pop(context); } } } catch (e) {} } Future paymentrequisitionApproveSubmitAPIFunction( BuildContext context, String mode, String payment_request_id, String approved_amount, String approve_remarks, String proposed_payment_account_id, ) async { print("🎯 === PROVIDER METHOD STARTED ==="); try { print("🔍 Starting validation..."); if (!validateApproval(approved_amount, approve_remarks, proposed_payment_account_id)) { print("❌ VALIDATION FAILED - Stopping execution"); return; } print("✅ Validation passed"); print("👤 Getting home provider..."); var homeProvider = Provider.of(context, listen: false); print("👤 Emp ID: ${homeProvider.empId}, Session: ${homeProvider.session}"); print("🌐 Calling API..."); final data = await ApiCalling.ApprovePaymentRequestSubmitAPI( homeProvider.empId, homeProvider.session, mode, payment_request_id, approved_amount, approve_remarks, proposed_payment_account_id, ); print("🌐 API call completed"); if (data != null) { print("📡 API Response: error=${data.error}, message=${data.message}"); if (data.error == "0") { print("✅ API SUCCESS - Processing..."); // Check if context is still valid before UI operations if (context.mounted) { print("🎯 Context mounted - performing UI operations"); paymentRequesitionDetails(context, payment_request_id); resetAll(); toast(context, data.message); Navigator.pop(context, true); print("✅ UI operations completed"); } else { print("⚠️ Context not mounted - skipping UI operations"); } notifyListeners(); print("✅ Notify listeners called"); } else { print("❌ API returned error: ${data.message}"); if (context.mounted) { toast(context, data.message ?? "Submission failed"); } } } else { print("❌ NULL response from API"); if (context.mounted) { toast(context, "No response from server"); } } } catch (e, s) { print("💥 EXCEPTION in provider method: $e"); print("📋 Stack trace: $s"); // Show error to user if (context.mounted) { toast(context, "Error: ${e.toString()}"); } } print("🎯 === PROVIDER METHOD COMPLETED ==="); } editPrevalues() { editPaymentRequestedAmountController.text = _requestDetails.requestedAmount ?? "-"; editPaymentRequestedEditableAmountController.text = _requestDetails.requestedAmount ?? "-"; notifyListeners(); } onChangeEditableAmount(value, context) { var provider = Provider.of(context, listen: false); if (provider.empId == "5" || provider.empId == "130" || provider.empId == "131" || provider.empId == "6") { editableAmountError = ""; } else { if (numberFormat.parse(editPaymentRequestedAmountController.text) < numberFormat.parse( editPaymentRequestedEditableAmountController.text, )) { editableAmountError = "Approved Amount should not be greater than amount"; } else { editableAmountError = null; } } _editPaymentProcessLoading = false; notifyListeners(); } bool validateEditprocessPayment(context) { bool isValid = true; editableAmountError = null; var provider = Provider.of(context, listen: false); if (editPaymentRequestedEditableAmountController.text.isNotEmpty) { if (provider.empId == "5" || provider.empId == "130" || provider.empId == "131" || provider.empId == "6") { editableAmountError = null; } else { if (numberFormat.parse(editPaymentRequestedAmountController.text) < numberFormat.parse( editPaymentRequestedEditableAmountController.text, )) { editableAmountError = "Approved Amount should not be greater than amount"; isValid = false; } else { editableAmountError = null; } } } _editPaymentProcessLoading = false; notifyListeners(); return isValid; } Future editProcessedPaymentAmountAPIFunction( context, paymentRequestId, approvalAmount, ) async { try { _editPaymentProcessLoading = true; notifyListeners(); if (!validateEditprocessPayment(context)) { return; } var provider = Provider.of(context, listen: false); final data = await ApiCalling.editProcessedRequestAmountAPI( provider.empId, provider.session, paymentRequestId, approvalAmount, ); if (data != null) { if (data.error == "0") { _editPaymentProcessLoading = false; paymentRequesitionDetails(context, paymentRequestId); resetAll(); toast(context, data.message); Navigator.pop(context, true); notifyListeners(); } else { _editPaymentProcessLoading = false; notifyListeners(); } } else { _editPaymentProcessLoading = false; notifyListeners(); } } catch (e) { _editPaymentProcessLoading = false; notifyListeners(); } } bool validateApproval( String approvedAmount, // Add type for clarity String approveRemarks, // Add type for clarity String proposedPaymentAccountId, // Add type for clarity ) { print("🔍 === VALIDATION STARTED ==="); print(" Approved Amount: '$approvedAmount'"); print(" Requested Amount: '${requestedAmount.text}'"); print(" Remarks: '$approveRemarks'"); print(" Payment Account ID: '$proposedPaymentAccountId'"); print(" Selected ID: '$_selectedID'"); remarksError = null; ApprovedAmountError = null; selectpaymentAccountError = null; bool isValid = true; // Fix 1: Use the String parameter directly (no .text) if (approvedAmount.trim().isEmpty) { ApprovedAmountError = "Enter Amount"; isValid = false; print("❌ Approved amount is empty"); } // Fix 2: Use the String parameter directly (no .text) if (approveRemarks.trim().isEmpty) { remarksError = "Please Enter Remarks"; isValid = false; print("❌ Remarks are empty"); } // Fix 3: Parse the String parameters, not .text if (approvedAmount.trim().isNotEmpty && requestedAmount.text.trim().isNotEmpty) { try { final numberFormat = NumberFormat.decimalPattern(); double approved = numberFormat.parse(approvedAmount.trim()).toDouble(); double requested = numberFormat.parse(requestedAmount.text.trim()).toDouble(); print("💰 Amount Comparison: Approved: $approved, Requested: $requested"); if (approved > requested) { ApprovedAmountError = "Approved Amount should not be greater than requested amount"; isValid = false; print("❌ Approved amount exceeds requested amount"); } } catch (e) { print("💥 Error parsing amounts: $e"); ApprovedAmountError = "Invalid amount format"; isValid = false; } } // Fix 4: Use the parameter OR check both for consistency if (proposedPaymentAccountId.isEmpty && _selectedID.isEmpty) { selectpaymentAccountError = "Please select an account"; isValid = false; print("❌ No payment account selected"); } else if (proposedPaymentAccountId.isNotEmpty && _selectedID.isEmpty) { // If parameter has value but _selectedID doesn't, sync them _selectedID = proposedPaymentAccountId; print("🔄 Synced selected ID from parameter: $_selectedID"); } _submitClicked = false; notifyListeners(); print("🔍 === VALIDATION RESULT: $isValid ==="); return isValid; } checkApprovalDropDown() {} Future paymentrequisitionProcessSubmitAPIFunction( context, mode, referenceNum, paymentAmount, paymentRequestId, paymentAccountId, processingRemarks, attachment, ) async { try { var provider = Provider.of(context, listen: false); final data = await ApiCalling.processApproveRejectPaymentRequestSubmitAPI( provider.empId, provider.session, mode, referenceNum, paymentAmount, paymentRequestId, paymentAccountId, processingRemarks, attachment, ); if (data != null) { if (data.error == "0") { paymentRequesitionDetails(context, paymentRequestId); resetAll(); toast(context, data.message); Navigator.pop(context); } } } catch (e) {} } resetAll() { checkDropDownReset(); editPaymentRequestedAmountController.clear(); editPaymentRequestedEditableAmountController.clear(); _editPaymentProcessLoading = false; editableAmountError = null; requestedAmount.clear(); proposedPaymentAccount.clear(); approvedAmountReadonly.clear(); approvedAmount.clear(); accountName.clear(); branch.clear(); requestingPurpose.clear(); description.clear(); amount.clear(); paymentMode.clear(); bankUpiID.clear(); bankName.clear(); bankBranchName.clear(); bankAccountNumber.clear(); bankIfscCode.clear(); bankHolderName.clear(); paymentAccountSearchController.clear(); _selectedPaymentAccounts = null; _selectedValue = ""; _selectedID = null; proposedAmountError = null; remarksError = null; ApprovedAmountError = null; selectpaymentAccountError = null; notifyListeners(); } onChangeApprov(value) { final numberFormat = NumberFormat.decimalPattern(); if (numberFormat.parse(approvedAmount.text) > numberFormat.parse(requestedAmount.text)) { ApprovedAmountError = "Approved Amount should not be greater than requested amount"; } else { ApprovedAmountError = null; } notifyListeners(); } void checkDropDownReset() { if (!_paymentAccounts.contains(_selectedPaymentAccounts) && _selectedPaymentAccounts != null) { _selectedPaymentAccounts = null; _selectedID = null; _selectedValue = ""; } notifyListeners(); } }