cloudroam
3 天以前 3a819e4f668c15e8b77b188b322470da12bb7a43
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
package com.mzl.flower.service.payment;
 
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mzl.flower.config.exception.ValidationException;
import com.mzl.flower.constant.Constants;
import com.mzl.flower.dto.request.payment.BillQueryDTO;
import com.mzl.flower.dto.response.payment.BillDTO;
import com.mzl.flower.dto.response.payment.BillListDTO;
import com.mzl.flower.entity.payment.*;
import com.mzl.flower.mapper.payment.*;
import com.mzl.flower.service.BaseService;
import com.mzl.flower.utils.UUIDGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
 
@Slf4j
@Service
@Transactional
public class BillService extends BaseService {
 
    @Autowired
    private BillMapper billMapper;
 
    @Autowired
    private OrderService orderService;
 
    @Autowired
    private OrderMapper orderMapper;
 
    @Autowired
    private OrderItemMapper orderItemMapper;
 
    @Autowired
    private OrderItemSalesMapper orderItemSalesMapper;
 
    @Autowired
    private OrderItemSettlementMapper orderItemSettlementMapper;
 
    public Page<BillListDTO> selectBillList(Page page, BillQueryDTO dto){
        dto.setStart(parseLocalDate(dto.getStartDate()));
        dto.setEnd(parseLocalDate(dto.getEndDate()));
 
        List<BillListDTO> ls = billMapper.selectBillList(page, dto);
 
        page.setRecords(ls);
 
        return page;
    }
 
    public BillListDTO getBillStatistics(BillQueryDTO dto){
        dto.setStart(parseLocalDate(dto.getStartDate()));
        dto.setEnd(parseLocalDate(dto.getEndDate()));
 
        List<BillListDTO> ls = billMapper.selectBillList(null, dto);
        BillListDTO r = new BillListDTO();
        if(ls != null && ls.size() > 0){
            for(BillListDTO b : ls){
                r.setNum(r.getNum() + b.getNum());
                r.setOrderAmount(r.getOrderAmount().add(b.getOrderAmount()));
                r.setSupplierAmount(r.getSupplierAmount().add(b.getSupplierAmount()));
                r.setPackingFee(r.getPackingFee().add(b.getPackingFee()));
                r.setTransportFee(r.getTransportFee().add(b.getTransportFee()));
                r.setMarkupOne(r.getMarkupOne().add(b.getMarkupOne()));
                r.setMarkupTwo(r.getMarkupTwo().add(b.getMarkupTwo()));
                r.setMarkupPartner(r.getMarkupPartner().add(b.getMarkupPartner()));
                r.setDeductAmount(r.getDeductAmount().add(b.getDeductAmount()));
                r.setSalesAmount(r.getSalesAmount().add(b.getSalesAmount()));
                r.setProfitAmount(r.getProfitAmount().add(b.getProfitAmount()));
                r.setMemberCouponAmount(r.getMemberCouponAmount().add(b.getMemberCouponAmount()));
            }
        }
 
        return r;
    }
 
    public BillDTO getBill(String id){
        Bill bill = billMapper.selectById(id);
        if(bill == null){
            throw new ValidationException("账单不存在");
        }
 
        BillDTO dto = new BillDTO();
        BeanUtils.copyProperties(bill, dto);
 
        /*OrderQueryDTO q = new OrderQueryDTO();
        q.setBillId(id);
        List<OrderListDTO> orders = orderService.getOrderList(null, q);
        dto.setOrders(orders);*/
 
        return dto;
    }
 
    public void generateBill(LocalDate date){
        int count = billMapper.selectCount(new QueryWrapper<Bill>().eq("bill_date", date).eq("deleted", 0));
        if(count > 0){
            log.warn(date + "已生成账单");
            return;
        }
        LocalDateTime startTime = date.atTime(0, 0, 0);
        LocalDateTime endTime = startTime.plusDays(1);
        List<Order> ls = orderMapper.getOrderForBill(startTime, endTime);
        if(ls == null || ls.size() == 0){
            log.warn(date + "无任何已收货订单");
            return;
        }
 
        List<String> orderIdsAll = new ArrayList<>();
        List<String> orderIdsPartner = new ArrayList<>();
        List<String> orderIdsPersonal = new ArrayList<>();
        Map<String, Order> orderMap = new HashMap<>();
        for(Order o : ls){
            String orderId = o.getId();
            orderIdsAll.add(orderId);
            orderMap.put(orderId, o);
 
            Long partnerId = o.getPartnerId();
            if(partnerId != null){
                orderIdsPartner.add(orderId);
            } else {
                orderIdsPersonal.add(orderId);
            }
        }
 
        List<OrderItem> orderItems = orderItemMapper.selectList(new QueryWrapper<OrderItem>()
                .in("order_id", orderIdsAll));
        Map<String, List<OrderItem>> orderItemMap = new HashMap<>();
        for(OrderItem oi : orderItems){
            String orderId = oi.getOrderId();
            List<OrderItem> items = orderItemMap.computeIfAbsent(orderId, k -> new ArrayList<>());
            items.add(oi);
        }
 
        //账单售后
        /*List<OrderItemSales> sLs = orderItemSalesMapper.selectList(new QueryWrapper<OrderItemSales>()
                .in("order_id", orderIdsAll));*/
        List<OrderItemSettlement> sLs = orderItemSettlementMapper.selectList(new QueryWrapper<OrderItemSettlement>()
                .in("order_id", orderIdsAll));
        Map<String, BigDecimal> salesMap = new HashMap<>();
        Map<String, BigDecimal> deductMap = new HashMap<>();
        if(sLs != null && sLs.size() > 0){
            for(OrderItemSettlement s : sLs){//同一个订单的同一个商品可能会多次理赔
                salesMap.put(s.getOrderItemId(), s.getSalesFeePlatform());
                deductMap.put(s.getOrderItemId(), s.getLackFeePlatform());
            }
        }
 
 
        String type = Constants.BILL_TYPE.partner.name();//账单类型
        calculate(date, type, orderIdsPartner, orderMap, orderItemMap, salesMap, deductMap);
 
        type = Constants.BILL_TYPE.personal.name();//账单类型
        calculate(date, type, orderIdsPersonal, orderMap, orderItemMap, salesMap, deductMap);
    }
 
    public Bill calculate(LocalDate date, String type, List<String> orderIds, Map<String, Order> orderMap
            , Map<String, List<OrderItem>> orderItemMap, Map<String, BigDecimal> salesMap
            , Map<String, BigDecimal> deductMap){
        Bill bill = new Bill();
        bill.setId(UUIDGenerator.getUUID());
 
        BigDecimal orderAmount = new BigDecimal(0);//花款(售价)
        BigDecimal supplierAmount = new BigDecimal(0);//花款(底价)
        Integer num = 0;//发货数
        BigDecimal packingFee = new BigDecimal(0);//打包费
        BigDecimal transportFee = new BigDecimal(0);//运费
        BigDecimal markupOne = new BigDecimal(0);//区间加价
        BigDecimal markupTwo = new BigDecimal(0);//二次加价
        BigDecimal markupPartner = new BigDecimal(0);//合伙人加价
        BigDecimal deductAmount = new BigDecimal(0);//质检退款(缺货)
        BigDecimal salesAmount = new BigDecimal(0);//售后退款
        BigDecimal memberCouponAmount = new BigDecimal(0);//优惠券金额
        for(String orderId : orderIds){
            Order o = orderMap.get(orderId);
            orderAmount = orderAmount.add(o.getTotalAmount());
            packingFee = packingFee.add(o.getPackingFee());
            transportFee = transportFee.add(o.getTransportFee());
            List<OrderItem> items = orderItemMap.get(orderId);
            for(OrderItem oi : items){
                Integer n = oi.getNum();
                supplierAmount = supplierAmount.add(oi.getSupplierPrice().multiply(new BigDecimal(n)));
                markupOne = markupOne.add(getAmount(oi.getMarkupOne()).multiply(new BigDecimal(n)));
                markupTwo = markupTwo.add(getAmount(oi.getMarkupTwo()).multiply(new BigDecimal(n)));
                markupPartner = markupPartner.add(getAmount(oi.getMarkupPartner()).multiply(new BigDecimal(n)));
 
                salesAmount = salesAmount.add(getAmount(salesMap.get(oi.getId())));
                deductAmount = deductAmount.add(getAmount(deductMap.get(oi.getId())));
                num += n;
            }
 
            memberCouponAmount = memberCouponAmount.add(getAmount(o.getMemberCouponAmount()));
 
            o.setBillId(bill.getId());
            orderMapper.updateById(o);
        }
 
        bill.setType(type);
        bill.setOrderAmount(orderAmount);
        bill.setSupplierAmount(supplierAmount);
        bill.setNum(num);
        bill.setPackingFee(packingFee);
        bill.setTransportFee(transportFee);
        bill.setMarkupOne(markupOne);
        bill.setMarkupTwo(markupTwo);
        bill.setMarkupPartner(markupPartner);
        bill.setDeductAmount(deductAmount);
        bill.setSalesAmount(salesAmount);
        bill.setMemberCouponAmount(memberCouponAmount);
        bill.setBillDate(date);
 
        //合伙人:利润=售价-底价(花农上架价格)-打包、运费(订单管理手输)-合伙人加价-平台罚款-质检(缺货)-优惠券
        //散户:利润=售价-底价(花农上架价格)-运费-平台罚款-质检(缺货)-优惠券
        //其实都一样的计算方式
        BigDecimal profitAmount = orderAmount.subtract(supplierAmount)
                .subtract(markupPartner).subtract(salesAmount).subtract(packingFee).subtract(transportFee)
                .subtract(deductAmount).subtract(memberCouponAmount);//利润合计
        bill.setProfitAmount(profitAmount);
 
        bill.create();
 
        billMapper.insert(bill);
 
        return bill;
    }
}