import 'dart:developer'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:customer/models/coupon_model.dart'; import 'package:customer/models/user_model.dart'; import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import '../constant/constant.dart'; import '../models/onprovider_order_model.dart'; import '../models/wallet_transaction_model.dart'; import '../models/worker_model.dart'; import '../service/fire_store_utils.dart'; import '../service/send_notification.dart'; import '../themes/show_toast_dialog.dart'; class OnDemandOrderDetailsController extends GetxController { Rx providerUser = Rx(null); Rxn onProviderOrder = Rxn(); Rxn worker = Rxn(); Rx couponTextController = TextEditingController().obs; Rx cancelBookingController = TextEditingController().obs; RxDouble subTotal = 0.0.obs; RxDouble price = 0.0.obs; RxDouble discountAmount = 0.0.obs; RxDouble totalAmount = 0.0.obs; RxDouble quantity = 0.0.obs; RxString discountType = "".obs; RxString discountLabel = "".obs; RxString offerCode = "".obs; RxList couponList = [].obs; final RxBool isLoading = false.obs; @override void onInit() { super.onInit(); final args = Get.arguments; if (args != null && args is OnProviderOrderModel) { onProviderOrder.value = args; } getData(); } Future getData() async { try { final order = await FireStoreUtils.getProviderOrderById( onProviderOrder.value!.id, ); if (order != null) { onProviderOrder.value = order; discountType.value = order.discountType ?? ""; discountLabel.value = order.discountLabel ?? ""; discountAmount.value = double.tryParse(order.discount.toString()) ?? 0.0; offerCode.value = order.couponCode ?? ""; // Fetch provider providerUser.value = await FireStoreUtils.getUserProfile( order.provider.author.toString(), ); // Fetch worker (if exists) if (order.workerId != null && order.workerId!.isNotEmpty) { worker.value = await FireStoreUtils.getWorker(order.workerId!); } else { worker.value = null; } calculatePrice(); // Load available coupons FireStoreUtils.getProviderCouponAfterExpire( order.provider.author.toString(), ).then((expiredCoupons) { couponList.assignAll(expiredCoupons); }); } else { onProviderOrder.value = null; providerUser.value = null; worker.value = null; couponList.clear(); } } catch (e, st) { log("Error in getData: $e\n$st"); onProviderOrder.value = null; providerUser.value = null; worker.value = null; couponList.clear(); } } void applyCoupon(CouponModel coupon) { double discount = 0.0; if (coupon.discountType == "Percentage" || coupon.discountType == "Percent") { discount = price.value * (double.tryParse(coupon.discount.toString()) ?? 0) / 100; } else { discount = double.tryParse(coupon.discount.toString()) ?? 0; } if (subTotal.value > discount) { discountType.value = coupon.discountType ?? ''; discountLabel.value = coupon.discount.toString(); offerCode.value = coupon.code ?? ''; calculatePrice(); } else { Get.snackbar("Error", "Coupon cannot be applied"); } } void calculatePrice() { double basePrice = (onProviderOrder.value?.provider.disPrice == "" || onProviderOrder.value?.provider.disPrice == "0") ? double.tryParse( onProviderOrder.value?.provider.price.toString() ?? "0", ) ?? 0 : double.tryParse( onProviderOrder.value?.provider.disPrice.toString() ?? "0", ) ?? 0; price.value = basePrice * (onProviderOrder.value?.quantity ?? 0.0); // discount if (discountType.value == "Percentage" || discountType.value == "Percent") { discountAmount.value = price.value * (double.tryParse(discountLabel.value) ?? 0) / 100; } else { discountAmount.value = double.tryParse( discountLabel.value.isEmpty ? '0' : discountLabel.value, ) ?? 0; } subTotal.value = price.value - discountAmount.value; // tax calculation double total = subTotal.value; for (var element in Constant.taxList) { total += Constant.getTaxValue( amount: subTotal.value.toString(), taxModel: element, ); } totalAmount.value = total; } String getDate(String date) { try { DateTime dt = DateTime.parse(date); return "${dt.day}-${dt.month}-${dt.year}"; } catch (e) { return date; } } Future cancelBooking() async { final order = onProviderOrder.value; if (order == null) return; ShowToastDialog.showLoader("Please wait...".tr); try { double total = 0.0; // Calculate total final pricePerUnit = (order.provider.disPrice == "" || order.provider.disPrice == "0") ? double.tryParse(order.provider.price.toString()) ?? 0 : double.tryParse(order.provider.disPrice.toString()) ?? 0; total = pricePerUnit * (order.quantity); // Add tax if (Constant.taxList.isNotEmpty) { for (var tax in Constant.taxList) { total += Constant.getTaxValue( amount: total.toString(), taxModel: tax, ); } } // Admin commission double adminComm = 0.0; if ((order.adminCommission ?? '0') != '0' && (order.adminCommissionType ?? '').isNotEmpty) { if (order.adminCommissionType!.toLowerCase() == 'percentage' || order.adminCommissionType!.toLowerCase() == 'percent') { adminComm = (total * (double.tryParse(order.adminCommission!) ?? 0)) / 100; } else { adminComm = double.tryParse(order.adminCommission!) ?? 0; } } // Refund customer wallet if not COD if ((order.payment_method).toLowerCase() != 'cod') { await FireStoreUtils.setWalletTransaction( WalletTransactionModel( id: Constant.getUuid(), serviceType: 'ondemand-service', amount: total, date: Timestamp.now(), paymentMethod: 'wallet', transactionUser: 'customer', userId: Constant.userModel?.id, isTopup: true, orderId: order.id, note: 'Booking Amount Refund', paymentStatus: "success".tr, ), ); // Deduct from provider if accepted if (order.status == Constant.orderAccepted) { await FireStoreUtils.setWalletTransaction( WalletTransactionModel( id: Constant.getUuid(), serviceType: 'ondemand-service', amount: total, date: Timestamp.now(), paymentMethod: 'wallet', transactionUser: 'provider', userId: order.provider.author ?? '', isTopup: false, orderId: order.id, note: 'Booking Amount Refund', paymentStatus: "success".tr, ), ); } } // Refund admin commission if (order.status == Constant.orderAccepted && adminComm > 0) { await FireStoreUtils.setWalletTransaction( WalletTransactionModel( id: Constant.getUuid(), serviceType: 'ondemand-service', amount: adminComm, date: Timestamp.now(), paymentMethod: 'wallet', transactionUser: 'provider', userId: order.provider.author ?? '', isTopup: true, orderId: order.id, note: 'Admin commission refund', paymentStatus: "success".tr, ), ); } // Update order status & reason order.status = Constant.orderCancelled; order.reason = cancelBookingController.value.text; await FireStoreUtils.updateOnDemandOrder(order); // Ensure this completes // Notify provider final provider = await FireStoreUtils.getUserProfile( order.provider.author ?? '', ); if (provider != null) { Map payload = { "type": 'provider_order', "orderId": order.id, }; await SendNotification.sendFcmMessage( Constant.bookingPlaced, provider.fcmToken ?? '', payload, ); } ShowToastDialog.closeLoader(); Get.back(); ShowToastDialog.showToast("Booking cancelled successfully".tr); } catch (e, st) { log("Cancel error: $e\n$st"); ShowToastDialog.closeLoader(); ShowToastDialog.showToast("Something went wrong".tr); } } }