2024-04-03 13:45:34 +08:00
|
|
|
import 'dart:convert';
|
|
|
|
|
|
|
|
import 'package:decimal/decimal.dart';
|
2024-04-02 12:24:08 +08:00
|
|
|
import 'package:flutter/material.dart';
|
2024-04-01 17:35:34 +08:00
|
|
|
import 'package:get/get.dart';
|
2024-04-03 13:45:34 +08:00
|
|
|
import 'package:math_expressions/math_expressions.dart';
|
|
|
|
import 'package:sk_base_mobile/models/base_search_more_controller.dart';
|
2024-04-01 17:35:34 +08:00
|
|
|
import 'package:sk_base_mobile/models/sale_quotation.model.dart';
|
2024-04-02 12:24:08 +08:00
|
|
|
import 'package:sk_base_mobile/screens/sale_quotation/components/sale_quotation_group_search.dart';
|
2024-04-03 13:45:34 +08:00
|
|
|
import 'package:sk_base_mobile/services/storage.service.dart';
|
|
|
|
import 'package:sk_base_mobile/util/snack_bar.util.dart';
|
|
|
|
import 'package:sk_base_mobile/widgets/core/sk_muti_search_more.dart';
|
2024-04-02 12:24:08 +08:00
|
|
|
import 'package:sk_base_mobile/widgets/core/sk_single_search_more.dart';
|
|
|
|
import 'package:sk_base_mobile/util/modal.util.dart';
|
|
|
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
2024-04-02 16:22:21 +08:00
|
|
|
import 'package:pinyin/pinyin.dart';
|
2024-04-01 17:35:34 +08:00
|
|
|
|
|
|
|
class SaleQuotationController extends GetxController {
|
|
|
|
static SaleQuotationController get to => Get.find();
|
|
|
|
final RxList editingcell = RxList([null, null, null]);
|
2024-04-03 13:45:34 +08:00
|
|
|
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
2024-04-01 17:35:34 +08:00
|
|
|
RxList<SaleQuotationItemModel> products = RxList([
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型支架控制器', unit: '台', spec: 'ZDYZ-Z'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器'),
|
|
|
|
SaleQuotationItemModel(name: '矿用隔爆兼本安型电源'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型隔离耦合器'),
|
|
|
|
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器'),
|
|
|
|
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-控制器'),
|
|
|
|
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-驱动器'),
|
|
|
|
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-隔离耦合器'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型支架无线遥控器'),
|
|
|
|
SaleQuotationItemModel(name: '矿用隔爆兼本安型电源'),
|
|
|
|
SaleQuotationItemModel(name: '电液换向阀(10功能10接口)', remark: '中间过渡架主阀组'),
|
|
|
|
SaleQuotationItemModel(name: '电液换向阀(20功能20接口)', remark: '端头架主阀组'),
|
|
|
|
SaleQuotationItemModel(name: '自动反冲洗过滤装置', remark: '流量:900L/min,过滤精度25μm'),
|
|
|
|
SaleQuotationItemModel(name: '全自动反冲洗过滤器电缆', remark: '控制器-自动反冲洗'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型位移传感器'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型压力传感器'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型红外发射器'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型LED信号灯'),
|
|
|
|
SaleQuotationItemModel(name: '倾角传感器'),
|
|
|
|
SaleQuotationItemModel(name: '各类安装附件'),
|
|
|
|
]);
|
|
|
|
RxList<SaleQuotationModel> groups = RxList<SaleQuotationModel>([]);
|
2024-04-03 13:45:34 +08:00
|
|
|
RxInt totalCost = RxInt(0);
|
|
|
|
RxDouble totalPrice = RxDouble(0.0);
|
|
|
|
RxBool isFormulaEditing = false.obs;
|
|
|
|
RxString formula = '成本 * 1.3 / 0.864'.obs;
|
2024-04-01 17:35:34 +08:00
|
|
|
@override
|
|
|
|
void onReady() {
|
2024-04-03 13:45:34 +08:00
|
|
|
init();
|
2024-04-01 17:35:34 +08:00
|
|
|
super.onReady();
|
|
|
|
}
|
2024-04-02 12:24:08 +08:00
|
|
|
|
2024-04-03 13:45:34 +08:00
|
|
|
Future<void> init() async {
|
|
|
|
String? salesQuotation = StorageService.to.getString('salesQuotation');
|
|
|
|
if (salesQuotation != null) {
|
|
|
|
groups.assignAll((jsonDecode(salesQuotation) as List)
|
|
|
|
.map((e) => SaleQuotationModel.fromJson(e))
|
|
|
|
.toList());
|
|
|
|
calculateTotal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void calculateTotal({String? newFormula}) {
|
|
|
|
//计算groups中所有items中的amout总和
|
|
|
|
totalCost.value = groups.fold<int>(0, (previousValue, element) {
|
|
|
|
return previousValue +
|
|
|
|
element.items.fold<int>(0, (previousValue, element) {
|
|
|
|
return previousValue + element.amount;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
Parser p = Parser();
|
|
|
|
Expression exp = p.parse(newFormula ?? formula.value);
|
|
|
|
Variable x = Variable('成本');
|
|
|
|
ContextModel cm = ContextModel()..bindVariable(x, Number(totalCost.value));
|
|
|
|
double eval = exp.evaluate(EvaluationType.REAL, cm);
|
|
|
|
totalPrice.value = eval.toPrecision(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 实时计算数量,单价,总价之间的关系
|
|
|
|
SaleQuotationItemModel calculateRow(
|
|
|
|
SaleQuotationItemModel data, String changedField) {
|
|
|
|
Decimal quantity = Decimal.fromInt(0);
|
|
|
|
Decimal cost = Decimal.fromInt(0);
|
|
|
|
Decimal amount = Decimal.fromInt(0);
|
|
|
|
if (data.quantity != 0) {
|
|
|
|
quantity = Decimal.parse('${data.quantity}');
|
|
|
|
}
|
|
|
|
if (data.cost != 0) {
|
|
|
|
cost = Decimal.parse('${data.cost}');
|
|
|
|
}
|
|
|
|
if (data.amount != 0) {
|
|
|
|
amount = Decimal.parse('${data.amount}');
|
|
|
|
}
|
|
|
|
// 入库一般是先输入单价和数量,然后计算单价
|
|
|
|
if (changedField != 'amount') {
|
|
|
|
Decimal result = cost * quantity;
|
|
|
|
data.amount = result != Decimal.zero ? result.toBigInt().toInt() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changedField == 'amount' && quantity != Decimal.zero) {
|
|
|
|
Decimal result =
|
|
|
|
(amount / quantity).toDecimal(scaleOnInfinitePrecision: 10);
|
|
|
|
data.cost = result != Decimal.zero ? result.toBigInt().toInt() : 0;
|
|
|
|
} else if (changedField != 'amount') {
|
|
|
|
Decimal result = (cost * quantity);
|
|
|
|
data.amount = result != Decimal.zero ? result.toBigInt().toInt() : 0;
|
|
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
void saveChanges(int groupIndex, int rowIndex, SaleQuotationItemModel data,
|
|
|
|
String changedField) {
|
|
|
|
data = calculateRow(data, changedField);
|
|
|
|
groups[groupIndex].items[rowIndex] = data;
|
|
|
|
calculateTotal();
|
|
|
|
stopEditing();
|
|
|
|
}
|
|
|
|
|
|
|
|
void stopEditing() {
|
|
|
|
editingcell.assignAll([null, null, null]);
|
|
|
|
save();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> save() async {
|
|
|
|
await StorageService.to
|
|
|
|
.setString('salesQuotation', jsonEncode(groups.toJson()));
|
|
|
|
// SnackBarUtil().success('已保存到本地');
|
|
|
|
}
|
|
|
|
|
|
|
|
void addGroup() async {
|
2024-04-02 12:24:08 +08:00
|
|
|
final controller = Get.put(GroupSearchMoreController());
|
|
|
|
// 选择组件 选择分组
|
|
|
|
ModalUtil.showGeneralDialog(
|
2024-04-03 13:45:34 +08:00
|
|
|
content: SkMutilSearchMore<SaleQuotationModel>(
|
2024-04-02 12:24:08 +08:00
|
|
|
controller: controller,
|
|
|
|
enablePullUp: false,
|
|
|
|
enablePullDown: true,
|
2024-04-03 13:45:34 +08:00
|
|
|
onOk: (List<int> indexes) {
|
|
|
|
groups.addAll(controller.list.where((element) {
|
|
|
|
return indexes.contains(controller.list.indexOf(element));
|
|
|
|
}));
|
|
|
|
save();
|
|
|
|
},
|
|
|
|
leadingBuilder: (index) {
|
|
|
|
return Container(
|
|
|
|
padding: EdgeInsets.symmetric(
|
|
|
|
horizontal: ScreenAdaper.width(5),
|
|
|
|
vertical: ScreenAdaper.height(10)),
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
Text(
|
|
|
|
controller.list[index].name,
|
|
|
|
style: TextStyle(fontSize: ScreenAdaper.height(30)),
|
2024-04-02 12:24:08 +08:00
|
|
|
),
|
2024-04-03 13:45:34 +08:00
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
2024-04-02 12:24:08 +08:00
|
|
|
},
|
|
|
|
),
|
|
|
|
width: Get.width - ScreenAdaper.width(50))
|
|
|
|
.then((value) => Get.delete<GroupSearchController>());
|
2024-04-03 13:45:34 +08:00
|
|
|
calculateTotal();
|
2024-04-02 12:24:08 +08:00
|
|
|
}
|
|
|
|
|
2024-04-03 13:45:34 +08:00
|
|
|
void removeGroup(int index) {
|
2024-04-02 12:24:08 +08:00
|
|
|
groups.removeAt(index);
|
2024-04-03 13:45:34 +08:00
|
|
|
calculateTotal();
|
|
|
|
save();
|
2024-04-02 12:24:08 +08:00
|
|
|
}
|
|
|
|
|
2024-04-03 13:45:34 +08:00
|
|
|
void addItems(int groupIndex) async {
|
2024-04-02 12:24:08 +08:00
|
|
|
final controller = Get.put(ItemSearchMoreController());
|
|
|
|
// 选择产品
|
|
|
|
ModalUtil.showGeneralDialog(
|
2024-04-03 13:45:34 +08:00
|
|
|
content: SkMutilSearchMore<SaleQuotationItemModel>(
|
2024-04-02 12:24:08 +08:00
|
|
|
controller: controller,
|
|
|
|
enablePullUp: false,
|
|
|
|
enablePullDown: true,
|
|
|
|
isDialog: true,
|
2024-04-03 13:45:34 +08:00
|
|
|
onOk: (List<int> indexes) {
|
|
|
|
groups[groupIndex].items.addAll(products.where((element) {
|
|
|
|
return indexes.contains(products.indexOf(element));
|
|
|
|
}));
|
|
|
|
save();
|
|
|
|
},
|
|
|
|
leadingBuilder: (index) {
|
|
|
|
return Container(
|
|
|
|
padding: EdgeInsets.symmetric(
|
|
|
|
horizontal: ScreenAdaper.width(5),
|
|
|
|
vertical: ScreenAdaper.height(10)),
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
Text(
|
|
|
|
controller.list[index].name,
|
|
|
|
style: TextStyle(fontSize: ScreenAdaper.height(25)),
|
2024-04-02 12:24:08 +08:00
|
|
|
),
|
2024-04-03 13:45:34 +08:00
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
2024-04-02 12:24:08 +08:00
|
|
|
},
|
|
|
|
),
|
|
|
|
width: Get.width - ScreenAdaper.width(50))
|
|
|
|
.then((value) => Get.delete<ItemSearchMoreController>());
|
2024-04-03 13:45:34 +08:00
|
|
|
calculateTotal();
|
|
|
|
}
|
|
|
|
|
|
|
|
void removeItem(int groupIndex, int rowIndex) {
|
|
|
|
groups[groupIndex].items.removeAt(rowIndex);
|
|
|
|
calculateTotal();
|
2024-04-02 12:24:08 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class GroupSearchMoreController extends GetxController
|
2024-04-03 13:45:34 +08:00
|
|
|
with BaseSearchMoreController<SaleQuotationModel> {
|
2024-04-02 12:24:08 +08:00
|
|
|
@override
|
|
|
|
Future<List<SaleQuotationModel>> getData({bool isRefresh = false}) async {
|
|
|
|
List<SaleQuotationModel> newList = [
|
2024-04-02 16:22:21 +08:00
|
|
|
SaleQuotationModel(name: '中间过渡架电控部分', items: RxList([])),
|
|
|
|
SaleQuotationModel(name: '端头架电控部分', items: RxList([])),
|
|
|
|
SaleQuotationModel(name: '主阀部分', items: RxList([])),
|
|
|
|
SaleQuotationModel(name: '自动反冲洗过滤器部分', items: RxList([])),
|
|
|
|
SaleQuotationModel(name: '位移测量部分', items: RxList([])),
|
|
|
|
SaleQuotationModel(name: '压力检测部分', items: RxList([])),
|
|
|
|
SaleQuotationModel(name: '煤机定位部分', items: RxList([])),
|
|
|
|
SaleQuotationModel(name: '姿态检测部分', items: RxList([])),
|
2024-04-02 12:24:08 +08:00
|
|
|
];
|
2024-04-02 16:22:21 +08:00
|
|
|
list.assignAll(newList
|
|
|
|
.where((element) => PinyinHelper.getPinyin(element.name, separator: '')
|
|
|
|
.contains(searchKey.value))
|
|
|
|
.toList());
|
2024-04-02 12:24:08 +08:00
|
|
|
return newList;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class ItemSearchMoreController extends GetxController
|
2024-04-03 13:45:34 +08:00
|
|
|
with BaseSearchMoreController<SaleQuotationItemModel> {
|
2024-04-02 12:24:08 +08:00
|
|
|
@override
|
|
|
|
Future<List<SaleQuotationItemModel>> getData({bool isRefresh = false}) async {
|
|
|
|
List<SaleQuotationItemModel> newList = [
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型支架控制器', unit: '台', spec: 'ZDYZ-Z'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器'),
|
|
|
|
SaleQuotationItemModel(name: '矿用隔爆兼本安型电源'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型隔离耦合器'),
|
|
|
|
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器'),
|
|
|
|
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-控制器'),
|
|
|
|
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-驱动器'),
|
|
|
|
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-隔离耦合器'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型支架无线遥控器'),
|
|
|
|
SaleQuotationItemModel(name: '矿用隔爆兼本安型电源'),
|
|
|
|
SaleQuotationItemModel(name: '电液换向阀(10功能10接口)', remark: '中间过渡架主阀组'),
|
|
|
|
SaleQuotationItemModel(name: '电液换向阀(20功能20接口)', remark: '端头架主阀组'),
|
|
|
|
SaleQuotationItemModel(name: '自动反冲洗过滤装置', remark: '流量:900L/min,过滤精度25μm'),
|
|
|
|
SaleQuotationItemModel(name: '全自动反冲洗过滤器电缆', remark: '控制器-自动反冲洗'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型位移传感器'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型压力传感器'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型红外发射器'),
|
|
|
|
SaleQuotationItemModel(name: '矿用本安型LED信号灯'),
|
|
|
|
SaleQuotationItemModel(name: '倾角传感器'),
|
|
|
|
SaleQuotationItemModel(name: '各类安装附件'),
|
|
|
|
];
|
2024-04-02 16:22:21 +08:00
|
|
|
list.assignAll(newList
|
|
|
|
.where((element) => PinyinHelper.getPinyin(element.name, separator: '')
|
|
|
|
.contains(searchKey.value))
|
|
|
|
.toList());
|
2024-04-02 12:24:08 +08:00
|
|
|
return newList;
|
|
|
|
}
|
2024-04-01 17:35:34 +08:00
|
|
|
}
|