Beneficiary Localization Chamges

This commit is contained in:
2025-08-14 16:15:35 +05:30
parent f48bfabb4a
commit e2a809d363
12 changed files with 324 additions and 39 deletions

View File

@@ -0,0 +1,31 @@
import 'package:dio/dio.dart';
import 'package:kmobile/data/models/imps_response.dart';
import 'package:kmobile/data/models/imps_transaction.dart';
class RtgsService {
final Dio _dio;
RtgsService(this._dio);
Future<ImpsResponse> processImpsTransaction(
ImpsTransaction transaction) async {
try {
await Future.delayed(const Duration(seconds: 3));
final response = await _dio.post(
'/api/payment/rtgs',
data: transaction.toJson(),
);
if (response.statusCode == 200) {
return ImpsResponse.fromJson(response.data);
} else {
throw Exception(
'RTGS transaction failed with status code: ${response.statusCode}');
}
} on DioException {
rethrow ;
} catch (e) {
throw Exception('An unexpected error occurred: ${e.toString()}');
}
}
}

View File

@@ -0,0 +1,16 @@
class ImpsResponse {
final String message;
final String utr;
ImpsResponse({
required this.message,
required this.utr,
});
factory ImpsResponse.fromJson(Map<String, dynamic> json) {
return ImpsResponse(
message: json['message'] ?? '',
utr: json['utr'] ?? '',
);
}
}

View File

@@ -0,0 +1,32 @@
class ImpsTransaction {
final String fromAccount;
final String toAccount;
final String amount;
final String ifscCode;
final String? remitterName;
final String beneficiaryName;
final String tpin;
ImpsTransaction({
required this.fromAccount,
required this.toAccount,
required this.amount,
required this.ifscCode,
this.remitterName,
required this.beneficiaryName,
required this.tpin,
});
Map<String, dynamic> toJson() {
return {
'stFromAccDetails': fromAccount,
'stBenAccNo': toAccount,
'stTransferAmount': amount,
'stBenIFSC': ifscCode,
//'remitterName': remitterName,
'stBeneName': beneficiaryName,
'stRemarks': "Check",
'tpin': tpin,
};
}
}

View File

@@ -15,3 +15,4 @@ class ThemeState extends Equatable {
@override @override
List<Object?> get props => [themeType]; List<Object?> get props => [themeType];
} }

View File

@@ -1,8 +1,6 @@
// ignore_for_file: avoid_print // ignore_for_file: avoid_print
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:kmobile/api/services/neft_service.dart'; import 'package:kmobile/api/services/neft_service.dart';
@@ -70,13 +68,13 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
showDialog( showDialog(
context: context, context: context,
builder: (ctx) => AlertDialog( builder: (ctx) => AlertDialog(
title: const Text('Invalid Amount for RTGS'), title: Text(AppLocalizations.of(context).invalidRtgs),
content: const Text( content: Text(
'RTGS transactions require a minimum amount of 200,000. Please enter a higher amount or select NEFT as the transaction mode.'), AppLocalizations.of(context).invalidRtgsPopUp),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.of(ctx).pop(), onPressed: () => Navigator.of(ctx).pop(),
child: const Text('OK'), child: Text(AppLocalizations.of(context).ok),
), ),
], ],
), ),
@@ -129,9 +127,9 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
final error = jsonDecode(e.response.toString())['error']; final error = jsonDecode(e.response.toString())['error'];
var errorMessage = var errorMessage =
{ {
"INCORRECT_TPIN" : "Please Enter the correct TPIN", "INCORRECT_TPIN" : AppLocalizations.of(context).correctTpin,
"INSUFFICIENT_FUNDS": "Your account does not have sufficient balance" "INSUFFICIENT_FUNDS": AppLocalizations.of(context).insufficientFund
}[error] ?? "Something Went Wrong"; }[error] ?? AppLocalizations.of(context).somethingWentWrong;
final paymentResponse = PaymentResponse( final paymentResponse = PaymentResponse(
isSuccess: false, isSuccess: false,
@@ -143,11 +141,70 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
print(e.toString()); print(e.toString());
final paymentResponse = PaymentResponse( final paymentResponse = PaymentResponse(
isSuccess: false, isSuccess: false,
errorMessage: "Something went Wrong", errorMessage: AppLocalizations.of(context).somethingWentWrong,
); );
completer.complete(paymentResponse); completer.complete(paymentResponse);
} }
} else { }
// else if (_selectedMode == TransactionMode.imps){
// final rtgsTx = RtgsTransaction(
// fromAccount: widget.debitAccountNo,
// toAccount: widget.creditBeneficiary.accountNo,
// amount: _amountController.text,
// ifscCode: widget.creditBeneficiary.ifscCode,
// remitterName: widget.remitterName,
// beneficiaryName: widget.creditBeneficiary.name,
// tpin: tpin,
// );
// final rtgsService = getIt<RtgsService>();
// final completer = Completer<PaymentResponse>();
// Navigator.of(pinScreenContext).pushReplacement(
// MaterialPageRoute(
// builder: (_) => PaymentAnimationScreen(
// paymentResponse: completer.future),
// ),
// );
// try {
// final rtgsResponse =
// await rtgsService.processRtgsTransaction(rtgsTx);
// final paymentResponse = PaymentResponse(
// isSuccess: rtgsResponse.message.toUpperCase() == 'SUCCESS',
// date: DateTime.now(),
// creditedAccount: rtgsTx.toAccount,
// amount: rtgsTx.amount,
// currency: 'INR',
// utr: rtgsResponse.utr,
// );
// completer.complete(paymentResponse);
// } on DioException catch(e) {
// print('dio exception');
// print(e.toString());
// final error = jsonDecode(e.response.toString())['error'];
// var errorMessage =
// {
// "INCORRECT_TPIN" : "Please Enter the correct TPIN",
// "INSUFFICIENT_FUNDS": "Your account does not have sufficient balance"
// }[error] ?? "Something Went Wrong";
// final paymentResponse = PaymentResponse(
// isSuccess: false,
// errorMessage: errorMessage,
// );
// completer.complete(paymentResponse);
// } catch (e) {
// print('generic exception');
// print(e.toString());
// final paymentResponse = PaymentResponse(
// isSuccess: false,
// errorMessage: "Something went Wrong",
// );
// completer.complete(paymentResponse);
// }
// }
else {
final rtgsTx = RtgsTransaction( final rtgsTx = RtgsTransaction(
fromAccount: widget.debitAccountNo, fromAccount: widget.debitAccountNo,
toAccount: widget.creditBeneficiary.accountNo, toAccount: widget.creditBeneficiary.accountNo,
@@ -186,9 +243,10 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
final error = jsonDecode(e.response.toString())['error']; final error = jsonDecode(e.response.toString())['error'];
var errorMessage = var errorMessage =
{ {
"INCORRECT_TPIN" : "Please Enter the correct TPIN", "INCORRECT_TPIN" : AppLocalizations.of(context).correctTpin,
"INSUFFICIENT_FUNDS": "Your account does not have sufficient balance" "INSUFFICIENT_FUNDS": AppLocalizations.of(context).insufficientFund
}[error] ?? "Something Went Wrong"; // ignore: use_build_context_synchronously
}[error] ?? AppLocalizations.of(context).somethingWentWrong;
final paymentResponse = PaymentResponse( final paymentResponse = PaymentResponse(
isSuccess: false, isSuccess: false,
@@ -200,7 +258,7 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
print(e.toString()); print(e.toString());
final paymentResponse = PaymentResponse( final paymentResponse = PaymentResponse(
isSuccess: false, isSuccess: false,
errorMessage: "Something went Wrong", errorMessage: AppLocalizations.of(context).somethingWentWrong,
); );
completer.complete(paymentResponse); completer.complete(paymentResponse);
} }
@@ -248,7 +306,7 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
// Credit Account (Beneficiary) // Credit Account (Beneficiary)
Text( Text(
"Credit To", AppLocalizations.of(context).creditedTo,
style: Theme.of(context).textTheme.titleSmall, style: Theme.of(context).textTheme.titleSmall,
), ),
Card( Card(
@@ -264,7 +322,7 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
// Transaction Mode Selection // Transaction Mode Selection
Text( Text(
"Select Transaction Mode", AppLocalizations.of(context).selectTransactionType,
style: Theme.of(context).textTheme.titleMedium, style: Theme.of(context).textTheme.titleMedium,
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
@@ -292,15 +350,19 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
selectedBorderColor: Colors.transparent, selectedBorderColor: Colors.transparent,
splashColor: Theme.of(context).primaryColor.withOpacity(0.1), splashColor: Theme.of(context).primaryColor.withOpacity(0.1),
highlightColor: Theme.of(context).primaryColor.withOpacity(0.05), highlightColor: Theme.of(context).primaryColor.withOpacity(0.05),
children: const [ children: [
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
child: Text('NEFT'), child: Text(AppLocalizations.of(context).neft),
), ),
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
child: Text('RTGS'), child: Text(AppLocalizations.of(context).rtgs),
), ),
// Padding(
// padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
// child: Text(AppLocalizations.of(context).imps),
// ),
], ],
), ),
), ),
@@ -336,7 +398,7 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16), padding: const EdgeInsets.symmetric(vertical: 16),
), ),
child: const Text("Proceed"), child: Text(AppLocalizations.of(context).proceed),
), ),
), ),
], ],

View File

@@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/services.dart';
import 'package:kmobile/api/services/neft_service.dart'; import 'package:kmobile/api/services/neft_service.dart';
import 'package:kmobile/api/services/rtgs_service.dart'; import 'package:kmobile/api/services/rtgs_service.dart';
import 'package:kmobile/data/models/neft_transaction.dart'; import 'package:kmobile/data/models/neft_transaction.dart';
@@ -83,7 +84,6 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
final String accountNo = accountNumberController.text.trim(); final String accountNo = accountNumberController.text.trim();
final String ifsc = ifscController.text.trim(); final String ifsc = ifscController.text.trim();
// TODO: Replace with actual remitter name
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final String remitter = "Unknown"; final String remitter = "Unknown";
@@ -141,8 +141,8 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
if (_formKey.currentState!.validate()) { if (_formKey.currentState!.validate()) {
if (!_isBeneficiaryValidated) { if (!_isBeneficiaryValidated) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( SnackBar(
content: Text('Please validate beneficiary details first.')), content: Text(AppLocalizations.of(context).plsValidateBeneficiary)),
); );
return; return;
} }
@@ -155,13 +155,12 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
showDialog( showDialog(
context: context, context: context,
builder: (ctx) => AlertDialog( builder: (ctx) => AlertDialog(
title: const Text('Invalid Amount for RTGS'), title: Text(AppLocalizations.of(context).invalidRtgs),
content: const Text( content: Text(AppLocalizations.of(context).invalidRtgsPopUp),
'RTGS transactions require a minimum amount of 200,000. Please enter a higher amount or select NEFT as the transaction mode.'),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.of(ctx).pop(), onPressed: () => Navigator.of(ctx).pop(),
child: const Text('OK'), child: Text(AppLocalizations.of(context).ok),
), ),
], ],
), ),
@@ -346,7 +345,7 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
return AppLocalizations.of(context).accountNumberRequired; return AppLocalizations.of(context).accountNumberRequired;
} else if (value.length < 7 || value.length > 20) { } else if (value.length < 7 || value.length > 20) {
return 'Account number must be between 7 and 20 digits'; return AppLocalizations.of(context).accno7to20;
} }
return null; return null;
}, },
@@ -385,6 +384,10 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
children: [ children: [
Expanded( Expanded(
child: TextFormField( child: TextFormField(
maxLength: 11,
inputFormatters: [
LengthLimitingTextInputFormatter(11),
],
decoration: InputDecoration( decoration: InputDecoration(
labelText: AppLocalizations.of(context).ifscCode, labelText: AppLocalizations.of(context).ifscCode,
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
@@ -520,7 +523,7 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
} else { } else {
setState(() { setState(() {
_validationError = _validationError =
'Account numbers do not match.'; AppLocalizations.of(context).accountMismatch;
}); });
} }
}, },
@@ -531,7 +534,7 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
child: CircularProgressIndicator( child: CircularProgressIndicator(
strokeWidth: 2), strokeWidth: 2),
) )
: const Text('Validate Beneficiary'), : Text(AppLocalizations.of(context).validateBeneficiary),
), ),
), ),
), ),

View File

@@ -212,7 +212,7 @@ class _QuickPayWithinBankScreen extends State<QuickPayWithinBankScreen> {
} else { } else {
setState(() { setState(() {
_validationError = _validationError =
'Please enter a valid and matching account number.'; AppLocalizations.of(context).accountMismatch;
}); });
} }
}, },
@@ -222,7 +222,7 @@ class _QuickPayWithinBankScreen extends State<QuickPayWithinBankScreen> {
height: 20, height: 20,
child: CircularProgressIndicator(strokeWidth: 2), child: CircularProgressIndicator(strokeWidth: 2),
) )
: const Text('Validate Beneficiary'), : Text(AppLocalizations.of(context).validateBeneficiary),
), ),
), ),
), ),
@@ -234,7 +234,7 @@ class _QuickPayWithinBankScreen extends State<QuickPayWithinBankScreen> {
const Icon(Icons.check_circle, color: Colors.green), const Icon(Icons.check_circle, color: Colors.green),
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
'Beneficiary: $_beneficiaryName', '${AppLocalizations.of(context).beneficiaryName}: $_beneficiaryName',
style: const TextStyle( style: const TextStyle(
color: Colors.green, fontWeight: FontWeight.bold), color: Colors.green, fontWeight: FontWeight.bold),
), ),
@@ -338,7 +338,7 @@ class _QuickPayWithinBankScreen extends State<QuickPayWithinBankScreen> {
if (!_isBeneficiaryValidated) { if (!_isBeneficiaryValidated) {
setState(() { setState(() {
_validationError = _validationError =
'Please validate beneficiary before proceeding.'; AppLocalizations.of(context).validateBeneficiaryproceeding;
}); });
return; return;
} }

View File

@@ -236,6 +236,16 @@
"transactionType": "Transaction Type", "transactionType": "Transaction Type",
"transferType": "Transfer Type", "transferType": "Transfer Type",
"utrNo": "UTR No.", "utrNo": "UTR No.",
"beneficiaryAccountNo": "Beneficiary Account No." "beneficiaryAccountNo": "Beneficiary Account No.",
"invalidRtgs": "Invalid Amount for RTGS",
"invalidRtgsPopUp": "RTGS transactions require a minimum amount of 200,000. Please enter a higher amount or select NEFT as the transaction mode.",
"correctTpin": "Please Enter the correct TPIN",
"insufficientFund": "Your account does not have sufficient balance",
"creditedTo": "Credited To",
"selectTransactionType": "Select transaction Type",
"proceed": "Proceed",
"plsValidateBeneficiary": "Please validate beneficiary details first",
"accno7to20": "Account number must be between 7 and 20 digits",
"validateBeneficiaryproceeding": "Please validate beneficiary before proceeding"
} }

View File

@@ -236,5 +236,15 @@
"transactionType": "लेनदेन प्रकार", "transactionType": "लेनदेन प्रकार",
"transferType": "स्थानांतरण प्रकार", "transferType": "स्थानांतरण प्रकार",
"utrNo": "यूटीआर नंबर", "utrNo": "यूटीआर नंबर",
"beneficiaryAccountNo": "लाभार्थी खाता संख्या" "beneficiaryAccountNo": "लाभार्थी खाता संख्या",
"invalidRtgs": "RTGS के लिए अमान्य राशि",
"invalidRtgsPopUp": "RTGS लेनदेन के लिए न्यूनतम 2,00,000 रुपये की राशि की आवश्यकता होती है। कृपया अधिक राशि दर्ज करें या लेनदेन मोड के रूप में NEFT चुनें",
"correctTpin": "कृपया सही टी-पिन दर्ज करें",
"insufficientFund": "आपके खाते में पर्याप्त शेष राशि नहीं है",
"creditedTo": "को श्रेय दिया गया",
"selectTransactionType": "लेन-देन का प्रकार चुनें",
"proceed": "आगे बढ़ना",
"plsValidateBeneficiary": "कृपया पहले लाभार्थी विवरण सत्यापित करें",
"accno7to20": "खाता संख्या सात से बीस अंकों के बीच होनी चाहिए",
"validateBeneficiaryproceeding": "कृपया आगे बढ़ने से पहले लाभार्थी को पट्टे पर मान्य करें"
} }

View File

@@ -1444,6 +1444,66 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'Beneficiary Account No.'** /// **'Beneficiary Account No.'**
String get beneficiaryAccountNo; String get beneficiaryAccountNo;
/// No description provided for @invalidRtgs.
///
/// In en, this message translates to:
/// **'Invalid Amount for RTGS'**
String get invalidRtgs;
/// No description provided for @invalidRtgsPopUp.
///
/// In en, this message translates to:
/// **'RTGS transactions require a minimum amount of 200,000. Please enter a higher amount or select NEFT as the transaction mode.'**
String get invalidRtgsPopUp;
/// No description provided for @correctTpin.
///
/// In en, this message translates to:
/// **'Please Enter the correct TPIN'**
String get correctTpin;
/// No description provided for @insufficientFund.
///
/// In en, this message translates to:
/// **'Your account does not have sufficient balance'**
String get insufficientFund;
/// No description provided for @creditedTo.
///
/// In en, this message translates to:
/// **'Credited To'**
String get creditedTo;
/// No description provided for @selectTransactionType.
///
/// In en, this message translates to:
/// **'Select transaction Type'**
String get selectTransactionType;
/// No description provided for @proceed.
///
/// In en, this message translates to:
/// **'Proceed'**
String get proceed;
/// No description provided for @plsValidateBeneficiary.
///
/// In en, this message translates to:
/// **'Please validate beneficiary details first'**
String get plsValidateBeneficiary;
/// No description provided for @accno7to20.
///
/// In en, this message translates to:
/// **'Account number must be between 7 and 20 digits'**
String get accno7to20;
/// No description provided for @validateBeneficiaryproceeding.
///
/// In en, this message translates to:
/// **'Please validate beneficiary before proceeding'**
String get validateBeneficiaryproceeding;
} }
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> { class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {

View File

@@ -682,4 +682,34 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get beneficiaryAccountNo => 'Beneficiary Account No.'; String get beneficiaryAccountNo => 'Beneficiary Account No.';
@override
String get invalidRtgs => 'Invalid Amount for RTGS';
@override
String get invalidRtgsPopUp => 'RTGS transactions require a minimum amount of 200,000. Please enter a higher amount or select NEFT as the transaction mode.';
@override
String get correctTpin => 'Please Enter the correct TPIN';
@override
String get insufficientFund => 'Your account does not have sufficient balance';
@override
String get creditedTo => 'Credited To';
@override
String get selectTransactionType => 'Select transaction Type';
@override
String get proceed => 'Proceed';
@override
String get plsValidateBeneficiary => 'Please validate beneficiary details first';
@override
String get accno7to20 => 'Account number must be between 7 and 20 digits';
@override
String get validateBeneficiaryproceeding => 'Please validate beneficiary before proceeding';
} }

View File

@@ -682,4 +682,34 @@ class AppLocalizationsHi extends AppLocalizations {
@override @override
String get beneficiaryAccountNo => 'लाभार्थी खाता संख्या'; String get beneficiaryAccountNo => 'लाभार्थी खाता संख्या';
@override
String get invalidRtgs => 'RTGS के लिए अमान्य राशि';
@override
String get invalidRtgsPopUp => 'RTGS लेनदेन के लिए न्यूनतम 2,00,000 रुपये की राशि की आवश्यकता होती है। कृपया अधिक राशि दर्ज करें या लेनदेन मोड के रूप में NEFT चुनें';
@override
String get correctTpin => 'कृपया सही टी-पिन दर्ज करें';
@override
String get insufficientFund => 'आपके खाते में पर्याप्त शेष राशि नहीं है';
@override
String get creditedTo => 'को श्रेय दिया गया';
@override
String get selectTransactionType => 'लेन-देन का प्रकार चुनें';
@override
String get proceed => 'आगे बढ़ना';
@override
String get plsValidateBeneficiary => 'कृपया पहले लाभार्थी विवरण सत्यापित करें';
@override
String get accno7to20 => 'खाता संख्या सात से बीस अंकों के बीच होनी चाहिए';
@override
String get validateBeneficiaryproceeding => 'कृपया आगे बढ़ने से पहले लाभार्थी को पट्टे पर मान्य करें';
} }