Cui Zhi Feng
2024-08-28 9005cfeca43a3f661fe67158753d5c7febdac15b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
package com.mzl.flower.service.payment;
 
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mzl.flower.constant.Constants;
import com.mzl.flower.entity.flower.FlowerSupplierSaleNum;
import com.mzl.flower.entity.payment.OrderItem;
import com.mzl.flower.entity.payment.OrderItemCheck;
import com.mzl.flower.entity.payment.OrderItemSales;
import com.mzl.flower.entity.payment.OrderItemSettlement;
import com.mzl.flower.entity.supplier.Station;
import com.mzl.flower.mapper.flower.FlowerSupplierSaleNumMapper;
import com.mzl.flower.mapper.payment.*;
import com.mzl.flower.mapper.supplier.StationMapper;
import com.mzl.flower.service.BaseService;
import com.mzl.flower.utils.UUIDGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;
 
 
@Slf4j
@Service
@Transactional
public class OrderItemSettlementService extends BaseService {
 
    @Autowired
    private OrderMapper orderMapper;
 
    @Autowired
    private OrderItemMapper orderItemMapper;
 
    @Autowired
    private OrderItemCheckMapper orderItemCheckMapper;
 
    @Autowired
    private OrderItemSalesMapper orderItemSalesMapper;
 
    @Autowired
    private StationMapper stationMapper;
 
    @Autowired
    private FlowerSupplierSaleNumMapper saleNumMapper;
 
    @Autowired
    private OrderItemSettlementMapper orderItemSettlementMapper;
 
    public void createItemSettlement(OrderItem oi){
        OrderItemSettlement ois = new OrderItemSettlement();
        ois.setId(UUIDGenerator.getUUID());
        ois.setOrderItemId(oi.getId());
        ois.setOrderId(oi.getOrderId());
        ois.setCheckNum(0);
        ois.setCheckFee(new BigDecimal(0));
        ois.setReplaceNum(0);
        ois.setReplaceFee(new BigDecimal(0));
        ois.setLackNum(0);
        ois.setLackFeeSupplier(new BigDecimal(0));
        ois.setLackFeePartner(new BigDecimal(0));
        ois.setLackFeePlatform(new BigDecimal(0));
        ois.setServiceFeeRate(getFeeRate(oi));
        ois.setServiceFee(getServiceFee(oi, 0, 0, ois.getServiceFeeRate()));
        ois.setStationFee(getStationFee(oi, 0, 0));
        ois.setSalesFeePlatform(new BigDecimal(0));
        ois.setSalesFeePartner(new BigDecimal(0));
        ois.setSalesFeeSupplier(new BigDecimal(0));
 
        setSupplierIncome(oi, ois);
        setPartnerIncome(oi, ois);
 
        ois.create("sys");
        orderItemSettlementMapper.insert(ois);
    }
 
    public void saveItemSettlementInfo(List<String> orderIds){//在结算前使用
        List<OrderItem> ls = orderItemMapper.selectList(new QueryWrapper<OrderItem>()
                .in("order_id", orderIds));
        if(ls != null && ls.size() > 0){
            for(OrderItem oi : ls){
                saveItemSettlementInfo(oi, "sys", Constants.S_TYPE.ALL);
            }
        }
    }
 
    public void saveItemSettlementInfo(OrderItem oi, String userId, Constants.S_TYPE sType){
        String orderItemId = oi.getId();
        OrderItemSettlement ois = orderItemSettlementMapper.selectOne(new QueryWrapper<OrderItemSettlement>()
                .eq("order_item_id", orderItemId));
        boolean isCreate = false;
        if(ois == null){
            isCreate = true;
            ois = new OrderItemSettlement();
            ois.setId(UUIDGenerator.getUUID());
            ois.setOrderItemId(orderItemId);
            ois.setOrderId(oi.getOrderId());
        }
 
        if (Constants.S_TYPE.CHECK.equals(sType) || Constants.S_TYPE.ALL.equals(sType)) {
            List<OrderItemCheck> orderItemCheckList = orderItemCheckMapper.selectList(new QueryWrapper<OrderItemCheck>()
                    .eq("order_item_id", orderItemId)
                    .eq("audit_status", Constants.CHECK_AUDIT_STATUS.AGREED.name()));
            int checkNum = 0;//降级数量
            BigDecimal checkFee = new BigDecimal(0);//降级扣款
            int replaceNum = 0;//补货数量
            BigDecimal replaceFee = new BigDecimal(0);//补货扣款
            int lackNum = 0;//缺货数量
            BigDecimal lackFeeSupplier = new BigDecimal(0);//缺货扣款
            BigDecimal lackFeePartner = new BigDecimal(0);//缺货扣款
            BigDecimal lackFeePlatform = new BigDecimal(0);//缺货扣款
            if (orderItemCheckList != null && orderItemCheckList.size() > 0) {
                for (OrderItemCheck c : orderItemCheckList) {
                    Integer num = c.getNum();
                    BigDecimal amount = c.getDeductAmount();
                    String type = c.getType();
                    if (Constants.CHECK_TYPE.reduce.name().equals(type)) {
                        checkNum = num == null ? 0 : num;
                        checkFee = amount == null ? new BigDecimal(0) : amount;
                    } else if (Constants.CHECK_TYPE.lack.name().equals(type)) {
                        lackNum = num == null ? 0 : num;
                        lackFeeSupplier = oi.getSupplierPrice().multiply(new BigDecimal(lackNum));
 
                        BigDecimal markupPartner = oi.getMarkupPartner() == null ? new BigDecimal(0) : oi.getMarkupPartner();
                        lackFeePartner = markupPartner.multiply(new BigDecimal(lackNum));
 
                        lackFeePlatform = oi.getMarkupOne().multiply(new BigDecimal(lackNum));
                        lackFeePlatform = lackFeePlatform.add(oi.getMarkupTwo().multiply(new BigDecimal(lackNum)));
                    } else if (Constants.CHECK_TYPE.replace.name().equals(type)) {
                        replaceNum = num == null ? 0 : num;
                        replaceFee = amount == null ? new BigDecimal(0) : amount;
                    }
                }
            }
            ois.setCheckNum(checkNum);
            ois.setCheckFee(checkFee);
            ois.setReplaceNum(replaceNum);
            ois.setReplaceFee(replaceFee);
            ois.setLackNum(lackNum);
            ois.setLackFeePartner(lackFeePartner);
            ois.setLackFeeSupplier(lackFeeSupplier);
            ois.setLackFeePlatform(lackFeePlatform);
 
            Double serviceFeeRate = ois.getServiceFeeRate();
            if (serviceFeeRate == null) {
                ois.setServiceFeeRate(getFeeRate(oi));
            }
            ois.setServiceFee(getServiceFee(oi, replaceNum, lackNum, ois.getServiceFeeRate()));
 
            ois.setStationFee(getStationFee(oi, replaceNum, lackNum));
        }
 
        //售后计算
        if (Constants.S_TYPE.SALES.equals(sType) || Constants.S_TYPE.ALL.equals(sType)) {
            List<OrderItemSales> ls = orderItemSalesMapper.selectList(new QueryWrapper<OrderItemSales>()
                    .eq("order_item_id", oi.getId())
                    .eq("status", Constants.ORDER_SALES_STATUS.AGREED.name())
            );
            BigDecimal salesFeePlatform = new BigDecimal(0);//平台售后费用
            BigDecimal salesFeeSupplier = new BigDecimal(0);//供应商售后费用
            BigDecimal salesFeePartner = new BigDecimal(0);//合伙人售后费用
            if (ls != null && ls.size() > 0) {
                for (OrderItemSales s : ls) {
                    BigDecimal feeSupplier = s.getFeeSupplier();
                    BigDecimal feePartner = s.getFeePartner();
                    BigDecimal feePlatform = s.getFeePlatform();
                    BigDecimal feePlatformPack = s.getFeePlatformPack();
                    BigDecimal feePlatformCheck = s.getFeePlatformCheck();
                    BigDecimal feePlatformTransport = s.getFeePlatformTransport();
                    salesFeePlatform = salesFeePlatform.add(feePlatform)
                            .add(feePlatformPack).add(feePlatformCheck).add(feePlatformTransport);
                    salesFeeSupplier = salesFeeSupplier.add(feeSupplier);
                    salesFeePartner = salesFeePartner.add(feePartner);
                }
            }
            ois.setSalesFeePlatform(salesFeePlatform);
            ois.setSalesFeeSupplier(salesFeeSupplier);
            ois.setSalesFeePartner(salesFeePartner);
        }
 
        setSupplierIncome(oi, ois);
        setPartnerIncome(oi, ois);
 
        if(isCreate){
            ois.create(userId);
            orderItemSettlementMapper.insert(ois);
        } else {
            ois.update(userId);
            orderItemSettlementMapper.updateById(ois);
        }
    }
 
    private double getFeeRate(OrderItem oi){
        String yearMonth = format(LocalDateTime.now().plusMonths(-1), "yyyy-MM");
        FlowerSupplierSaleNum saleNum = saleNumMapper.selectOne(new QueryWrapper<FlowerSupplierSaleNum>()
                .eq("`year_month`", yearMonth).eq("supplier_id", oi.getSupplierId()));
        double serviceFeeRate = 0D;
        if (saleNum != null) {
            serviceFeeRate = saleNum.getServiceFeeRate() == null ? 0D : saleNum.getServiceFeeRate();
        }
 
        return serviceFeeRate;
    }
 
    private void setSupplierIncome(OrderItem oi, OrderItemSettlement ois){
        //供应商结算:商品价格-扣款-理赔-运费-服务费 = 结算金额
        //扣款包含:降级扣款、缺货扣款和补货扣款
        BigDecimal totalAmount = oi.getSupplierPrice().multiply(new BigDecimal(oi.getNum()));
        BigDecimal settlementAmount = totalAmount.subtract(ois.getCheckFee()).subtract(ois.getLackFeeSupplier())
                .subtract(ois.getReplaceFee()).subtract(ois.getSalesFeeSupplier())
                .subtract(ois.getStationFee()).subtract(ois.getServiceFee());//结算金额
        if(settlementAmount.doubleValue() < 0){
            settlementAmount = new BigDecimal(0);
        }
        ois.setIncomeSupplier(settlementAmount);
    }
 
    private void setPartnerIncome(OrderItem oi, OrderItemSettlement ois){
        //合伙人结算:合伙人加价-理赔-缺货扣款 = 结算金额
        BigDecimal markupPartner = oi.getMarkupPartner() == null ? new BigDecimal(0) : oi.getMarkupPartner();
        BigDecimal totalAmount = markupPartner.multiply(new BigDecimal(oi.getNum()));
        BigDecimal settlementAmount = totalAmount.subtract(ois.getSalesFeePartner()).subtract(ois.getLackFeePartner());//结算金额
        if(settlementAmount.doubleValue() < 0){
            settlementAmount = new BigDecimal(0);
        }
        ois.setIncomePartner(settlementAmount);
    }
 
    private BigDecimal getServiceFee(OrderItem oi, int replaceNum, int lackNum, double serviceFeeRate){
        int num = oi.getNum() - replaceNum - lackNum;
        if(num <= 0){
            return new BigDecimal(0);
        }
        BigDecimal totalAmount = oi.getSupplierPrice().multiply(new BigDecimal(num));
 
        return totalAmount.multiply(new BigDecimal(serviceFeeRate))
                .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
    }
 
    private BigDecimal getStationFee(OrderItem oi, int replaceNum, int lackNum){
        Long stationId = oi.getStationId();
        BigDecimal fee = new BigDecimal(0);
        if(stationId != null) {//集货站运费按每扎算
            Station station = stationMapper.selectById(stationId);
            if(station != null && station.getFreight() != null){
                int num = oi.getNum() - replaceNum - lackNum;
                if(num > 0) {
                    fee = station.getFreight().multiply(new BigDecimal(num));
                }
            }
        }
 
        return fee;
    }
}