package com.kmall.admin.utils; import com.kmall.admin.dto.GoodsDetailsDto; import com.kmall.admin.dto.GoodsDto; import com.kmall.admin.entity.GoodsEntity; import com.kmall.manager.manager.express.sf.ServiceException; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * xwh * 2020年12月7日14:57:04 */ public class CalculateTax { private static final Logger logger = LoggerFactory.getLogger(CalculateTax.class); private static List hsCodeList = new ArrayList<>(); private static Map hsCodeMap = new HashMap(); /* cus_goods_code 计税方式 3304990029 完税价格≥10元/克的,税率为15% 3304910000 完税价格≥10元/克的,税率为15% 3303000010 完税价格≥10元/克的,税率为15% 3303000020 完税价格≥10元/毫升的,税率为15% 3304100091 完税价格≥10元/克的,税率为15% 3304100092 完税价格≥10元/毫升的,税率为15% 3304100093 完税价格≥15元/片(张)的,税率为15% 3304200091 完税价格≥10元/克的,税率为15% 3304200092 完税价格≥10元/毫升的,税率为15% 3304200093 完税价格≥15元/片(张)的,税率为15% 3304300001 完税价格≥10元/克的,税率为15% 3304300002 完税价格≥10元/毫升的,税率为15% 3304300003 完税价格≥15元/片(张)的,税率为15% 3304990049 完税价格≥15元/片(张)的,税率为15% 3304990099 完税价格≥10元/克的,税率为15% 3304990039 完税价格≥10元/克的,税率为15% 9102190000 进口关税完税价格在10000人民币及以上时,税率为20% */ static { hsCodeMap.put("3304990029",new BigDecimal("10")); hsCodeMap.put("3304910000",new BigDecimal("10")); hsCodeMap.put("3303000010",new BigDecimal("10")); hsCodeMap.put("3303000020",new BigDecimal("10")); hsCodeMap.put("3304100091",new BigDecimal("10")); hsCodeMap.put("3304100092",new BigDecimal("10")); hsCodeMap.put("3304100093",new BigDecimal("15")); hsCodeMap.put("3304200091",new BigDecimal("10")); hsCodeMap.put("3304200092",new BigDecimal("10")); hsCodeMap.put("3304200093",new BigDecimal("15")); hsCodeMap.put("3304300001",new BigDecimal("10")); hsCodeMap.put("3304300002",new BigDecimal("10")); hsCodeMap.put("3304300003",new BigDecimal("15")); hsCodeMap.put("3304990049",new BigDecimal("15")); hsCodeMap.put("3304990099",new BigDecimal("10")); hsCodeMap.put("3304990039",new BigDecimal("10")); hsCodeMap.put("9102190000",new BigDecimal("10000")); } /** * 计算税费,包括消费税和增值税。公式如下: * 订单该商品总税费 = (商品消费税 + 商品增值税)* 0.7 * * @param * @return */ public static final BigDecimal calculateTax(GoodsEntity goodsEntity, BigDecimal actualPaymentAmount) { // 该商品消费税 BigDecimal grandConsumerTax = BigDecimal.ZERO; // 该商品增值税 BigDecimal grandValueAddTax = BigDecimal.ZERO; String hsCode = goodsEntity.getHsCode();// 海关商品编码 String hsCodeName = goodsEntity.getHsCodeName();// 海关商品编码名称 // 消费税税率 final BigDecimal impConsumTaxRate = goodsEntity.getImpConsumTaxRate(); // 增值税税率 final BigDecimal valueAddedTaxRate = goodsEntity.getValueAddedTaxRate(); try { // 计算某类产品的消费税 final BigDecimal subConsumerTax = calculateConsumerTax(actualPaymentAmount, impConsumTaxRate, hsCodeName, goodsEntity, actualPaymentAmount); // 计算某类产品的增值税 final BigDecimal subValueAddTax = calculateValueAddTax(actualPaymentAmount, valueAddedTaxRate, subConsumerTax); // 计算总的消费税 grandConsumerTax = grandConsumerTax.add(subConsumerTax); // 计算总的增值税 grandValueAddTax = grandValueAddTax.add(subValueAddTax); } catch (final RuntimeException e) { if (logger.isErrorEnabled()) logger.error("计算税费出错!请检查产品的分类数据,以及产品类别的税率数据!", e); throw new IllegalStateException("计算税费出错!请检查产品的分类数据,以及产品类别的税率数据!", e); } // 按照公式,打7折 final BigDecimal tax = grandConsumerTax.add(grandValueAddTax).multiply(new BigDecimal("0.7")).setScale(2, BigDecimal.ROUND_HALF_UP); return tax; } /** * 计算消费税,公式如下: * 消费税 = (明细商品总价 / (1-消费税税率)) * 消费税税率 * * @param productSubTotal 订单中的某类商品总价(单价 * 数量) * @param impConsumTaxRate 进口从价消费税率,百分数 * @param goodsEntity 商品备案信息 * @param productUnitPrice 产品销售单价 * @return 消费税 */ private static final BigDecimal calculateConsumerTax(final BigDecimal productSubTotal, final BigDecimal impConsumTaxRate, final String cusGoodsName, GoodsEntity goodsEntity, final BigDecimal productUnitPrice) { // 消费税税率为0,不做计算 if (impConsumTaxRate.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } BigDecimal taxRate = null; //计算化妆品, 需要计算单价 BigDecimal unit1Price = null; BigDecimal unit2Price = null; BigDecimal qty1 = goodsEntity.getLegalUnit1Qty(); BigDecimal qty2 = goodsEntity.getLegalUnit2Qty(); if (StringUtils.isNotBlank(cusGoodsName) && (cusGoodsName.contains("“片”") || cusGoodsName.contains("“张”") || cusGoodsName.contains("\"片\"") || cusGoodsName.contains("\"张\""))) { //片、张的单价 if (qty2 != null) { unit2Price = productUnitPrice.divide(qty2, 5, BigDecimal.ROUND_HALF_UP); } } else { //毫升、克的单价 if (qty1 != null) { BigDecimal gramOrMl = qty1.multiply(new BigDecimal(1000)); unit1Price = productUnitPrice.divide(gramOrMl, 5, BigDecimal.ROUND_HALF_UP); } } // 每单位价格 // 如果有片、张的单价,按片、张;如果没有则按毫升、克 BigDecimal gramOrMlUnitPrice = (unit2Price != null) ? unit2Price : unit1Price; //获取化妆品阀值 BigDecimal cosmThresholdValue = goodsEntity.getCosmThresholdValue(); if (cosmThresholdValue != null && cosmThresholdValue.compareTo(BigDecimal.ZERO) > 0) { if (gramOrMlUnitPrice != null) { //完税法定单位单价大于阈值采用第一档消费税率,否则消费税率为0 if (gramOrMlUnitPrice.compareTo(cosmThresholdValue) >= 0) { taxRate = impConsumTaxRate.divide(new BigDecimal("100"), 10, BigDecimal.ROUND_HALF_UP); } else { taxRate = BigDecimal.ZERO; } } else { String message = "【" + goodsEntity.getSku() + "】缺少法定单价"; logger.error(message); throw new ServiceException(message); } } // 每单位价格小于化妆品阀值,不做计算 if (taxRate.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } final BigDecimal tax = productSubTotal.divide(BigDecimal.ONE.subtract(taxRate), 10, BigDecimal.ROUND_HALF_UP).multiply(taxRate); return tax; } /** * 计算增值税,公式如下: * 增值税 = (明细商品总价 + 消费税) * 增值税税率 * * @param productSubTotal 订单中的某类商品总价(单价 * 数量) * @param valueAddedTaxRate 增值税率,百分数 * @param consumerTax 订单中的某类商品总的消费税 * @return 增值税 */ private static final BigDecimal calculateValueAddTax(final BigDecimal productSubTotal, final BigDecimal valueAddedTaxRate, final BigDecimal consumerTax) { final BigDecimal taxRate = valueAddedTaxRate.divide(new BigDecimal("100"), 10, BigDecimal.ROUND_HALF_UP); // 免税,不做计算 if (taxRate.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } final BigDecimal tax = productSubTotal.add(consumerTax).multiply(taxRate); return tax; } /** * 计算税率 * * @param * @return */ public static final BigDecimal calculateGoodsRate(GoodsEntity goodsEntity, BigDecimal actualPaymentAmount) { // 该商品消费税 BigDecimal grandConsumerTax = BigDecimal.ZERO; // 该商品增值税 BigDecimal grandValueAddTax = BigDecimal.ZERO; String hsCode = goodsEntity.getHsCode();// 海关商品编码 String hsCodeName = goodsEntity.getHsCodeName();// 海关商品编码名称 // 消费税税率 final BigDecimal impConsumTaxRate = goodsEntity.getImpConsumTaxRate(); // 增值税税率 final BigDecimal valueAddedTaxRate = goodsEntity.getValueAddedTaxRate(); try { // 计算某类产品的消费税 final BigDecimal subConsumerTax = calculateConsumerTax(actualPaymentAmount, impConsumTaxRate, hsCodeName, goodsEntity, actualPaymentAmount); // 计算某类产品的增值税 final BigDecimal subValueAddTax = calculateValueAddTax(actualPaymentAmount, valueAddedTaxRate, subConsumerTax); // 计算总的消费税 grandConsumerTax = grandConsumerTax.add(subConsumerTax); // 计算总的增值税 grandValueAddTax = grandValueAddTax.add(subValueAddTax); } catch (final RuntimeException e) { if (logger.isErrorEnabled()) logger.error("计算税费出错!请检查产品的分类数据,以及产品类别的税率数据!", e); throw new IllegalStateException("计算税费出错!请检查产品的分类数据,以及产品类别的税率数据!", e); } // 如果增值税为0,免税 if (BigDecimal.ZERO.compareTo(grandValueAddTax)==0){ return grandValueAddTax; } // 如果有消费税 23.06%=(0.13+0.15)/(1-0.15)*0.7 if (BigDecimal.ZERO.compareTo(grandConsumerTax)!=0){ return valueAddedTaxRate.add(impConsumTaxRate). divide(new BigDecimal(100).subtract(impConsumTaxRate),10, BigDecimal.ROUND_HALF_UP) .multiply(new BigDecimal("0.7")).setScale(4, BigDecimal.ROUND_HALF_UP); }else { // 如果没有消费税 9.1%=0.13*0.7 valueAddedTaxRate.multiply(new BigDecimal("0.7")).divide(new BigDecimal("100"),4,BigDecimal.ROUND_HALF_UP); } // 按照公式,打7折 final BigDecimal tax = grandConsumerTax.add(grandValueAddTax).multiply(new BigDecimal("0.7")).setScale(2, BigDecimal.ROUND_HALF_UP); return tax.divide(actualPaymentAmount, 4, BigDecimal.ROUND_HALF_UP); } /** * * 1.2.1 特殊化妆品(如下列举的“特殊化妆品SKU”),计算“消费税成分单价”: * 1.2.1.1 如果是片、张,优先使用片、张成分单价,没有,则按毫升、克成分单价为算税依据,二者成分单价计算公式如下: * 如果特殊化妆品内规格为“片”或“张”的化妆品,用第二数量按片、张计算成分单价:成分单价=销售单价/产品备案数据第二数量; * 其它的化妆品,用第一数量按毫升、克计算成分单价,成分单价=销售单价/(产品备案数据第一数量*1000); * 1.2.2 根据海关产品分类中“消费税成分单价收税阀值”,如果“消费税成分单价”大于等于“消费税成分单价收税阀值”,按产品分类消费税率作为算税依据,小于,则消费税率为0;无“消费税成分单价收税阀值”的,按产品分类消费税率作为算税依据: * 1.2.3 总计订单全部明细商品消费税; * @return */ public static BigDecimal calculateFinalTax(GoodsEntity goodsEntity,BigDecimal retailPrice){ GoodsEntity goods = null; GoodsDetailsDto goodsDetailsDto = null; // 判断商品的海关商品编码是否是在特殊化妆品里面 // 海关商品编码 String hsCode = goods.getHsCode(); // 商品税率 BigDecimal goodsRate = goods.getGoodsRate(); if(hsCodeMap.containsKey(hsCode)){ String cusGoodsName = goods.getHsCodeName(); // 法1 BigDecimal qty1 = goods.getLegalUnit1Qty(); // 法2 BigDecimal qty2 = goods.getLegalUnit2Qty(); // 阈值 BigDecimal cosmThresholdValue = goods.getCosmThresholdValue(); BigDecimal unit1Price = null; BigDecimal unit2Price = null; // 根据税后价计算出税前价 BigDecimal productUnitPrice = retailPrice ; // TODO 需要得到公式计算出税前价 if (StringUtils.isNotBlank(cusGoodsName) && (cusGoodsName.contains("“片”") || cusGoodsName.contains("“张”") || cusGoodsName.contains("片") || cusGoodsName.contains("张"))) { //片、张的单价 if (qty2 != null) { // 计算税额是否达到阈值 unit2Price = productUnitPrice.divide(qty2, 5, BigDecimal.ROUND_HALF_UP); } } else { //毫升、克的单价 if (qty1 != null) { BigDecimal gramOrMl = qty1.multiply(new BigDecimal(1000)); unit1Price = productUnitPrice.divide(gramOrMl, 5, BigDecimal.ROUND_HALF_UP); } } // 每单位价格 // 如果有片、张的单价,按片、张;如果没有则按毫升、克 BigDecimal gramOrMlUnitPrice = (unit2Price != null) ? unit2Price : unit1Price; //获取化妆品阀值 if (cosmThresholdValue != null && cosmThresholdValue.compareTo(BigDecimal.ZERO) > 0) { if (gramOrMlUnitPrice != null) { //完税法定单位单价大于阈值采用第一档消费税率,否则消费税率为0 if (gramOrMlUnitPrice.compareTo(cosmThresholdValue) >= 0) { goodsRate = new BigDecimal("0.2306"); return goodsRate.multiply(retailPrice .divide(new BigDecimal(1).add(goodsRate),2, RoundingMode.HALF_DOWN)) .setScale(2,RoundingMode.HALF_DOWN) ; } else { goodsRate = new BigDecimal("0.091"); return goodsRate.multiply(retailPrice .divide(new BigDecimal(1).add(goodsRate),2, RoundingMode.HALF_DOWN)) .setScale(2,RoundingMode.HALF_DOWN) ; } } else { String message = "【" + goodsEntity.getSku() + "】缺少法定单价"; logger.error(message); throw new ServiceException(message); } } // 一般走不到这里,但是为了做个保险,还是要这个 return goodsRate.multiply(retailPrice .divide(new BigDecimal(1).add(goodsRate),2, RoundingMode.HALF_DOWN)) .setScale(2,RoundingMode.HALF_DOWN) ; }else{ // 该商品不是特殊海关商品编码,直接用里面的税率进行计算 return goodsRate.multiply(retailPrice .divide(new BigDecimal(1).add(goodsRate),2, RoundingMode.HALF_DOWN)) .setScale(2,RoundingMode.HALF_DOWN) ; } } }