|
@@ -0,0 +1,154 @@
|
|
|
|
+package com.kmall.admin.utils;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+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;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * xwh
|
|
|
|
+ * 2020年12月7日14:57:04
|
|
|
|
+ */
|
|
|
|
+public class CalculateTax {
|
|
|
|
+ private static final Logger logger = LoggerFactory.getLogger(CalculateTax.class);
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 计算税费,包括消费税和增值税。公式如下:
|
|
|
|
+ * 订单该商品总税费 = (商品消费税 + 商品增值税)* 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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|