|
@@ -9,23 +9,27 @@ class OrderService extends CrudService {
|
|
|
constructor(ctx) {
|
|
|
super(ctx, 'order');
|
|
|
this.orderModel = this.ctx.model.Trade.Order;
|
|
|
+ this.platformActModel = this.ctx.model.System.PlatformAct;
|
|
|
+ this.gjaModel = this.ctx.model.Shop.GoodsJoinAct;
|
|
|
}
|
|
|
|
|
|
// #region 下单前计算函数
|
|
|
/**
|
|
|
* 计算每个店铺的价格
|
|
|
- * @param {Array} list 按店铺分组的商品列表
|
|
|
* list是经过 getPageData 处理过的数据
|
|
|
- * @param {String} type 订单类型码: 0常规单,1团购单
|
|
|
+ * @param {Array} list 按店铺分组的商品列表
|
|
|
*/
|
|
|
- makeOrder_computedShopTotal(list, type = '0') {
|
|
|
- let sell_money_key;
|
|
|
- if (type === '1') sell_money_key = 'group_sell_money';
|
|
|
- else sell_money_key = 'sell_money';
|
|
|
+ makeOrder_computedShopTotal(list) {
|
|
|
for (const i of list) {
|
|
|
- i.goods = i.goods.map((e) => ({ ...e, price: _.get(e, sell_money_key) }));
|
|
|
- i.goods_total = i.goods.reduce((p, n) => this.ctx.plus(p, this.ctx.multiply(_.get(n, sell_money_key), n.num)), 0);
|
|
|
- i.freight_total = i.goods.reduce((p, n) => this.ctx.plus(p, this.ctx.multiply(n.freight, n.num)), 0);
|
|
|
+ let goods_total = 0,
|
|
|
+ freight_total = 0;
|
|
|
+ for (const g of i.goods) {
|
|
|
+ // 如果有特价,那就使用特价,没有特价就是用正常销售价
|
|
|
+ goods_total = this.ctx.plus(goods_total, _.get(g, 'price'));
|
|
|
+ freight_total = this.ctx.plus(freight_total, _.get(g, 'freight'));
|
|
|
+ }
|
|
|
+ i.goods_total = goods_total;
|
|
|
+ i.freight_total = freight_total;
|
|
|
}
|
|
|
return list;
|
|
|
}
|
|
@@ -57,7 +61,7 @@ class OrderService extends CrudService {
|
|
|
// 解除店铺层
|
|
|
const sd = Object.values(detail);
|
|
|
// 取出规格层
|
|
|
- const sgd = sd.map((i) => Object.values(i));
|
|
|
+ const sgd = sd.map(i => Object.values(i));
|
|
|
// 将规格明细降维至一维
|
|
|
const oneLevel = _.flattenDeep(sgd);
|
|
|
// 根据订单类型,计算应付(优惠券部分已经按订单类型计算并分配完了.这地方只是复现)
|
|
@@ -174,6 +178,195 @@ class OrderService extends CrudService {
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
+ /**
|
|
|
+ * 检查商品是否满足加价购
|
|
|
+ * @param {Array} goodsList 平铺的商品列表
|
|
|
+ * @param {Array} actList 活动
|
|
|
+ */
|
|
|
+ async dealAct_plus(goodsList, actList) {
|
|
|
+ for (const act of actList) {
|
|
|
+ const { platform_act, plus_money } = act;
|
|
|
+ const goodsInAct = await this.getGoodsInAct(goodsList, platform_act);
|
|
|
+ // 没有有关活动的商品,直接下个活动
|
|
|
+ if (goodsInAct.length <= 0) continue;
|
|
|
+ const total = goodsInAct.reduce((p, n) => {
|
|
|
+ const rp = this.getGoodsPayAfterAct(n);
|
|
|
+ return this.ctx.plus(p, rp);
|
|
|
+ }, 0);
|
|
|
+ // 商品,优惠过后的金额,大于等于 活动下限:活动可以进行
|
|
|
+ if (this.ctx.minus(total, plus_money) >= 0) act.activity = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置商品特价部分
|
|
|
+ * @param {Array} goodsList 平铺的商品列表
|
|
|
+ * @param {Array} actList 活动
|
|
|
+ */
|
|
|
+ dealAct_sp(goodsList, actList) {
|
|
|
+ for (const act of actList) {
|
|
|
+ const { spec, sp_price } = act;
|
|
|
+ if (!spec) continue;
|
|
|
+ const goods = goodsList.find(f => f.goodsSpec_id === spec);
|
|
|
+ if (goods) {
|
|
|
+ // 默认特价为商品金额
|
|
|
+ goods.sp_price = sp_price;
|
|
|
+ goods.price = sp_price;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 商品满减/折处理:主要区分在于 将折扣转换为金额,剩下都是按比例分配
|
|
|
+ * @param {Array} goodsList 平铺的商品列表
|
|
|
+ * @param {Array} actList 活动
|
|
|
+ */
|
|
|
+ async dealAct_discount(goodsList, actList) {
|
|
|
+ for (const act of actList) {
|
|
|
+ const { discount = [], platform_act, platform_act_type } = act;
|
|
|
+ // 整理出区间
|
|
|
+ const range = this.getDiscountRange(discount);
|
|
|
+ // 找到在当前活动的商品
|
|
|
+ const goodsInAct = await this.getGoodsInAct(goodsList, platform_act);
|
|
|
+ if (goodsInAct.length <= 0) continue;
|
|
|
+ // 计算总价格够不够线(因为活动有优先级问题,如果发生满减够, 而满减之后的价格就不足以满折, 那就不给满折,所以要重新计算)
|
|
|
+ const total = goodsInAct.reduce((p, n) => {
|
|
|
+ const rp = this.getGoodsPayAfterAct(n);
|
|
|
+ return this.ctx.plus(p, rp);
|
|
|
+ }, 0);
|
|
|
+ for (const r of range) {
|
|
|
+ const { ls, le, number, max } = r;
|
|
|
+ let res = false;
|
|
|
+ if (ls && le) res = _.inRange(total, ls, le);
|
|
|
+ else if (ls && !le) res = this.ctx.minus(total, ls) >= 0;
|
|
|
+ if (res) {
|
|
|
+ // 在区间中,处理钱的问题.
|
|
|
+ // 按比例分配金额; 分配完后,结果统一放回原数据中
|
|
|
+ const actResult = [];
|
|
|
+ let discountTotal = number;
|
|
|
+ if (platform_act_type === '6') {
|
|
|
+ // 满折:因为输入的是折扣,所以需要将折扣转换成具体金额,然后与优惠上限对比,决定最后优惠总金额
|
|
|
+ const dp = this.ctx.minus(1, this.ctx.divide(number, 10));
|
|
|
+ // 计算优惠的金额
|
|
|
+ discountTotal = this.ctx.multiply(dp, total);
|
|
|
+ // 如果超出上限,则使用上限值作为优惠金额
|
|
|
+ if (_.isNumber(max)) {
|
|
|
+ if (this.ctx.minus(discountTotal, max) > 0) discountTotal = max;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (const gia of goodsInAct) {
|
|
|
+ const { goodsSpec_id } = gia;
|
|
|
+ // 不是最后一个
|
|
|
+ if (!_.isEqual(gia, _.last(goodsInAct))) {
|
|
|
+ const rp = this.getGoodsPayAfterAct(gia);
|
|
|
+ const percent = this.ctx.divide(rp, total);
|
|
|
+ const money = this.ctx.multiply(percent, discountTotal);
|
|
|
+ actResult.push({ platform_act, money, goodsSpec_id });
|
|
|
+ } else {
|
|
|
+ const allready = actResult.reduce((p, n) => this.ctx.plus(p, n.money), 0);
|
|
|
+ const el = this.ctx.minus(discountTotal, allready);
|
|
|
+ actResult.push({ platform_act, money: el, goodsSpec_id });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 修改数据
|
|
|
+ for (const i of actResult) {
|
|
|
+ const { goodsSpec_id, ...others } = i;
|
|
|
+ const r = goodsList.find(f => f.goodsSpec_id === goodsSpec_id);
|
|
|
+ if (r) {
|
|
|
+ const { act = [] } = r;
|
|
|
+ act.push(others);
|
|
|
+ r.act = act;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 修改活动数据
|
|
|
+ const text = `满${platform_act_type === '6' ? '折' : '减'}活动`;
|
|
|
+ const actData = await this.platformActModel.findById(platform_act);
|
|
|
+ act.title = _.get(actData, 'act_time.title', text);
|
|
|
+ act.discount = actResult.reduce((p, n) => this.ctx.plus(p, n.money), 0);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 商品买赠处理
|
|
|
+ * @param {Array} goodsList 平铺的商品列表
|
|
|
+ * @param {Array} actList 活动
|
|
|
+ */
|
|
|
+ async dealAct_gift(goodsList, actList) {
|
|
|
+ for (const act of actList) {
|
|
|
+ const { spec, gift, platform_act } = act;
|
|
|
+ const goodsInAct = await this.getGoodsInAct(goodsList, platform_act);
|
|
|
+ const actResult = [];
|
|
|
+ for (const goods of goodsInAct) {
|
|
|
+ const { goodsSpec_id } = goods;
|
|
|
+ if (spec === goodsSpec_id) actResult.push({ platform_act, gift, goodsSpec_id });
|
|
|
+ }
|
|
|
+ for (const i of actResult) {
|
|
|
+ const { goodsSpec_id, ...others } = i;
|
|
|
+ const r = goodsList.find(f => f.goodsSpec_id === goodsSpec_id);
|
|
|
+ if (r) {
|
|
|
+ const { act = [] } = r;
|
|
|
+ act.push(others);
|
|
|
+ r.act = act;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查看商品是否在活动中
|
|
|
+ * @param {Array} goodsList 平铺商品列表
|
|
|
+ * @param {String} platform_act 活动id
|
|
|
+ */
|
|
|
+ async getGoodsInAct(goodsList, platform_act) {
|
|
|
+ const num = await this.platformActModel.count({ _id: platform_act, is_use: '0' });
|
|
|
+ if (num <= 0) return [];
|
|
|
+ // 查询商品是否参与活动
|
|
|
+ const goodsInAct = [];
|
|
|
+ for (const goods of goodsList) {
|
|
|
+ const { goodsSpec_id } = goods;
|
|
|
+ const gnum = await this.gjaModel.count({ 'spec._id': goodsSpec_id, platform_act });
|
|
|
+ if (gnum <= 0) continue;
|
|
|
+ goodsInAct.push(goods);
|
|
|
+ }
|
|
|
+ return goodsInAct;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 获取商品经活动后实付的价格
|
|
|
+ * @param {Object} goods 平铺的商品数据
|
|
|
+ */
|
|
|
+ getGoodsPayAfterAct(goods) {
|
|
|
+ const { act = [], price } = goods;
|
|
|
+ const actDiscount = act.reduce((p, n) => this.ctx.plus(p, n.money), 0);
|
|
|
+ const rp = this.ctx.minus(price, actDiscount);
|
|
|
+ return rp;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取满减/折区间范围
|
|
|
+ * @param {Array} discount 满减/折阶梯设置
|
|
|
+ */
|
|
|
+ getDiscountRange(discount) {
|
|
|
+ const range = [];
|
|
|
+ for (let i = 0; i < discount.length; i++) {
|
|
|
+ const e1 = _.get(discount, i);
|
|
|
+ const e2 = _.get(discount, i + 1);
|
|
|
+ if (e1 && e2) {
|
|
|
+ const { limit: ls, number, max } = e1;
|
|
|
+ const { limit: le } = e2;
|
|
|
+ const obj = { ls: this.ctx.toNumber(ls), le: this.ctx.toNumber(le), number: this.ctx.toNumber(number) };
|
|
|
+ if (max) obj.max = max;
|
|
|
+ range.push(obj);
|
|
|
+ } else if (e1 && !e2) {
|
|
|
+ const { limit: ls, number, max } = e1;
|
|
|
+ const obj = { ls: this.ctx.toNumber(ls), number: this.ctx.toNumber(number) };
|
|
|
+ if (max) obj.max = max;
|
|
|
+ range.push(obj);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return range;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
module.exports = OrderService;
|