feat: Implement major features and fix theming bug
This commit introduces several new features and a critical bug fix. - Implemented a full "Quick Pay" flow for both within and outside the bank, including IFSC validation, beneficiary verification, and a TPIN-based payment process. - Added a date range filter to the Account Statement screen and streamlined the UI by removing the amount filters. - Fixed a major bug that prevented dynamic theme changes from being applied. The app now correctly switches between color themes. - Refactored and improved beneficiary management, transaction models, and the fund transfer flow to support NEFT/RTGS.
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:kmobile/data/models/ifsc.dart';
|
||||
import 'package:kmobile/data/models/beneficiary.dart';
|
||||
@@ -9,14 +11,16 @@ class BeneficiaryService {
|
||||
|
||||
Future<String> validateBeneficiaryWithinBank(String accountNumber) async {
|
||||
try {
|
||||
final response = await _dio.get('/api/beneficiary/validate/within-bank', queryParameters: {
|
||||
final response = await _dio
|
||||
.get('/api/beneficiary/validate/within-bank', queryParameters: {
|
||||
'accountNumber': accountNumber,
|
||||
});
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return response.data['name'];
|
||||
} else {
|
||||
throw Exception(response.data['error'] ?? 'Failed to validate beneficiary');
|
||||
throw Exception(
|
||||
response.data['error'] ?? 'Failed to validate beneficiary');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw Exception('Network error: ${e.message}');
|
||||
@@ -24,147 +28,76 @@ class BeneficiaryService {
|
||||
throw Exception('Unexpected error: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<ifsc?> validateIFSC(String ifscCode) async {
|
||||
try {
|
||||
final response = await _dio.get('/api/beneficiary/ifsc-details', queryParameters: {
|
||||
"ifscCode": ifscCode
|
||||
}
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return ifsc.fromJson(response.data);
|
||||
Future<Ifsc> validateIFSC(String ifscCode) async {
|
||||
try {
|
||||
final response = await _dio.get('/api/beneficiary/ifsc-details',
|
||||
queryParameters: {"ifscCode": ifscCode});
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return Ifsc.fromJson(response.data);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
if (e.response?.statusCode == 404) {
|
||||
throw Exception('INVALID IFSC CODE');
|
||||
}
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
if (e.response?.statusCode == 404) {
|
||||
print('Invalid IFSC code.');
|
||||
} else {
|
||||
print('API error: ${e.message}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('Unexpected error: $e');
|
||||
return Ifsc.fromJson({});
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
///Step 1: Validate beneficiary (returns refNo)
|
||||
Future<String?> validateBeneficiary({
|
||||
Future<String> validateBeneficiary({
|
||||
required String accountNo,
|
||||
required String ifscCode,
|
||||
required String remitterName,
|
||||
}) async {
|
||||
|
||||
try {
|
||||
final response = await _dio.post(
|
||||
'/api/beneficiary/validate/outside_bank',
|
||||
queryParameters: {
|
||||
'accountNo': accountNo,
|
||||
'ifscCode': ifscCode,
|
||||
'remitterName': remitterName,
|
||||
},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return response.data['refNo'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error validating beneficiary: $e");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Step 2: Check validation status (returns Beneficiary name if success)
|
||||
Future<String?> checkValidationStatus(String refNo) async {
|
||||
try {
|
||||
final response = await _dio.get(
|
||||
'/api/beneficiary/check',
|
||||
queryParameters: {
|
||||
'refNo': refNo,
|
||||
},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200 && response.data != null) {
|
||||
return Beneficiary.fromJson(response.data).name;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error checking validation status: $e");
|
||||
return null;
|
||||
log('inside validate beneficiary service');
|
||||
final response = await _dio.get(
|
||||
'/api/beneficiary/validate/outside-bank',
|
||||
queryParameters: {
|
||||
'accountNo': accountNo,
|
||||
'ifscCode': ifscCode,
|
||||
'remitterName': remitterName,
|
||||
},
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception("Invalid Beneficiary Details");
|
||||
}
|
||||
return response.data['name'];
|
||||
}
|
||||
|
||||
// Send Data for Validation
|
||||
Future<void> sendForValidation(Beneficiary beneficiary) async {
|
||||
Future<bool> sendForValidation(Beneficiary beneficiary) async {
|
||||
try {
|
||||
print(beneficiary.toJson());
|
||||
final response = await _dio.post(
|
||||
'/api/beneficiary/add',
|
||||
'/api/beneficiary',
|
||||
data: beneficiary.toJson(),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
print("SENT FOR VALIDATION");
|
||||
return true;
|
||||
} else {
|
||||
print("VALIDATION REQUEST FAILED: ${response.statusCode}");
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
print("ERROR IN SENDING REQUEST: $e");
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// Poll to check if beneficiary is found
|
||||
Future<bool> checkIfFound(String accountNo) async {
|
||||
const int timeoutInSeconds = 30;
|
||||
const int intervalInSeconds = 2;
|
||||
const int maxTries = timeoutInSeconds ~/ intervalInSeconds;
|
||||
|
||||
int attempts = 0;
|
||||
|
||||
while (attempts < maxTries) {
|
||||
try {
|
||||
final response = await _dio.get(
|
||||
'/api/beneficiary/check?',
|
||||
queryParameters: {
|
||||
'accountNo': accountNo
|
||||
}
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
print("FOUND");
|
||||
return true;
|
||||
} else if (response.statusCode == 404) {
|
||||
print("NOT FOUND");
|
||||
}
|
||||
} catch (e) {
|
||||
print("ERROR DURING STATUS: $e");
|
||||
}
|
||||
attempts++;
|
||||
}
|
||||
|
||||
print("Beneficiary not found within timeout.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<List<Beneficiary>> fetchBeneficiaryList() async{
|
||||
Future<List<Beneficiary>> fetchBeneficiaryList() async {
|
||||
try {
|
||||
final response = await _dio.get(
|
||||
"/api/beneficiary/get",
|
||||
options: Options(
|
||||
"/api/beneficiary",
|
||||
options: Options(
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return Beneficiary.listFromJson(response.data);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return Beneficiary.listFromJson(response.data);
|
||||
} else {
|
||||
throw Exception("Failed to fetch beneficiaries");
|
||||
}
|
||||
@@ -173,7 +106,4 @@ class BeneficiaryService {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
30
lib/api/services/neft_service.dart
Normal file
30
lib/api/services/neft_service.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:kmobile/data/models/neft_response.dart';
|
||||
import 'package:kmobile/data/models/neft_transaction.dart';
|
||||
|
||||
class NeftService {
|
||||
final Dio _dio;
|
||||
|
||||
NeftService(this._dio);
|
||||
|
||||
Future<NeftResponse> processNeftTransaction(NeftTransaction transaction) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(seconds: 3));
|
||||
final response = await _dio.post(
|
||||
'/api/payment/neft',
|
||||
data: transaction.toJson(),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return NeftResponse.fromJson(response.data);
|
||||
} else {
|
||||
throw Exception(
|
||||
'NEFT transaction failed with status code: ${response.statusCode}');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw Exception('Failed to process NEFT transaction: ${e.message}');
|
||||
} catch (e) {
|
||||
throw Exception('An unexpected error occurred: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
}
|
31
lib/api/services/rtgs_service.dart
Normal file
31
lib/api/services/rtgs_service.dart
Normal file
@@ -0,0 +1,31 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:kmobile/data/models/rtgs_response.dart';
|
||||
import 'package:kmobile/data/models/rtgs_transaction.dart';
|
||||
|
||||
class RtgsService {
|
||||
final Dio _dio;
|
||||
|
||||
RtgsService(this._dio);
|
||||
|
||||
Future<RtgsResponse> processRtgsTransaction(
|
||||
RtgsTransaction 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 RtgsResponse.fromJson(response.data);
|
||||
} else {
|
||||
throw Exception(
|
||||
'RTGS transaction failed with status code: ${response.statusCode}');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw Exception('Failed to process RTGS transaction: ${e.message}');
|
||||
} catch (e) {
|
||||
throw Exception('An unexpected error occurred: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user