class PriceManager {

    public PriceProductCalcRespDTO calcProductPrice(PriceProductCalcReqDTO calcReqDTO) {
        // TODO 芋艿，补充一些表单校验。例如说，需要传入用户编号。
        // 校验商品都存在
        Map<Integer, PriceProductCalcReqDTO.Item> calcProductItemDTOMap = CollectionUtils.convertMap(
                calcReqDTO.getItems(), PriceProductCalcReqDTO.Item::getSkuId);
        CommonResult<List<ProductSkuRespDTO>> listProductSkusResult = productSkuRpc.listProductSkus(
                new ProductSkuListQueryReqDTO().setProductSkuIds(calcProductItemDTOMap.keySet()));
        listProductSkusResult.checkError();
        if (calcReqDTO.getItems().size() != listProductSkusResult.getData().size()) {
            throw ServiceExceptionUtil.exception(PRICE_PRODUCT_SKU_NOT_EXISTS);
        }
        // TODO 库存相关
        // 查询促销活动
        List<PromotionActivityRespDTO> activityRespDTOs = promotionActivityService.listPromotionActivitiesBySpuIds(
                CollectionUtils.convertSet(listProductSkusResult.getData(), ProductSkuRespDTO::getSpuId),
                Collections.singleton(PromotionActivityStatusEnum.RUN.getValue()));
        // 拼装结果（主要是计算价格）
        PriceProductCalcRespDTO calcRespDTO = new PriceProductCalcRespDTO();
        // 1. 创建初始的每一项的数组
        List<PriceProductCalcRespDTO.Item> calcItemRespDTOs = this.initCalcOrderPriceItems(
                listProductSkusResult.getData(), calcProductItemDTOMap);
        // 2. 计算【限时折扣】促销
        this.modifyPriceByTimeLimitDiscount(calcItemRespDTOs, activityRespDTOs);
        // 3. 计算【满减送】促销
        List<PriceProductCalcRespDTO.ItemGroup> itemGroups = this.groupByFullPrivilege(calcItemRespDTOs, activityRespDTOs);
        calcRespDTO.setItemGroups(itemGroups);
        // 4. 计算优惠劵 TODO 芋艿：未详细测试；
        if (calcReqDTO.getCouponCardId() != null) {
            Integer result = this.modifyPriceByCouponCard(calcReqDTO.getUserId(), calcReqDTO.getCouponCardId(), itemGroups);
            calcRespDTO.setCouponCardDiscountTotal(result);
        }
        // 5. 计算最终的价格
        int buyTotal = 0;
        int discountTotal = 0;
        int presentTotal = 0;
        for (PriceProductCalcRespDTO.ItemGroup itemGroup : calcRespDTO.getItemGroups()) {
            buyTotal += itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getBuyTotal() : 0).sum();
            discountTotal += itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getDiscountTotal() : 0).sum();
            presentTotal += itemGroup.getItems().stream().mapToInt(item -> item.getSelected() ? item.getPresentTotal() : 0).sum();
        }
        Assert.isTrue(buyTotal - discountTotal ==  presentTotal,
                String.format("价格合计( %d - %d == %d )不正确", buyTotal, discountTotal, presentTotal));
        calcRespDTO.setFee(new PriceProductCalcRespDTO.Fee(buyTotal, discountTotal, 0, presentTotal));
        return calcRespDTO;
    }

}