fixed PMA 1205 and PMA 1204

faiz_dev
faizatflutter 4 weeks ago
parent 556aa6171c
commit 7855258529

@ -1938,6 +1938,7 @@
"refundReason5": "الخدمة لم تُنجز / غير متاحة بسبب عطل الجهاز / رفض المريض", "refundReason5": "الخدمة لم تُنجز / غير متاحة بسبب عطل الجهاز / رفض المريض",
"refundReason6": "تم إلغاء الإجراء السريري أو تغييره من قِبل الطبيب المحيل", "refundReason6": "تم إلغاء الإجراء السريري أو تغييره من قِبل الطبيب المحيل",
"refundReason7": "تم إلغاء إجراء وحدة الخدمة / المختبر / الأشعة أو تغييره من قِبل الطبيب المحيل", "refundReason7": "تم إلغاء إجراء وحدة الخدمة / المختبر / الأشعة أو تغييره من قِبل الطبيب المحيل",
"refundReason8": "نقل المريض إلى الباقة",
"selectProcedures": "اختر العمليات", "selectProcedures": "اختر العمليات",
"beforeUsingSymptomsChecker": "قبل استخدام فاحص الأعراض، يرجى قراءة شروط الخدمة وتذكر:", "beforeUsingSymptomsChecker": "قبل استخدام فاحص الأعراض، يرجى قراءة شروط الخدمة وتذكر:",
"symptomsCheckerNotDiagnosis": "• فاحص الأعراض ليس تشخيصًا. إنه للمعلومات الخاصة بك فقط وليس رأيًا طبيًا مؤهلاً.", "symptomsCheckerNotDiagnosis": "• فاحص الأعراض ليس تشخيصًا. إنه للمعلومات الخاصة بك فقط وليس رأيًا طبيًا مؤهلاً.",

@ -1930,6 +1930,7 @@
"refundReason5": "Service not done/not available due to machine breakdown/patient refusal", "refundReason5": "Service not done/not available due to machine breakdown/patient refusal",
"refundReason6": "Clinical procedure cancelled or changed by requesting doctor", "refundReason6": "Clinical procedure cancelled or changed by requesting doctor",
"refundReason7": "Service unit/lab/radiology procedure cancelled or changed by requesting doctor", "refundReason7": "Service unit/lab/radiology procedure cancelled or changed by requesting doctor",
"refundReason8": "Patient Transfer to package",
"selectProcedures": "Select Procedures", "selectProcedures": "Select Procedures",
"beforeUsingSymptomsChecker": "Before using the Symptoms Checker, please read the Terms of Service and remember:", "beforeUsingSymptomsChecker": "Before using the Symptoms Checker, please read the Terms of Service and remember:",
"symptomsCheckerNotDiagnosis": "• Symptoms Checker isn't a diagnosis. It's only for your information and not a qualified medical opinion.", "symptomsCheckerNotDiagnosis": "• Symptoms Checker isn't a diagnosis. It's only for your information and not a qualified medical opinion.",

@ -1,6 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:developer';
import 'dart:io'; import 'dart:io';
import 'package:clarity_flutter/clarity_flutter.dart'; import 'package:clarity_flutter/clarity_flutter.dart';
@ -213,9 +212,9 @@ class ApiClientImp implements ApiClient {
// body['TokenID'] = "@dm!n"; // body['TokenID'] = "@dm!n";
// body['PatientID'] = 6424682; // body['PatientID'] = 6424682;
// body['PatientID'] = 4772785; // body['PatientID'] = 4772785;
// body['PatientID'] = 4776462;
// body['PatientID'] = 4776359; // body['PatientID'] = 4776359;
// body['PatientID'] = 4776466; // body['PatientID'] = 4776466;
// body['PatientID'] = 4769748; // body['PatientID'] = 4769748;
// body['PatientID'] = 89754444; // body['PatientID'] = 89754444;
// body['PatientTypeID'] = 1; // body['PatientTypeID'] = 1;

@ -286,13 +286,13 @@ class HabibWalletViewModel extends ChangeNotifier {
return true; return true;
} }
Future<void> fetchAdvancesForHospital() async { Future<void> fetchAdvancesForHospital({required int projectId}) async {
isAdvancesLoading = true; isAdvancesLoading = true;
totalAdvancesBalance = 0.0; totalAdvancesBalance = 0.0;
refundableAdvancesList = []; refundableAdvancesList = [];
notifyListeners(); notifyListeners();
final result = await refundRequestRepo.getRefundableAdvances(); final result = await refundRequestRepo.getRefundableAdvances(projectID: projectId);
result.fold( result.fold(
(failure) { (failure) {
isAdvancesLoading = false; isAdvancesLoading = false;

@ -20,7 +20,7 @@ abstract class RefundRequestRepo {
required int projectId, required int projectId,
}); });
Future<Either<Failure, GenericApiModel<RefundableAdvancesObject>>> getRefundableAdvances(); Future<Either<Failure, GenericApiModel<RefundableAdvancesObject>>> getRefundableAdvances({required int projectID});
Future<Either<Failure, GenericApiModel<RefundStatusModel>>> getRefundStatus({required String referenceNumber}); Future<Either<Failure, GenericApiModel<RefundStatusModel>>> getRefundStatus({required String referenceNumber});
@ -146,14 +146,16 @@ class RefundRequestRepoImp implements RefundRequestRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<RefundableAdvancesObject>>> getRefundableAdvances() async { Future<Either<Failure, GenericApiModel<RefundableAdvancesObject>>> getRefundableAdvances({required int projectID}) async {
try { try {
Map<String, dynamic> body = {"ProjectID": projectID};
GenericApiModel<RefundableAdvancesObject>? apiResponse; GenericApiModel<RefundableAdvancesObject>? apiResponse;
Failure? failure; Failure? failure;
await apiClient.post( await apiClient.post(
ApiConsts.getRefundableAdvances, ApiConsts.getRefundableAdvances,
body: {}, body: body,
onFailure: (error, statusCode, {messageStatus, failureType}) { onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType; failure = failureType;
}, },

@ -148,7 +148,6 @@ class RefundRequestViewModel extends ChangeNotifier {
} }
} }
void clearHospital() { void clearHospital() {
selectedHospital = null; selectedHospital = null;
selectedInvoice = null; selectedInvoice = null;
@ -431,46 +430,6 @@ class RefundRequestViewModel extends ChangeNotifier {
); );
} }
// Refundable Advances
RefundableAdvancesObject? refundableAdvances;
bool isRefundableAdvancesLoading = false;
Future<void> getRefundableAdvances({
Function(RefundableAdvancesObject)? onSuccess,
Function(String)? onError,
}) async {
isRefundableAdvancesLoading = true;
refundableAdvances = null;
notifyListeners();
final result = await refundRequestRepo.getRefundableAdvances();
result.fold(
(failure) {
isRefundableAdvancesLoading = false;
notifyListeners();
if (onError != null) {
onError(failure.message);
} else {
errorHandlerService.handleError(failure: failure);
}
},
(apiResponse) {
isRefundableAdvancesLoading = false;
if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
refundableAdvances = apiResponse.data;
notifyListeners();
if (onSuccess != null) onSuccess(apiResponse.data!);
} else {
notifyListeners();
if (onError != null) {
onError(apiResponse.errorMessage ?? "Failed to load refundable advances");
}
}
},
);
}
// Refund Status // Refund Status
RefundStatusModel? refundStatus; RefundStatusModel? refundStatus;
bool isRefundStatusLoading = false; bool isRefundStatusLoading = false;

File diff suppressed because it is too large Load Diff

@ -2,7 +2,7 @@
// ignore_for_file: constant_identifier_names // ignore_for_file: constant_identifier_names
abstract class LocaleKeys { abstract class LocaleKeys {
static const english = 'english'; static const english = 'english';
static const arabic = 'arabic'; static const arabic = 'arabic';
static const login = 'login'; static const login = 'login';
@ -1921,6 +1921,7 @@ abstract class LocaleKeys {
static const refundReason5 = 'refundReason5'; static const refundReason5 = 'refundReason5';
static const refundReason6 = 'refundReason6'; static const refundReason6 = 'refundReason6';
static const refundReason7 = 'refundReason7'; static const refundReason7 = 'refundReason7';
static const refundReason8 = 'refundReason8';
static const selectProcedures = 'selectProcedures'; static const selectProcedures = 'selectProcedures';
static const beforeUsingSymptomsChecker = 'beforeUsingSymptomsChecker'; static const beforeUsingSymptomsChecker = 'beforeUsingSymptomsChecker';
static const symptomsCheckerNotDiagnosis = 'symptomsCheckerNotDiagnosis'; static const symptomsCheckerNotDiagnosis = 'symptomsCheckerNotDiagnosis';

@ -285,8 +285,8 @@ class _WithdrawRequestCreatePageState extends State<WithdrawRequestCreatePage> {
SizedBox(width: 12.w), SizedBox(width: 12.w),
Expanded( Expanded(
child: LocaleKeys.cashRefundApprovalInstructions.tr(context: context).toText12( child: LocaleKeys.cashRefundApprovalInstructions.tr(context: context).toText12(
color: AppColors.greyInfoTextColor, color: AppColors.greyInfoTextColor,
), ),
), ),
], ],
), ),
@ -345,9 +345,9 @@ class _WithdrawRequestCreatePageState extends State<WithdrawRequestCreatePage> {
final isStep2Valid = vm.selectedWithdrawMethod != null && final isStep2Valid = vm.selectedWithdrawMethod != null &&
(isCash (isCash
? !vm.isCashWithdrawAmountExceeded // Cash: check amount limit ? !vm.isCashWithdrawAmountExceeded // Cash: check amount limit
: (isBankTransfer && : (isBankTransfer
_bankDetailsController.text.trim().isNotEmpty && ? (_bankDetailsController.text.trim().isNotEmpty && _descriptionController.text.trim().isNotEmpty) // Bank: check IBAN and description
_descriptionController.text.trim().isNotEmpty)); // Bank: check fields : true)); // HMG Wallet: no additional validation
return Container( return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
@ -460,10 +460,10 @@ class _WithdrawRequestCreatePageState extends State<WithdrawRequestCreatePage> {
child: SelectHospitalBottomSheet( child: SelectHospitalBottomSheet(
onHospitalSelected: (hospital) { onHospitalSelected: (hospital) {
habibWalletViewModel.setSelectedHospital(hospital); habibWalletViewModel.setSelectedHospital(hospital);
habibWalletViewModel.fetchAdvancesForHospital();
if (hospital.iD != null) { if (hospital.iD != null) {
final projectId = hospital.iD is int ? hospital.iD as int : int.tryParse(hospital.iD.toString()); final projectId = hospital.iD is int ? hospital.iD as int : int.tryParse(hospital.iD.toString());
if (projectId != null) { if (projectId != null) {
habibWalletViewModel.fetchAdvancesForHospital(projectId: projectId);
habibWalletViewModel.getThresholdAmount(projectId: projectId); habibWalletViewModel.getThresholdAmount(projectId: projectId);
} }
} }
@ -492,6 +492,7 @@ class _WithdrawRequestCreatePageState extends State<WithdrawRequestCreatePage> {
Widget _buildBankInputDetails() { Widget _buildBankInputDetails() {
return Consumer<HabibWalletViewModel>( return Consumer<HabibWalletViewModel>(
builder: (context, viewModel, _) { builder: (context, viewModel, _) {
final isBankTransfer = viewModel.selectedWithdrawMethod == RefundTabType.invoices;
final hasError = viewModel.ibanError != null || viewModel.withdrawDescriptionError != null; final hasError = viewModel.ibanError != null || viewModel.withdrawDescriptionError != null;
return Container( return Container(
padding: EdgeInsets.all(16.h), padding: EdgeInsets.all(16.h),
@ -505,32 +506,34 @@ class _WithdrawRequestCreatePageState extends State<WithdrawRequestCreatePage> {
), ),
child: Column( child: Column(
children: [ children: [
TextInputWidget( if (isBankTransfer) ...[
labelText: LocaleKeys.addIbanDetails.tr(), TextInputWidget(
hintText: "SA0000000000000000000000", labelText: LocaleKeys.addIbanDetails.tr(),
controller: _bankDetailsController, hintText: "SA0000000000000000000000",
focusNode: _ibanFocusNode, controller: _bankDetailsController,
autoFocus: false, focusNode: _ibanFocusNode,
keyboardType: TextInputType.text, autoFocus: false,
isEnable: true, keyboardType: TextInputType.text,
isReadOnly: false, isEnable: true,
prefix: null, isReadOnly: false,
isBorderAllowed: false, prefix: null,
isAllowLeadingIcon: true, isBorderAllowed: false,
fontSize: 14.f, isAllowLeadingIcon: true,
isCountryDropDown: false, fontSize: 14.f,
leadingIcon: AppAssets.bankIcon, isCountryDropDown: false,
fontFamily: "Poppins", leadingIcon: AppAssets.bankIcon,
hasError: false, fontFamily: "Poppins",
errorMessage: viewModel.ibanError, hasError: false,
onChange: (value) { errorMessage: viewModel.ibanError,
viewModel.clearIbanError(); onChange: (value) {
}, viewModel.clearIbanError();
onSubmitted: (value) { },
_descriptionFocusNode.requestFocus(); onSubmitted: (value) {
}, _descriptionFocusNode.requestFocus();
), },
Divider(color: AppColors.bottomNAVBorder, thickness: 1).withVerticalPadding(16.h), ),
Divider(color: AppColors.bottomNAVBorder, thickness: 1).withVerticalPadding(16.h),
],
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.description.tr(), labelText: LocaleKeys.description.tr(),
hintText: LocaleKeys.enterDescription.tr(), hintText: LocaleKeys.enterDescription.tr(),
@ -733,9 +736,17 @@ class _WithdrawRequestCreatePageState extends State<WithdrawRequestCreatePage> {
final user = _appState.getAuthenticatedUser(); final user = _appState.getAuthenticatedUser();
final hospital = vm.selectedHospital; final hospital = vm.selectedHospital;
// Determine refund destination: '2' = Bank Transfer, '3' = Cash // Determine refund destination: 1 = HMG Wallet, 2 = Bank Transfer, 3 = Cash
String refundDestination;
final isBankTransfer = vm.selectedWithdrawMethod == RefundTabType.invoices;
final isCash = vm.selectedWithdrawMethod == RefundTabType.cash; final isCash = vm.selectedWithdrawMethod == RefundTabType.cash;
final refundDestination = isCash ? '3' : '2'; if (isCash) {
refundDestination = '3';
} else if (isBankTransfer) {
refundDestination = '2';
} else {
refundDestination = '1'; // HMG Wallet
}
await vm.submitWalletWithdrawalRequest( await vm.submitWalletWithdrawalRequest(
iban: _bankDetailsController.text.trim(), iban: _bankDetailsController.text.trim(),
@ -904,11 +915,9 @@ class _WithdrawRequestCreatePageState extends State<WithdrawRequestCreatePage> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildRefundMethodSelection(habibWalletViewModel), _buildRefundMethodSelection(habibWalletViewModel),
if (habibWalletViewModel.selectedWithdrawMethod == RefundTabType.invoices) ...[ if (habibWalletViewModel.selectedWithdrawMethod != null) ...[
SizedBox(height: 16.h), SizedBox(height: 16.h),
_buildBankInputDetails(), _buildBankInputDetails(),
],
if (habibWalletViewModel.selectedWithdrawMethod != null) ...[
SizedBox(height: 16.h), SizedBox(height: 16.h),
_buildImageUploadSection(habibWalletViewModel), _buildImageUploadSection(habibWalletViewModel),
], ],

@ -340,11 +340,9 @@ class _RefundRequestCreatePageState extends State<RefundRequestCreatePage> {
), ),
), ),
], ],
if (vm.selectedPaymentMethod == RefundTabType.invoices) ...[ if (vm.selectedPaymentMethod != null) ...[
SizedBox(height: 16.h), SizedBox(height: 16.h),
_buildBankInputDetails(vm), _buildBankInputDetails(vm),
],
if (vm.selectedPaymentMethod != null) ...[
SizedBox(height: 16.h), SizedBox(height: 16.h),
_buildImageUploadSection(vm), _buildImageUploadSection(vm),
], ],
@ -507,6 +505,7 @@ class _RefundRequestCreatePageState extends State<RefundRequestCreatePage> {
// Bank Transfer Input // Bank Transfer Input
Widget _buildBankInputDetails(RefundRequestViewModel vm) { Widget _buildBankInputDetails(RefundRequestViewModel vm) {
final isBankTransfer = vm.selectedPaymentMethod == RefundTabType.invoices;
final hasError = vm.ibanError != null || vm.descriptionError != null; final hasError = vm.ibanError != null || vm.descriptionError != null;
return Container( return Container(
padding: EdgeInsets.all(16.h), padding: EdgeInsets.all(16.h),
@ -520,32 +519,34 @@ class _RefundRequestCreatePageState extends State<RefundRequestCreatePage> {
), ),
child: Column( child: Column(
children: [ children: [
TextInputWidget( if (isBankTransfer) ...[
labelText: LocaleKeys.addIbanDetails.tr(), TextInputWidget(
hintText: "SA0000000000000000000000", labelText: LocaleKeys.addIbanDetails.tr(),
controller: _ibanController, hintText: "SA0000000000000000000000",
focusNode: _ibanFocusNode, controller: _ibanController,
autoFocus: false, focusNode: _ibanFocusNode,
keyboardType: TextInputType.text, autoFocus: false,
isEnable: true, keyboardType: TextInputType.text,
isReadOnly: false, isEnable: true,
prefix: null, isReadOnly: false,
isBorderAllowed: false, prefix: null,
isAllowLeadingIcon: true, isBorderAllowed: false,
fontSize: 14.f, isAllowLeadingIcon: true,
isCountryDropDown: false, fontSize: 14.f,
leadingIcon: AppAssets.bankIcon, isCountryDropDown: false,
fontFamily: "Poppins", leadingIcon: AppAssets.bankIcon,
hasError: false, fontFamily: "Poppins",
errorMessage: vm.ibanError, hasError: false,
onChange: (value) { errorMessage: vm.ibanError,
vm.clearIbanError(); onChange: (value) {
}, vm.clearIbanError();
onSubmitted: (value) { },
_descriptionFocusNode.requestFocus(); onSubmitted: (value) {
}, _descriptionFocusNode.requestFocus();
), },
Divider(color: AppColors.bottomNAVBorder, thickness: 1).withVerticalPadding(16.h), ),
Divider(color: AppColors.bottomNAVBorder, thickness: 1).withVerticalPadding(16.h),
],
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.description.tr(), labelText: LocaleKeys.description.tr(),
hintText: LocaleKeys.enterDescription.tr(), hintText: LocaleKeys.enterDescription.tr(),
@ -813,7 +814,7 @@ class _RefundRequestCreatePageState extends State<RefundRequestCreatePage> {
refundClinicName: invoice.clinicName ?? '', refundClinicName: invoice.clinicName ?? '',
refundDestination: refundDestination, refundDestination: refundDestination,
refundIban: isBankTransfer ? _ibanController.text.trim() : '', refundIban: isBankTransfer ? _ibanController.text.trim() : '',
refundRemarks: isBankTransfer ? _descriptionController.text.trim() : '', refundRemarks: _descriptionController.text.trim(),
refundTotalAmount: vm.totalRefundableAmount, refundTotalAmount: vm.totalRefundableAmount,
refundAttachmentsBase64List: vm.refundAttachmentList, refundAttachmentsBase64List: vm.refundAttachmentList,
refundProceduresList: vm.selectedProcedures refundProceduresList: vm.selectedProcedures

@ -49,6 +49,7 @@ class _RefundReasonSheetContentState extends State<_RefundReasonSheetContent> {
LocaleKeys.refundReason5.tr(context: context), LocaleKeys.refundReason5.tr(context: context),
LocaleKeys.refundReason6.tr(context: context), LocaleKeys.refundReason6.tr(context: context),
LocaleKeys.refundReason7.tr(context: context), LocaleKeys.refundReason7.tr(context: context),
LocaleKeys.refundReason8.tr(context: context),
]; ];
@override @override

Loading…
Cancel
Save