fix : buyer in sale out of the province

This commit is contained in:
2025-06-28 13:12:17 +03:30
parent 7bb19a7ffc
commit 1ab478308e
5 changed files with 519 additions and 482 deletions

View File

@@ -1,6 +1,8 @@
import 'package:flutter/material.dart' show Colors;
import 'package:flutter/widgets.dart';
import 'package:rasadyar_auth/data/services/token_storage_service.dart';
import 'package:rasadyar_auth/data/utils/safe_call.dart';
import 'package:rasadyar_chicken/data/models/response/inventory/inventory_model.dart';
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
import 'package:rasadyar_chicken/data/repositories/chicken_repository.dart';
import 'package:rasadyar_chicken/data/repositories/chicken_repository_imp.dart';
@@ -22,15 +24,13 @@ class RootLogic extends GetxController {
Container(color: Colors.amber),
];
late DioRemote dioRemote;
var tokenService = Get.find<TokenStorageService>();
late ChickenRepository chickenRepository;
RxList<ErrorLocationType> errorLocationType = RxList();
RxMap<int, dynamic> inventoryExpandedList = RxMap();
Rxn<InventoryModel> inventoryModel = Rxn<InventoryModel>();
RxList<IranProvinceCityModel> provinces = <IranProvinceCityModel>[].obs;
@override
@@ -42,8 +42,8 @@ class RootLogic extends GetxController {
getProvinces();
/*getInventory();
getKillHouseDistributionInfo();*/
getInventory();
//getKillHouseDistributionInfo();
}
void toggleExpanded(int index) {
@@ -54,6 +54,29 @@ class RootLogic extends GetxController {
}
}
Future<void> getInventory() async {
await safeCall<List<InventoryModel>?>(
call: () async => await chickenRepository.getInventory(token: tokenService.accessToken.value!),
onSuccess: (result) {
if (result != null) {
inventoryModel.value = result.first;
}
},
onError: (error, stackTrace) {
switch (error.response?.statusCode) {
case 401:
errorHandler(error);
break;
case 403:
errorHandler(error);
break;
default:
errorHandler(error);
}
},
);
}
void rootErrorHandler(DioException error) {
handleGeneric(error, () {
tokenService.deleteTokens();
@@ -75,4 +98,10 @@ class RootLogic extends GetxController {
provinces.clear();
}
}
void errorHandler(DioException error) {
handleGeneric(error, () {
tokenService.deleteTokens();
});
}
}

View File

@@ -11,14 +11,18 @@ import 'package:rasadyar_core/core.dart';
class SalesInProvinceLogic extends GetxController {
var rootLogic = Get.find<RootLogic>();
Rxn<List<AllocatedMadeModel>?> allocatedMadeModel =
Rxn<List<AllocatedMadeModel>?>();
Rxn<List<AllocatedMadeModel>?> allocatedMadeModel = Rxn<List<AllocatedMadeModel>?>();
RxList<int> isExpandedList = <int>[].obs;
RxList<ProductModel> rolesProductsModel = RxList<ProductModel>();
RxBool searchIsSelected = false.obs;
RxnString searchedValue = RxnString();
RxList<GuildModel> guildsModel = <GuildModel>[].obs;
GlobalKey<FormState> formKey = GlobalKey<FormState>();
Rxn<Jalali> fromDateFilter = Rxn<Jalali>(null);
Rxn<Jalali> toDateFilter = Rxn<Jalali>(null);
Rxn<ProductModel> selectedProductModel = Rxn<ProductModel>();
Rxn<GuildModel> selectedGuildModel = Rxn<GuildModel>();
Rxn<GuildProfile> guildProfile = Rxn<GuildProfile>();
@@ -37,8 +41,8 @@ class SalesInProvinceLogic extends GetxController {
final RxBool addPageAllocationsMade = false.obs;
final RxBool hasMoreDataAllocationsMade = true.obs;
Rxn<AllocatedMadeModel> selectedAllocationModelForUpdate =
Rxn<AllocatedMadeModel>();
Rxn<AllocatedMadeModel> selectedAllocationModelForUpdate = Rxn<AllocatedMadeModel>();
SubmitStewardAllocation? tmpStewardAllocation;
@override
void onInit() {
@@ -51,17 +55,16 @@ class SalesInProvinceLogic extends GetxController {
ever(saleType, (callback) {
getGuilds();
});
weight.listen((num) {
totalCost.value = num * pricePerKilo.value;
debounce(weight, time: Duration(milliseconds: 110), (callback) {
totalCost.value = callback * weight.value;
});
pricePerKilo.listen((num) {
totalCost.value = num * weight.value;
debounce(pricePerKilo, time: Duration(milliseconds: 100), (callback) {
totalCost.value = callback * weight.value;
});
totalCost.listen((data) {
totalCostController.text = data.toString();
totalCostController.text = data.toString().separatedByComma;
isValid.value =
weight.value > 0 &&
@@ -78,15 +81,23 @@ class SalesInProvinceLogic extends GetxController {
getAllocatedMade();
}
});
debounce(searchedValue, (callback) => getAllocatedMade(), time: Duration(milliseconds: 2000));
ever(searchIsSelected, (data) {
if (data == false) {
searchedValue.value = null;
}
});
}
Future<void> getAllocatedMade() async {
if (isLoadingMoreAllocationsMade.value ||
!hasMoreDataAllocationsMade.value) {
if (isLoadingMoreAllocationsMade.value || !hasMoreDataAllocationsMade.value) {
return;
}
if (addPageAllocationsMade.value) {
if (searchIsSelected.value) {
currentPageAllocationsMade.value = 1;
} else if (addPageAllocationsMade.value) {
currentPageAllocationsMade.value++;
}
safeCall(
@@ -97,6 +108,7 @@ class SalesInProvinceLogic extends GetxController {
pageSize: 20,
search: 'filter',
role: 'Steward',
value: searchedValue.value,
),
),
onSuccess: (result) {
@@ -157,8 +169,7 @@ class SalesInProvinceLogic extends GetxController {
safeCall(
call: () async => await rootLogic.chickenRepository.confirmAllAllocation(
token: rootLogic.tokenService.accessToken.value!,
allocationTokens:
allocatedMadeModel.value?.map((e) => e.key!).toList() ?? [],
allocationTokens: allocatedMadeModel.value?.map((e) => e.key!).toList() ?? [],
),
onSuccess: (result) {
getAllocatedMade();
@@ -169,9 +180,8 @@ class SalesInProvinceLogic extends GetxController {
Future<void> getRolesProducts() async {
safeCall(
call: () async => await rootLogic.chickenRepository.getRolesProducts(
token: rootLogic.tokenService.accessToken.value!,
),
call: () async =>
await rootLogic.chickenRepository.getRolesProducts(token: rootLogic.tokenService.accessToken.value!),
onSuccess: (result) {
if (result != null) {
rolesProductsModel.value = result;
@@ -186,10 +196,7 @@ class SalesInProvinceLogic extends GetxController {
safeCall(
call: () async => await rootLogic.chickenRepository.getGuilds(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(
queryParams: {'free': saleType.value == 2 ? true : false},
role: 'Steward',
),
queryParameters: buildQueryParams(queryParams: {'free': saleType.value == 2 ? true : false}, role: 'Steward'),
),
onSuccess: (result) {
if (result != null) {
@@ -215,9 +222,7 @@ class SalesInProvinceLogic extends GetxController {
Future<void> getGuildProfile() async {
await safeCall(
call: () async => await rootLogic.chickenRepository.getProfile(
token: rootLogic.tokenService.accessToken.value!,
),
call: () async => await rootLogic.chickenRepository.getProfile(token: rootLogic.tokenService.accessToken.value!),
onError: (error, stackTrace) {},
onSuccess: (result) {
guildProfile.value = result;
@@ -225,29 +230,30 @@ class SalesInProvinceLogic extends GetxController {
);
}
Future<void> submitAllocation() async {
SubmitStewardAllocation stewardAllocation = SubmitStewardAllocation(
void setSubmitData() {
tmpStewardAllocation = SubmitStewardAllocation(
approvedPriceStatus: false,
allocationType:
'${guildProfile.value?.steward == true ? "steward" : "guild"}-${selectedGuildModel.value?.steward == true ? "steward" : "guild"}',
'${guildProfile.value?.steward == true ? "steward" : "guild"}_${selectedGuildModel.value?.steward == true ? "steward" : "guild"}',
sellerType: guildProfile.value?.steward == true ? "Steward" : "Guild",
buyerType: selectedGuildModel.value?.steward == true
? "Steward"
: "Guild",
buyerType: selectedGuildModel.value?.steward == true ? "Steward" : "Guild",
amount: pricePerKilo.value,
totalAmount: totalCost.value,
weightOfCarcasses: weight.value,
sellType:saleType.value ==2 ? "free" :'exclusive',
numberOfCarcasses: 0,
guildKey: selectedGuildModel.value?.key,
productKey: selectedProductModel.value?.key,
date: DateTime.now().formattedGregorianDate,
date: DateTime.now().formattedDashedGregorian,
type: "manual",
);
}
Future<void> submitAllocation() async {
safeCall(
call: () async =>
await rootLogic.chickenRepository.postSubmitStewardAllocation(
call: () async => await rootLogic.chickenRepository.postSubmitStewardAllocation(
token: rootLogic.tokenService.accessToken.value!,
request: stewardAllocation,
request: tmpStewardAllocation!,
),
onSuccess: (result) {
@@ -259,8 +265,7 @@ class SalesInProvinceLogic extends GetxController {
Future<void> deleteAllocation(AllocatedMadeModel model) async {
safeCall(
call: () async =>
await rootLogic.chickenRepository.deleteStewardAllocation(
call: () async => await rootLogic.chickenRepository.deleteStewardAllocation(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: {'steward_allocation_key': model.key},
),
@@ -286,9 +291,7 @@ class SalesInProvinceLogic extends GetxController {
pricePerKilo.value = item.amount ?? 0;
totalCost.value = item.totalAmount ?? 0;
weightController.text = weight.value.toString().separatedByComma;
pricePerKiloController.text = pricePerKilo.value
.toString()
.separatedByComma;
pricePerKiloController.text = pricePerKilo.value.toString().separatedByComma;
totalCostController.text = totalCost.value.toString().separatedByComma;
isValid.value = true;
}
@@ -314,8 +317,7 @@ class SalesInProvinceLogic extends GetxController {
);
safeCall(
call: () async =>
await rootLogic.chickenRepository.updateStewardAllocation(
call: () async => await rootLogic.chickenRepository.updateStewardAllocation(
token: rootLogic.tokenService.accessToken.value!,
request: updatedAllocationModel,
),

View File

@@ -3,9 +3,9 @@ import 'package:flutter/services.dart';
import 'package:rasadyar_chicken/data/models/request/conform_allocation/conform_allocation.dart';
import 'package:rasadyar_chicken/data/models/response/allocated_made/allocated_made.dart';
import 'package:rasadyar_chicken/data/models/response/guild/guild_model.dart';
import 'package:rasadyar_chicken/data/models/response/inventory/inventory_model.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
import 'package:rasadyar_chicken/presentation/pages/entering_the_warehouse/string_utils.dart';
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
import 'package:rasadyar_core/core.dart';
import 'logic.dart';
@@ -18,11 +18,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
return Scaffold(
appBar: RAppBar(
titleTextStyle: AppFonts.yekan16Bold.copyWith(color: Colors.white),
centerTitle: true,
hasBack: true,
onBackPressed: () {
Get.back(id: 1);
},
hasBack: false,
leadingWidth: 155,
leading: Row(
mainAxisSize: MainAxisSize.min,
@@ -31,43 +27,31 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
Assets.vec.chickenSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(
Colors.white,
BlendMode.srcIn,
),
),
Text(
'رصدطیور',
style: AppFonts.yekan16Bold.copyWith(color: Colors.white),
colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn),
),
Text('رصدطیور', style: AppFonts.yekan16Bold.copyWith(color: Colors.white)),
],
),
additionalActions: [
GestureDetector(
onTap: () {
// controller.searchIsSelected.value = !controller.searchIsSelected.value;
controller.searchIsSelected.value = !controller.searchIsSelected.value;
},
child: Assets.vec.searchSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(
Colors.white,
BlendMode.srcIn,
),
colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn),
),
),
SizedBox(width: 8),
GestureDetector(
onTap: () {
// Get.bottomSheet(filterBottomSheet());
Get.bottomSheet(filterBottomSheet());
},
child: Assets.vec.filterOutlineSvg.svg(
width: 20,
height: 20,
colorFilter: const ColorFilter.mode(
Colors.white,
BlendMode.srcIn,
),
colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn),
),
),
SizedBox(width: 8),
@@ -77,21 +61,16 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
child: Column(
children: [
routePageWidget(),
buildSearchWidget(),
inventoryWidget(),
allocationsMade(),
SizedBox(height: 40),
],
),
),
floatingActionButton: RFab.add(
onPressed: () {
Get.bottomSheet(
showAddBottomSheet(),
isScrollControlled: true,
backgroundColor: Colors.transparent,
);
Get.bottomSheet(showAddBottomSheet(), isScrollControlled: true, backgroundColor: Colors.transparent);
},
),
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
@@ -99,123 +78,18 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
}
Widget inventoryWidget() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Column(
children: [
const SizedBox(height: 20),
Align(
alignment: Alignment.centerRight,
child: Text(
'موجودی انبار',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
),
),
SizedBox(height: 4),
/* ObxValue(
(data) => data.isEmpty
? Container(
margin: const EdgeInsets.symmetric(vertical: 2),
height: 80,
padding: EdgeInsets.all(6),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColor.blueNormal, width: 1),
),
child: Center(child: CircularProgressIndicator()),
)
: ListView.separated(
shrinkWrap: true,
itemCount: controller.rootLogic.inventoryList.length,
separatorBuilder: (context, index) =>
const SizedBox(height: 8),
itemBuilder: (context, index) {
return ObxValue((expand) {
return GestureDetector(
onTap: () {
controller.rootLogic.toggleExpanded(index);
},
behavior: HitTestBehavior.opaque,
child: AnimatedContainer(
onEnd: () {
controller
.rootLogic
.inventoryExpandedList[index] = !controller
.rootLogic
.inventoryExpandedList[index]!;
},
margin: const EdgeInsets.symmetric(vertical: 2),
padding: EdgeInsets.all(6),
curve: Curves.easeInOut,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: AppColor.blueNormal,
width: 1,
),
),
duration: const Duration(seconds: 1),
height: expand.keys.contains(index) ? 300 : 80,
child: inventoryItem(
isExpanded:
expand.keys.contains(index) && expand[index]!,
index: index,
model: controller.rootLogic.inventoryList[index],
),
),
return Container(
width: Get.width,
height: 39,
margin: EdgeInsets.all(4),
decoration: BoxDecoration(color: AppColor.greenLight, borderRadius: BorderRadius.circular(8)),
alignment: Alignment.center,
child: ObxValue((data) {
return Text(
' موجودی انبار: ${data.value?.totalRemainWeight?.toInt().separatedByComma ?? '0'} کیلوگرم',
style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkHover),
);
}, controller.rootLogic.inventoryExpandedList);
},
),
controller.rootLogic.inventoryList,
),*/
],
),
);
}
Widget inventoryItem({
required bool isExpanded,
required int index,
required InventoryModel model,
}) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 8,
children: [
buildRow('نام محصول', model.name ?? ''),
Visibility(
visible: isExpanded,
child: Column(
spacing: 8,
children: [
buildRow('وزن خریدهای دولتی داخل استان (کیلوگرم)', '0326598653'),
buildRow(
'وزن خریدهای آزاد داخل استان (کیلوگرم)',
model.receiveFreeCarcassesWeight.toString(),
),
buildRow(
'وزن خریدهای خارج استان (کیلوگرم)',
model.freeBuyingCarcassesWeight.toString(),
),
buildRow(
'کل ورودی به انبار (کیلوگرم)',
model.totalFreeBarsCarcassesWeight.toString(),
),
buildRow(
'کل فروش (کیلوگرم)',
model.realAllocatedWeight.toString(),
),
buildRow(
'مانده انبار (کیلوگرم)',
model.totalRemainWeight.toString(),
),
],
),
),
],
}, controller.rootLogic.inventoryModel),
);
}
@@ -230,9 +104,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
child: Text(
title,
textAlign: TextAlign.right,
style: AppFonts.yekan14.copyWith(
color: AppColor.darkGreyDarkHover,
),
style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDarkHover),
),
),
Flexible(
@@ -240,9 +112,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
child: Text(
value,
textAlign: TextAlign.left,
style: AppFonts.yekan14.copyWith(
color: AppColor.darkGreyDarkHover,
),
style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDarkHover),
),
),
],
@@ -253,21 +123,16 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
Widget allocationsMade() {
return Column(
children: [
const SizedBox(height: 20),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 6),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'تخصیصات صورت گرفته',
style: AppFonts.yekan16Bold.copyWith(
color: AppColor.blueNormal,
),
),
Text('تخصیصات صورت گرفته', style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal)),
RElevated(
text: 'تایید یکجا',
height: 30,
textStyle: AppFonts.yekan12.copyWith(color: Colors.white),
onPressed: () {
controller.confirmAllAllocations();
},
@@ -321,15 +186,10 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
}
final result = data.value![index];
return ObxValue((data) {
return allocationsMadeListItem(
expandList: controller.isExpandedList,
index: index,
item: result,
);
return allocationsMadeListItem(expandList: controller.isExpandedList, index: index, item: result);
}, controller.isExpandedList);
},
separatorBuilder: (BuildContext context, int index) =>
SizedBox(height: 8),
separatorBuilder: (BuildContext context, int index) => SizedBox(height: 8),
),
);
}
@@ -348,6 +208,8 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
top: 16,
bottom: MediaQuery.of(Get.context!).viewInsets.bottom + 16,
),
child: Form(
key: controller.formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
@@ -367,10 +229,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
initText: Jalali.now().formatCompactDate(),
),
const SizedBox(height: 12),
Material(
type: MaterialType.transparency,
child: productDropDown(),
),
Material(type: MaterialType.transparency, child: productDropDown()),
const SizedBox(height: 12),
SizedBox(
height: 40,
@@ -404,8 +263,6 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
const SizedBox(height: 12),
guildsDropDown(),
],
),
),
@@ -414,11 +271,14 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
controller: controller.weightController,
keyboardType: TextInputType.number,
borderColor: AppColor.darkGreyLight,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
SeparatorInputFormatter(),
],
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
validator: (value) {
if (int.parse(value!.clearComma) > (controller.rootLogic.inventoryModel.value?.totalRemainWeight?.toInt() ?? 100) ){
return 'وزن تخصیصی بیشتر از موجودی انبار است';
}
return null;
},
onChanged: (p0) {
controller.weight.value = int.tryParse(p0.clearComma) ?? 0;
},
@@ -428,36 +288,23 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
RTextField(
controller: controller.pricePerKiloController,
borderColor: AppColor.darkGreyLight,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
SeparatorInputFormatter(),
],
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
onChanged: (p0) {
controller.pricePerKilo.value =
int.tryParse(p0.clearComma) ?? 0;
controller.pricePerKilo.value = int.tryParse(p0.clearComma) ?? 0;
},
keyboardType: TextInputType.number,
label: 'قیمت هر کیلو',
),
const SizedBox(height: 12),
ObxValue(
(p0) => RTextField(
RTextField(
enabled: false,
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
SeparatorInputFormatter(),
],
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
borderColor: AppColor.darkGreyLight,
initText: controller.totalCost.value
.toString()
.separatedByComma,
controller: controller.totalCostController,
label: 'هزینه کل',
),
controller.totalCost,
),
const SizedBox(height: 20),
ObxValue((data) {
return RElevated(
@@ -466,13 +313,27 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
height: 40,
onPressed: data.value
? () async {
isEditMode
? await controller.submitAllocation()
: await controller.updateAllocation();
if (controller.formKey.currentState?.validate() ?? false) {
iLog("s2");
controller.setSubmitData();
iLog("s3");
Get.bottomSheet(show2StepAddBottomSheet());
}
/* isEditMode
? await controller.updateAllocation()
: () {
iLog("s1");
if (controller.formKey.currentState?.validate() ?? false) {
iLog("s2");
controller.setSubmitData();
iLog("s3");
Get.bottomSheet(show2StepAddBottomSheet());
}
};
controller.clearForm();
controller.getAllocatedMade();
Get.back();
Get.back();*/
}
: null,
);
@@ -481,6 +342,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
],
),
),
),
);
}
@@ -538,10 +400,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
Assets.vec.cubeSearchSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(
AppColor.blueNormal,
BlendMode.srcIn,
),
colorFilter: const ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
SizedBox(width: 6),
],
@@ -575,10 +434,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
child: Container(
width: Get.width,
margin: const EdgeInsets.fromLTRB(0, 0, 10, 0),
decoration: BoxDecoration(
color: getTintColor(item),
borderRadius: BorderRadius.circular(8),
),
decoration: BoxDecoration(color: getTintColor(item), borderRadius: BorderRadius.circular(8)),
child: AnimatedSize(
duration: Duration(milliseconds: 400),
alignment: Alignment.center,
@@ -627,18 +483,14 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
Text(
item.steward?.user?.fullname ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(
color: AppColor.blueNormal,
),
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
),
SizedBox(height: 2),
Text(
item.createDate?.formattedJalaliDate,
item.createDate?.formattedJalaliDate ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(
color: AppColor.bgDark,
),
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
),
],
),
@@ -654,16 +506,12 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
Text(
'${item.weightOfCarcasses.separatedByComma} Kg',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(
color: AppColor.bgDark,
),
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
Text(
'${item.amount.separatedByComma} ریال',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(
color: AppColor.darkGreyDark,
),
style: AppFonts.yekan12.copyWith(color: AppColor.darkGreyDark),
),
],
),
@@ -673,9 +521,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
child: Text(
'${item.allocationType?.faAllocationType}',
textAlign: TextAlign.center,
style: AppFonts.yekan10.copyWith(
color: AppColor.darkGreyDark,
),
style: AppFonts.yekan10.copyWith(color: AppColor.darkGreyDark),
),
),
@@ -686,16 +532,12 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
secondChild: Container(
padding: EdgeInsets.fromLTRB(8, 12, 14, 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
child: Column(
spacing: 8,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: () {
@@ -710,87 +552,53 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
child: Assets.vec.editSvg.svg(
width: 20,
height: 20,
colorFilter: ColorFilter.mode(
AppColor.blueNormal,
BlendMode.srcIn,
),
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
),
Text(
item.allocationType?.faAllocationType,
textAlign: TextAlign.center,
style: AppFonts.yekan16.copyWith(
color: AppColor.greenDark,
),
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
),
GestureDetector(
onTap: () {
buildDeleteDialog(
onConfirm: () =>
controller.deleteAllocation(item),
onConfirm: () {
expandList.remove(index);
return controller.deleteAllocation(item);
},
);
},
child: Assets.vec.trashSvg.svg(
width: 16,
height: 16,
colorFilter: ColorFilter.mode(
AppColor.error,
BlendMode.srcIn,
),
colorFilter: ColorFilter.mode(AppColor.error, BlendMode.srcIn),
),
),
],
),
buildRow(
'تاریخ ثبت',
item.date!.formattedJalaliDate ?? 'N/A',
),
buildRow('تاریخ ثبت', item.date!.formattedJalaliDate ?? 'N/A'),
buildRow(
'نام و نام خانوادگی خریدار',
getBuyerInformation(item)?.user?.fullname ??
'N/A',
),
buildRow(
'شماره خریدار',
getBuyerInformation(item)?.user?.mobile ??
'N/A',
),
buildRow(
'نوع فروش',
item.sellType?.faItem ?? 'N/A',
),
buildRow(
'قیمت هر کیلو',
'${item.amount.separatedByComma ?? 0} ریال ',
),
buildRow(
'قیمت کل',
'${item.totalAmount.separatedByComma ?? 0} ریال',
getBuyerInformation(item)?.user?.fullname ?? 'N/A',
),
buildRow('شماره خریدار', getBuyerInformation(item)?.user?.mobile ?? 'N/A'),
buildRow('نوع فروش', item.sellType?.faItem ?? 'N/A'),
buildRow('قیمت هر کیلو', '${item.amount.separatedByComma ?? 0} ریال '),
buildRow('قیمت کل', '${item.totalAmount.separatedByComma ?? 0} ریال'),
buildRow(
'وزن تخصیصی',
'${item.weightOfCarcasses?.toInt().separatedByComma ?? 0} کیلوگرم',
),
buildRow(
'کداحراز',
item.registrationCode?.toString() ?? 'N/A',
),
buildRow('کداحراز', item.registrationCode?.toString() ?? 'N/A'),
buildRow(
'وضعیت کد احراز',
item.systemRegistrationCode == true
? "ارسال شده"
: "ارسال نشده" ?? 'N/A',
),
buildRow(
'افت وزن(کیلوگرم)',
item.weightLossOfCarcasses
?.toInt()
.toString() ??
'N/A',
item.systemRegistrationCode == true ? "ارسال شده" : "ارسال نشده" ?? 'N/A',
),
buildRow('افت وزن(کیلوگرم)', item.weightLossOfCarcasses?.toInt().toString() ?? 'N/A'),
Row(
spacing: 10,
@@ -800,25 +608,17 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
backgroundColor: AppColor.greenNormal,
height: 40,
text: 'تایید',
textStyle: AppFonts.yekan18.copyWith(
color: Colors.white,
),
textStyle: AppFonts.yekan18.copyWith(color: Colors.white),
onPressed: () {
ConformAllocation confromation =
ConformAllocation(
ConformAllocation confromation = ConformAllocation(
allocation_key: item.key,
number_of_carcasses:
item.numberOfCarcasses,
weight_of_carcasses: item
.weightOfCarcasses
?.toInt(),
number_of_carcasses: item.numberOfCarcasses,
weight_of_carcasses: item.weightOfCarcasses?.toInt(),
amount: item.amount,
total_amount: item.totalAmount,
);
controller.confirmAllocation(
confromation,
);
controller.confirmAllocation(confromation);
},
),
),
@@ -827,13 +627,9 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
height: 40,
borderColor: AppColor.error,
text: 'رد',
textStyle: AppFonts.yekan18.copyWith(
color: AppColor.error,
),
textStyle: AppFonts.yekan18.copyWith(color: AppColor.error),
onPressed: () {
controller.denyAllocation(
item.key ?? '',
);
controller.denyAllocation(item.key ?? '');
},
),
),
@@ -853,11 +649,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
child: Center(
child: RotatedBox(
quarterTurns: 3,
child: Text(
item.state?.faItem,
style: AppFonts.yekan8,
textAlign: TextAlign.center,
),
child: Text(item.state?.faItem, style: AppFonts.yekan8, textAlign: TextAlign.center),
),
),
),
@@ -875,16 +667,10 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
decoration: BoxDecoration(
color: AppColor.greenLightHover,
borderRadius: BorderRadius.circular(4),
border: Border.all(
width: 0.50,
color: AppColor.greenDarkActive,
),
border: Border.all(width: 0.50, color: AppColor.greenDarkActive),
),
alignment: Alignment.center,
child: Text(
(index + 1).toString(),
style: AppFonts.yekan12.copyWith(color: Colors.black),
),
child: Text((index + 1).toString(), style: AppFonts.yekan12.copyWith(color: Colors.black)),
),
),
],
@@ -918,17 +704,12 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
}
}
Future<void> buildDeleteDialog({
required Future<void> Function() onConfirm,
}) async {
Future<void> buildDeleteDialog({required Future<void> Function() onConfirm}) async {
await Get.defaultDialog(
title: 'حذف ',
middleText: 'آیا از حذف این مورد مطمئن هستید؟',
confirm: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: AppColor.error,
foregroundColor: Colors.white,
),
style: ElevatedButton.styleFrom(backgroundColor: AppColor.error, foregroundColor: Colors.white),
onPressed: () async {
await onConfirm();
Get.back();
@@ -943,4 +724,232 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
),
).whenComplete(() => controller.getAllocatedMade());
}
ObxValue<RxBool> buildSearchWidget() {
return ObxValue((data) {
return AnimatedContainer(
duration: Duration(milliseconds: 300),
padding: EdgeInsets.only(top: 5),
curve: Curves.easeInOut,
height: data.value ? 50 : 0,
child: Visibility(
visible: data.value,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: RTextField(
suffixIcon: Padding(
padding: const EdgeInsets.all(12.0),
child: Assets.vec.searchSvg.svg(
width: 10,
height: 10,
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
),
hintText: 'جستجو',
onChanged: (value) {
controller.searchedValue.value = value;
},
controller: TextEditingController(),
),
),
),
);
}, controller.searchIsSelected);
}
Widget filterBottomSheet() {
return BaseBottomSheet(
height: 250,
child: Column(
spacing: 16,
children: [
Text('فیلترها', style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover)),
Row(
spacing: 8,
children: [
Expanded(
child: timeFilterWidget(
date: controller.fromDateFilter,
onChanged: (jalali) => controller.fromDateFilter.value = jalali,
),
),
Expanded(
child: timeFilterWidget(
isFrom: false,
date: controller.toDateFilter,
onChanged: (jalali) => controller.toDateFilter.value = jalali,
),
),
],
),
SizedBox(height: 2),
RElevated(
text: 'اعمال فیلتر',
onPressed: () {
controller.getAllocatedMade();
Get.back();
},
height: 40,
),
SizedBox(height: 16),
],
),
);
}
GestureDetector timeFilterWidget({
isFrom = true,
required Rxn<Jalali> date,
required Function(Jalali jalali) onChanged,
}) {
return GestureDetector(
onTap: () {
Get.bottomSheet(modalDatePicker((value) => onChanged(value)));
},
child: Container(
height: 35,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 1, color: AppColor.blueNormal),
),
padding: EdgeInsets.symmetric(horizontal: 11, vertical: 4),
child: Row(
spacing: 8,
children: [
Assets.vec.calendarSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
Text(isFrom ? 'از' : 'تا', style: AppFonts.yekan16.copyWith(color: AppColor.blueNormal)),
Expanded(
child: ObxValue((data) {
return Text(
date.value?.formatCompactDate() ?? Jalali.now().formatCompactDate(),
textAlign: TextAlign.center,
style: AppFonts.yekan16.copyWith(color: AppColor.lightGreyNormalActive),
);
}, date),
),
],
),
),
);
}
Container modalDatePicker(ValueChanged<Jalali> onDateSelected) {
Jalali? tempPickedDate;
return Container(
height: 250,
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: Row(
children: [
SizedBox(width: 20),
RElevated(
height: 35,
width: 70,
textStyle: AppFonts.yekan14.copyWith(color: Colors.white),
onPressed: () {
onDateSelected(tempPickedDate ?? Jalali.now());
Get.back();
},
text: 'تایید',
),
Spacer(),
RElevated(
height: 35,
width: 70,
backgroundColor: AppColor.error,
textStyle: AppFonts.yekan14.copyWith(color: Colors.white),
onPressed: () {
onDateSelected(tempPickedDate ?? Jalali.now());
Get.back();
},
text: 'لغو',
),
SizedBox(width: 20),
],
),
),
Divider(height: 0, thickness: 1),
Expanded(
child: Container(
child: PersianCupertinoDatePicker(
initialDateTime: Jalali.now(),
mode: PersianCupertinoDatePickerMode.date,
onDateTimeChanged: (dateTime) {
tempPickedDate = dateTime;
},
),
),
),
],
),
);
}
Widget show2StepAddBottomSheet() {
return BaseBottomSheet(
height: Get.height*.35,
child: Column(
spacing: 8,
children: [
buildRow('تاریخ ثبت', controller.tmpStewardAllocation?.date?.formattedJalaliDate ?? 'N/A'),
buildRow(
'نام و نام خانوادگی خریدار',
controller.guildsModel
.firstWhere((p0) => p0.key == controller.tmpStewardAllocation?.guildKey)
.user
?.fullname ??
'N/A',
),
buildRow(
'شماره خریدار',
controller.guildsModel.firstWhere((p0) => p0.key == controller.tmpStewardAllocation?.guildKey).user?.mobile ??
'N/A',
),
buildRow('قیمت هر کیلو', '${controller.tmpStewardAllocation?.amount.separatedByComma ?? 0} ریال '),
buildRow(
'وزن تخصیصی',
'${controller.tmpStewardAllocation?.weightOfCarcasses?.toInt().separatedByComma ?? 0} کیلوگرم',
),
buildRow('قیمت کل', '${controller.tmpStewardAllocation?.totalAmount.separatedByComma ?? 0} ریال'),
Row(
spacing: 10,
children: [
Expanded(
child: RElevated(
backgroundColor: AppColor.greenNormal,
height: 40,
text: 'ثبت',
textStyle: AppFonts.yekan18.copyWith(color: Colors.white),
onPressed: () async {
await controller.submitAllocation();
Get..back()..back();
},
),
),
Expanded(
child: ROutlinedElevated(
height: 40,
borderColor: AppColor.error,
text: ' بازگشت',
textStyle: AppFonts.yekan18.copyWith(color: AppColor.error),
onPressed: () {
Get.until((route) => route.settings.name == ChickenRoutes.salesInProvince);
},
),
),
],
),
],
),
);
}
}

View File

@@ -4,29 +4,26 @@ import 'package:persian_datetime_picker/persian_datetime_picker.dart';
extension XDateTime on String {
get toDateTime => DateTime.parse(this);
get formattedJalaliDate{
final dateTime = DateTime.parse(this);
String get formattedJalaliDate {
String tmp = contains("/") ? replaceAll("/", "-") : this;
final dateTime = DateTime.parse(tmp);
final jalaliDate = Jalali.fromDateTime(dateTime);
return "${jalaliDate.year}/${jalaliDate.month.toString().padLeft(2, '0')}/${jalaliDate.day.toString().padLeft(2, '0')}";
}
get formattedJalaliDateYHMS {
String get formattedJalaliDateYHMS {
final dateTime = DateTime.parse(this);
final jalaliDate = Jalali.fromDateTime(dateTime);
return "${jalaliDate.hour.toString().padLeft(2, '0')}:${jalaliDate.minute.toString().padLeft(2, '0')} - ${jalaliDate.year}/${jalaliDate.month.toString().padLeft(2, '0')}/${jalaliDate.day.toString().padLeft(2, '0')}";
}
get formattedYHMS{
String get formattedYHMS {
return DateFormat('yyyy-MM-dd HH:mm:ss').format(toDateTime);
}
}
extension XDateTime2 on DateTime {
get formattedJalaliDate {
final jalaliDate = Jalali.fromDateTime(this);
return "${jalaliDate.year}/${jalaliDate.month.toString().padLeft(2, '0')}/${jalaliDate.day.toString().padLeft(2, '0')}";

View File

@@ -7,7 +7,7 @@ extension XString on String {
return number != null ? formatter.format(number) : this;
}
get clearComma {
String get clearComma {
return replaceAll(RegExp(r'\D'), '');
}
}