From e2a809d36342995575b80e47dfe85f5bfe5e1368 Mon Sep 17 00:00:00 2001 From: Nilanjan Chakrabarti Date: Thu, 14 Aug 2025 16:15:35 +0530 Subject: [PATCH] Beneficiary Localization Chamges --- lib/api/services/imps_service.dart | 31 +++++ lib/data/models/imps_response.dart | 16 +++ lib/data/models/imps_transaction.dart | 32 ++++++ .../auth/controllers/theme_state.dart | 1 + .../screens/fund_transfer_amount_screen.dart | 108 ++++++++++++++---- .../quick_pay_outside_bank_screen.dart | 23 ++-- .../screens/quick_pay_within_bank_screen.dart | 8 +- lib/l10n/app_en.arb | 12 +- lib/l10n/app_hi.arb | 12 +- lib/l10n/app_localizations.dart | 60 ++++++++++ lib/l10n/app_localizations_en.dart | 30 +++++ lib/l10n/app_localizations_hi.dart | 30 +++++ 12 files changed, 324 insertions(+), 39 deletions(-) create mode 100644 lib/api/services/imps_service.dart create mode 100644 lib/data/models/imps_response.dart create mode 100644 lib/data/models/imps_transaction.dart diff --git a/lib/api/services/imps_service.dart b/lib/api/services/imps_service.dart new file mode 100644 index 0000000..94239c3 --- /dev/null +++ b/lib/api/services/imps_service.dart @@ -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 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()}'); + } + } +} diff --git a/lib/data/models/imps_response.dart b/lib/data/models/imps_response.dart new file mode 100644 index 0000000..452fc77 --- /dev/null +++ b/lib/data/models/imps_response.dart @@ -0,0 +1,16 @@ +class ImpsResponse { + final String message; + final String utr; + + ImpsResponse({ + required this.message, + required this.utr, + }); + + factory ImpsResponse.fromJson(Map json) { + return ImpsResponse( + message: json['message'] ?? '', + utr: json['utr'] ?? '', + ); + } +} diff --git a/lib/data/models/imps_transaction.dart b/lib/data/models/imps_transaction.dart new file mode 100644 index 0000000..76e64c7 --- /dev/null +++ b/lib/data/models/imps_transaction.dart @@ -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 toJson() { + return { + 'stFromAccDetails': fromAccount, + 'stBenAccNo': toAccount, + 'stTransferAmount': amount, + 'stBenIFSC': ifscCode, + //'remitterName': remitterName, + 'stBeneName': beneficiaryName, + 'stRemarks': "Check", + 'tpin': tpin, + }; + } +} diff --git a/lib/features/auth/controllers/theme_state.dart b/lib/features/auth/controllers/theme_state.dart index ef57938..32248f9 100644 --- a/lib/features/auth/controllers/theme_state.dart +++ b/lib/features/auth/controllers/theme_state.dart @@ -15,3 +15,4 @@ class ThemeState extends Equatable { @override List get props => [themeType]; } + diff --git a/lib/features/fund_transfer/screens/fund_transfer_amount_screen.dart b/lib/features/fund_transfer/screens/fund_transfer_amount_screen.dart index b1e7fb4..da5cea1 100644 --- a/lib/features/fund_transfer/screens/fund_transfer_amount_screen.dart +++ b/lib/features/fund_transfer/screens/fund_transfer_amount_screen.dart @@ -1,8 +1,6 @@ // ignore_for_file: avoid_print - import 'dart:async'; import 'dart:convert'; - import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:kmobile/api/services/neft_service.dart'; @@ -70,13 +68,13 @@ class _FundTransferAmountScreenState extends State { showDialog( context: context, builder: (ctx) => AlertDialog( - title: const Text('Invalid Amount for RTGS'), - content: const Text( - 'RTGS transactions require a minimum amount of 200,000. Please enter a higher amount or select NEFT as the transaction mode.'), + title: Text(AppLocalizations.of(context).invalidRtgs), + content: Text( + AppLocalizations.of(context).invalidRtgsPopUp), actions: [ TextButton( onPressed: () => Navigator.of(ctx).pop(), - child: const Text('OK'), + child: Text(AppLocalizations.of(context).ok), ), ], ), @@ -129,9 +127,9 @@ class _FundTransferAmountScreenState extends State { 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"; + "INCORRECT_TPIN" : AppLocalizations.of(context).correctTpin, + "INSUFFICIENT_FUNDS": AppLocalizations.of(context).insufficientFund + }[error] ?? AppLocalizations.of(context).somethingWentWrong; final paymentResponse = PaymentResponse( isSuccess: false, @@ -143,11 +141,70 @@ class _FundTransferAmountScreenState extends State { print(e.toString()); final paymentResponse = PaymentResponse( isSuccess: false, - errorMessage: "Something went Wrong", + errorMessage: AppLocalizations.of(context).somethingWentWrong, ); 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(); + // final completer = Completer(); + + // 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( fromAccount: widget.debitAccountNo, toAccount: widget.creditBeneficiary.accountNo, @@ -186,9 +243,10 @@ class _FundTransferAmountScreenState extends State { 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"; + "INCORRECT_TPIN" : AppLocalizations.of(context).correctTpin, + "INSUFFICIENT_FUNDS": AppLocalizations.of(context).insufficientFund + // ignore: use_build_context_synchronously + }[error] ?? AppLocalizations.of(context).somethingWentWrong; final paymentResponse = PaymentResponse( isSuccess: false, @@ -200,7 +258,7 @@ class _FundTransferAmountScreenState extends State { print(e.toString()); final paymentResponse = PaymentResponse( isSuccess: false, - errorMessage: "Something went Wrong", + errorMessage: AppLocalizations.of(context).somethingWentWrong, ); completer.complete(paymentResponse); } @@ -248,7 +306,7 @@ class _FundTransferAmountScreenState extends State { // Credit Account (Beneficiary) Text( - "Credit To", + AppLocalizations.of(context).creditedTo, style: Theme.of(context).textTheme.titleSmall, ), Card( @@ -264,7 +322,7 @@ class _FundTransferAmountScreenState extends State { // Transaction Mode Selection Text( - "Select Transaction Mode", + AppLocalizations.of(context).selectTransactionType, style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 12), @@ -292,15 +350,19 @@ class _FundTransferAmountScreenState extends State { selectedBorderColor: Colors.transparent, splashColor: Theme.of(context).primaryColor.withOpacity(0.1), highlightColor: Theme.of(context).primaryColor.withOpacity(0.05), - children: const [ + children: [ Padding( - padding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), - child: Text('NEFT'), + padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), + child: Text(AppLocalizations.of(context).neft), ), Padding( - padding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), - child: Text('RTGS'), + padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), + 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 { style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), ), - child: const Text("Proceed"), + child: Text(AppLocalizations.of(context).proceed), ), ), ], diff --git a/lib/features/quick_pay/screens/quick_pay_outside_bank_screen.dart b/lib/features/quick_pay/screens/quick_pay_outside_bank_screen.dart index b938c2c..79daeef 100644 --- a/lib/features/quick_pay/screens/quick_pay_outside_bank_screen.dart +++ b/lib/features/quick_pay/screens/quick_pay_outside_bank_screen.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'package:flutter/services.dart'; import 'package:kmobile/api/services/neft_service.dart'; import 'package:kmobile/api/services/rtgs_service.dart'; import 'package:kmobile/data/models/neft_transaction.dart'; @@ -83,7 +84,6 @@ class _QuickPayOutsideBankScreen extends State { final String accountNo = accountNumberController.text.trim(); final String ifsc = ifscController.text.trim(); - // TODO: Replace with actual remitter name // ignore: prefer_const_declarations final String remitter = "Unknown"; @@ -141,8 +141,8 @@ class _QuickPayOutsideBankScreen extends State { if (_formKey.currentState!.validate()) { if (!_isBeneficiaryValidated) { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Please validate beneficiary details first.')), + SnackBar( + content: Text(AppLocalizations.of(context).plsValidateBeneficiary)), ); return; } @@ -155,13 +155,12 @@ class _QuickPayOutsideBankScreen extends State { showDialog( context: context, builder: (ctx) => AlertDialog( - title: const Text('Invalid Amount for RTGS'), - content: const Text( - 'RTGS transactions require a minimum amount of 200,000. Please enter a higher amount or select NEFT as the transaction mode.'), + title: Text(AppLocalizations.of(context).invalidRtgs), + content: Text(AppLocalizations.of(context).invalidRtgsPopUp), actions: [ TextButton( onPressed: () => Navigator.of(ctx).pop(), - child: const Text('OK'), + child: Text(AppLocalizations.of(context).ok), ), ], ), @@ -346,7 +345,7 @@ class _QuickPayOutsideBankScreen extends State { if (value == null || value.isEmpty) { return AppLocalizations.of(context).accountNumberRequired; } 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; }, @@ -385,6 +384,10 @@ class _QuickPayOutsideBankScreen extends State { children: [ Expanded( child: TextFormField( + maxLength: 11, + inputFormatters: [ + LengthLimitingTextInputFormatter(11), + ], decoration: InputDecoration( labelText: AppLocalizations.of(context).ifscCode, border: const OutlineInputBorder(), @@ -520,7 +523,7 @@ class _QuickPayOutsideBankScreen extends State { } else { setState(() { _validationError = - 'Account numbers do not match.'; + AppLocalizations.of(context).accountMismatch; }); } }, @@ -531,7 +534,7 @@ class _QuickPayOutsideBankScreen extends State { child: CircularProgressIndicator( strokeWidth: 2), ) - : const Text('Validate Beneficiary'), + : Text(AppLocalizations.of(context).validateBeneficiary), ), ), ), diff --git a/lib/features/quick_pay/screens/quick_pay_within_bank_screen.dart b/lib/features/quick_pay/screens/quick_pay_within_bank_screen.dart index 5c1b33e..55a8454 100644 --- a/lib/features/quick_pay/screens/quick_pay_within_bank_screen.dart +++ b/lib/features/quick_pay/screens/quick_pay_within_bank_screen.dart @@ -212,7 +212,7 @@ class _QuickPayWithinBankScreen extends State { } else { setState(() { _validationError = - 'Please enter a valid and matching account number.'; + AppLocalizations.of(context).accountMismatch; }); } }, @@ -222,7 +222,7 @@ class _QuickPayWithinBankScreen extends State { height: 20, child: CircularProgressIndicator(strokeWidth: 2), ) - : const Text('Validate Beneficiary'), + : Text(AppLocalizations.of(context).validateBeneficiary), ), ), ), @@ -234,7 +234,7 @@ class _QuickPayWithinBankScreen extends State { const Icon(Icons.check_circle, color: Colors.green), const SizedBox(width: 8), Text( - 'Beneficiary: $_beneficiaryName', + '${AppLocalizations.of(context).beneficiaryName}: $_beneficiaryName', style: const TextStyle( color: Colors.green, fontWeight: FontWeight.bold), ), @@ -338,7 +338,7 @@ class _QuickPayWithinBankScreen extends State { if (!_isBeneficiaryValidated) { setState(() { _validationError = - 'Please validate beneficiary before proceeding.'; + AppLocalizations.of(context).validateBeneficiaryproceeding; }); return; } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 847fba1..a4a8d6e 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -236,6 +236,16 @@ "transactionType": "Transaction Type", "transferType": "Transfer Type", "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" } diff --git a/lib/l10n/app_hi.arb b/lib/l10n/app_hi.arb index 4611c25..e25ae27 100644 --- a/lib/l10n/app_hi.arb +++ b/lib/l10n/app_hi.arb @@ -236,5 +236,15 @@ "transactionType": "लेनदेन प्रकार", "transferType": "स्थानांतरण प्रकार", "utrNo": "यूटीआर नंबर", - "beneficiaryAccountNo": "लाभार्थी खाता संख्या" + "beneficiaryAccountNo": "लाभार्थी खाता संख्या", + "invalidRtgs": "RTGS के लिए अमान्य राशि", + "invalidRtgsPopUp": "RTGS लेनदेन के लिए न्यूनतम 2,00,000 रुपये की राशि की आवश्यकता होती है। कृपया अधिक राशि दर्ज करें या लेनदेन मोड के रूप में NEFT चुनें", + "correctTpin": "कृपया सही टी-पिन दर्ज करें", + "insufficientFund": "आपके खाते में पर्याप्त शेष राशि नहीं है", + "creditedTo": "को श्रेय दिया गया", + "selectTransactionType": "लेन-देन का प्रकार चुनें", + "proceed": "आगे बढ़ना", + "plsValidateBeneficiary": "कृपया पहले लाभार्थी विवरण सत्यापित करें", + "accno7to20": "खाता संख्या सात से बीस अंकों के बीच होनी चाहिए", + "validateBeneficiaryproceeding": "कृपया आगे बढ़ने से पहले लाभार्थी को पट्टे पर मान्य करें" } diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index da9c33c..d787df9 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -1444,6 +1444,66 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'Beneficiary Account No.'** 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 { diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 0a8002c..afab0b7 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -682,4 +682,34 @@ class AppLocalizationsEn extends AppLocalizations { @override 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'; } diff --git a/lib/l10n/app_localizations_hi.dart b/lib/l10n/app_localizations_hi.dart index b2c87b9..bc0eb54 100644 --- a/lib/l10n/app_localizations_hi.dart +++ b/lib/l10n/app_localizations_hi.dart @@ -682,4 +682,34 @@ class AppLocalizationsHi extends AppLocalizations { @override 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 => 'कृपया आगे बढ़ने से पहले लाभार्थी को पट्टे पर मान्य करें'; }