跳转到内容

案例 23:小微税费减免/稳岗补贴资格判定

本案例对应 USE-CASES 场景 23「小微税费减免/稳岗补贴资格判定(诉求 21)」,属于财税合规领域,面向税务与人社部门的惠企政策兑现场景,自动完成小型微利企业资格判定、企业所得税分段优惠核算、小规模纳税人增值税征收率适用与稳岗返还定额核定。

小微企业通过统一惠企窗口申请税费减免与稳岗补贴,申报要素包括:纳税人类型(一般纳税人 GENERAL / 小规模纳税人 SMALL_SCALE)、从业人数(含劳务派遣)、资产总额、年应纳税所得额、是否属于限制或禁止行业,以及用于稳岗审核的社保连续缴纳月数、上年度裁员率、是否存在社保欠费或欠税、上年度实际缴纳失业保险费。

小型微利企业资格按三项条件同时满足判定:从业人数不超过 300 人、资产总额不超过 5000 万元、年应纳税所得额不超过 300 万元(三项临界值均含本数)。具备资格的企业企业所得税按分段实际税负核定:年应纳税所得额 100 万元以下部分实际税负 5%,超过 100 万元的部分实际税负 10%(即 5 万元 + 超出部分 × 10%);不具备资格的按 25% 法定税率缴纳。系统同时按 25% 口径计算法定应纳税额,与核定税额之差即减免额。

流转税与稳岗返还并行审核:小规模纳税人增值税减按 1% 征收率执行,一般纳税人不适用该项优惠(征收率记 0)。稳岗补贴须同时满足社保连续缴纳满 12 个月、上年度裁员率不超过 5%、无社保欠费三个条件,资格成立时按实缴失业保险费的 50% 核定补贴;企业存在欠税记录的,即使符合三项条件,稳岗返还也暂缓拨付、须清缴后另行申请。

限制或禁止行业属于硬性禁入:从事限制或禁止行业的企业一律 DENIED,所得税按法定税率完税、增值税优惠与稳岗返还全部归零,并在原因中明确禁入依据。最终决策携带小微资格、法定税额、核定税额、减免额、征收率、稳岗资格与补贴金额,以及逐项政策依据 reasons,支撑惠企政策兑现通知书的生成与税务留痕。

  • 税收优惠口径随政策文件频繁调整:小型微利企业分段实际税负、1% 征收率、稳岗返还比例 50% 都可能随年度政策修订,硬编码进征管系统每次都要赶发版窗口。
  • 分段税额核算容易出错:100 万以下 5%、100-300 万部分 10% 是「超额分段」而非全额分档,写成 if 套表常被误算为全额 10%。
  • 资格条件与行业禁入优先级必须合规:限制行业即使三项规模全达标也不得享受,禁入判断必须先于税额与稳岗核算短路。
  • 优惠种类多、结论要逐项可解释:所得税减免、增值税征收率、稳岗返还三类政策相互独立,企业不满足小微条件时还要逐条告知是人数、资产还是所得额超标。
  • 欠税、欠费对补贴的影响易漏判:裁员率与社保条件达标但存在欠税的,补贴不是直接拒绝而是「暂缓拨付」,政策口径不同须区别表述。
  • 金额口径要求精确:税额、补贴保留两位小数且禁止科学计数法,double 直接拼接可能产生 6000.0 之类不规范文书表述。

本案例沿用六件套骨架:入参模型 + 决策结果模型 + 规则接口 + XML 规则脚本 + Service 编排 + 6 组真实业务形态测试。

层次 职责 对应文件
领域模型 税费减免与稳岗补贴申请要素、核定结果(资格/三类金额/政策原因) TaxReliefApplication.java、TaxReliefDecision.java
规则集与 XML 分段企业所得税、小规模征收率、稳岗资格条件、50% 返还定额 TaxReliefRules.java、tax-relief.xml
编排服务 小微三项条件与行业禁入、欠税暂缓、法定税额对比、金额精度与原因组装 TaxReliefService.java
测试 6 组企业形态(低档税率+稳岗/跨档税率/三项全超/临界值/限制行业/裁员与欠税) TaxReliefServiceTest.java
规则方法 口径 分值/输出
incomeTaxWan 具备小微资格:所得额 ≤100 万部分 ×5%,超出部分 = 5.0 +(所得额 - 100)×10%;不具备:×25% 万元税额
vatLevyRate SMALL_SCALE 返回 0.01,其余返回 0.0(不适用该优惠) 征收率
stabilizationEligible 社保 ≥12 月、裁员率 ≤5%、无社保欠费三者同时成立 boolean
subsidyAmountWan 资格成立时实缴失业保险费 ×50%,否则为 0 万元补贴

将下列文件按源码包结构放入 JQuick-Java 工程的测试目录:两个模型放入 src/test/java/com/github/paohaijiao/demo/model/,规则接口与测试类放入 src/test/java/com/github/paohaijiao/demo/,Service 放入 src/test/java/com/github/paohaijiao/demo/service/,XML 脚本放入 src/test/resources/demo/,包名保持源码原样(com.github.paohaijiao.demo / .model / .service)。放入后执行 mvn test -Dtest=TaxReliefServiceTest 即可运行全部 6 个用例。

package com.github.paohaijiao.demo.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 小微企业税费减免与稳岗补贴申请要素
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TaxReliefApplication {
/**
* 企业编号
*/
private String enterpriseId;
/**
* 企业名称
*/
private String enterpriseName;
/**
* 纳税人类型:GENERAL-一般纳税人 / SMALL_SCALE-小规模纳税人
*/
private String taxpayerType;
/**
* 从业人数(含劳务派遣)
*/
private int employeeCount;
/**
* 资产总额(万元)
*/
private double totalAssetsWan;
/**
* 年应纳税所得额(万元)
*/
private double annualTaxableIncomeWan;
/**
* 是否属于限制或禁止行业
*/
private boolean restrictedIndustry;
/**
* 社保连续缴纳月数(稳岗补贴审核用)
*/
private int socialInsuranceMonths;
/**
* 上年度裁员率(整数百分比)
*/
private int layoffRate;
/**
* 是否存在社保欠费
*/
private boolean socialArrears;
/**
* 是否存在欠税
*/
private boolean overdueTax;
/**
* 上年度实际缴纳失业保险费(万元)
*/
private double paidUnemploymentInsuranceWan;
}
package com.github.paohaijiao.demo.model;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 税费减免与稳岗补贴核定结果
*/
@Data
public class TaxReliefDecision {
/**
* 企业编号
*/
private String enterpriseId;
/**
* 办理结论:APPROVED-可享受优惠 / DENIED-不予享受
*/
private String result;
/**
* 是否具备小型微利企业资格
*/
private boolean smallQualified;
/**
* 法定应纳企业所得税(25% 口径,万元)
*/
private double statutoryTaxWan;
/**
* 核定应纳企业所得税(万元)
*/
private double incomeTaxWan;
/**
* 企业所得税减免额(万元)
*/
private double taxSavingWan;
/**
* 增值税征收率(小规模优惠为 0.01,不适用为 0)
*/
private double vatLevyRate;
/**
* 是否具备稳岗补贴资格
*/
private boolean stabilizationEligible;
/**
* 核定稳岗补贴金额(万元)
*/
private double stabilizationSubsidyWan;
/**
* 资格判定与政策依据
*/
private List<String> reasons = new ArrayList<String>();
public void addReason(String reason) {
this.reasons.add(reason);
}
}
package com.github.paohaijiao.demo;
import com.github.paohaijiao.xml.param.Param;
/**
* 场景 23:小微企业税费减免与稳岗补贴规则集
* <p>
* 小型微利企业所得税分段实际税负:100 万以下部分 5%、100-300 万部分 10%;
* 小规模纳税人增值税征收率 1%;稳岗补贴为实缴失业保险费的 50%。
* 规则脚本见 {@code src/test/resources/demo/tax-relief.xml}。
*/
public interface TaxReliefRules {
/** 核定企业所得税(万元):符合小微条件分段优惠,否则按 25% 法定税率 */
double incomeTaxWan(@Param("incomeWan") double incomeWan,
@Param("smallQualified") boolean smallQualified);
/** 增值税征收率:小规模纳税人减按 1%,一般纳税人不适用该优惠 */
double vatLevyRate(@Param("taxpayerType") String taxpayerType);
/** 稳岗补贴资格:社保满 12 月、裁员率不超过 5%、无社保欠费 */
boolean stabilizationEligible(@Param("ssMonths") int ssMonths,
@Param("layoffRate") int layoffRate,
@Param("noArrears") boolean noArrears);
/** 稳岗补贴定额:资格成立时为实缴失业保险费的 50% */
double subsidyAmountWan(@Param("paidUiWan") double paidUiWan,
@Param("eligible") boolean eligible);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE javas PUBLIC "-//PAOHAIJIAO//DTD API JAVA 1.0//EN"
"classpath:paohaijiao/dtd/Jquick-java.dtd">
<javas namespace="com.github.paohaijiao.demo.TaxReliefRules">
<!-- 企业所得税:小微分段优惠(100 万以下 5%,100-300 万部分 10%),否则 25% -->
<java name="incomeTaxWan" returnClass="double">
<![CDATA[
double def incomeTaxWan(double:incomeWan, boolean:smallQualified) {
double tax = 0.0;
if (smallQualified) {
if (incomeWan <= 100.0) {
tax = incomeWan * 0.05;
} else {
tax = 5.0 + (incomeWan - 100.0) * 0.10;
}
} else {
tax = incomeWan * 0.25;
}
return tax;
}
]]>
</java>
<!-- 增值税征收率:小规模 1%,一般纳税人不适用此优惠(0 表示不涉及) -->
<java name="vatLevyRate" returnClass="double">
<![CDATA[
double def vatLevyRate(str:taxpayerType) {
if (taxpayerType == "SMALL_SCALE") {
return 0.01;
} else {
return 0.0;
}
}
]]>
</java>
<!-- 稳岗补贴资格:社保 12 月以上、裁员率 5% 以下、无社保欠费 -->
<java name="stabilizationEligible" returnClass="boolean">
<![CDATA[
boolean def stabilizationEligible(int:ssMonths, int:layoffRate, boolean:noArrears) {
if (ssMonths >= 12) {
if (layoffRate <= 5) {
if (noArrears) {
return true;
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
}
]]>
</java>
<!-- 稳岗补贴定额:实缴失业保险费的 50% -->
<java name="subsidyAmountWan" returnClass="double">
<![CDATA[
double def subsidyAmountWan(double:paidUiWan, boolean:eligible) {
if (eligible) {
return paidUiWan * 0.5;
} else {
return 0.0;
}
}
]]>
</java>
</javas>
package com.github.paohaijiao.demo.service;
import com.github.paohaijiao.demo.TaxReliefRules;
import com.github.paohaijiao.demo.model.TaxReliefApplication;
import com.github.paohaijiao.demo.model.TaxReliefDecision;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 场景 23:小微企业税费减免 / 稳岗补贴资格判定服务
* <p>
* 职责划分:
* <ul>
* <li><b>Java 侧</b>:小型微利企业三项条件(人数/资产/所得额)、行业禁入、
* 欠税冻结、法定税额与减免额对比核算</li>
* <li><b>规则侧</b>:分段实际税负、小规模征收率、稳岗资格与返还比例,外置在 XML 中</li>
* </ul>
*/
public class TaxReliefService {
private static final int EMPLOYEE_LIMIT = 300;
private static final double ASSETS_LIMIT_WAN = 5000.0;
private static final double INCOME_LIMIT_WAN = 300.0;
private final TaxReliefRules rules;
public TaxReliefService(TaxReliefRules rules) {
this.rules = rules;
}
public TaxReliefDecision evaluate(TaxReliefApplication app) {
TaxReliefDecision decision = new TaxReliefDecision();
decision.setEnterpriseId(app.getEnterpriseId());
double income = app.getAnnualTaxableIncomeWan();
double statutory = round2(income * 0.25);
decision.setStatutoryTaxWan(statutory);
if (app.isRestrictedIndustry()) {
decision.setResult("DENIED");
decision.setSmallQualified(false);
decision.setIncomeTaxWan(statutory);
decision.setTaxSavingWan(0.0);
decision.setVatLevyRate(0.0);
decision.setStabilizationEligible(false);
decision.setStabilizationSubsidyWan(0.0);
decision.addReason("企业从事限制或禁止行业,不得享受小型微利企业税收优惠及稳岗返还");
return decision;
}
decision.setResult("APPROVED");
boolean employeeOk = app.getEmployeeCount() <= EMPLOYEE_LIMIT;
boolean assetsOk = app.getTotalAssetsWan() <= ASSETS_LIMIT_WAN;
boolean incomeOk = income <= INCOME_LIMIT_WAN;
boolean qualified = employeeOk && assetsOk && incomeOk;
decision.setSmallQualified(qualified);
double tax = round2(rules.incomeTaxWan(income, qualified));
decision.setIncomeTaxWan(tax);
decision.setTaxSavingWan(round2(statutory - tax));
if (qualified) {
decision.addReason("符合小型微利企业条件,年应纳企业所得税核定为 " + tax + " 万元,"
+ "较法定税率减免 " + decision.getTaxSavingWan() + " 万元");
} else {
decision.addReason("不满足小型微利企业条件,按 25% 法定税率缴纳企业所得税 " + statutory + " 万元");
if (!employeeOk) {
decision.addReason("从业人数 " + app.getEmployeeCount() + " 人超过 300 人标准");
}
if (!assetsOk) {
decision.addReason("资产总额 " + money(app.getTotalAssetsWan()) + " 万元超过 5000 万元标准");
}
if (!incomeOk) {
decision.addReason("年应纳税所得额超过 300 万元标准");
}
}
double vatRate = rules.vatLevyRate(app.getTaxpayerType());
decision.setVatLevyRate(vatRate);
if (vatRate > 0.0) {
decision.addReason("小规模纳税人增值税减按 1% 征收率执行");
}
boolean stable = rules.stabilizationEligible(app.getSocialInsuranceMonths(),
app.getLayoffRate(), !app.isSocialArrears());
if (stable && app.isOverdueTax()) {
stable = false;
decision.addReason("企业存在欠税记录,稳岗返还暂缓拨付,清缴后另行申请");
}
decision.setStabilizationEligible(stable);
double subsidy = round2(rules.subsidyAmountWan(app.getPaidUnemploymentInsuranceWan(), stable));
decision.setStabilizationSubsidyWan(subsidy);
if (stable) {
decision.addReason("符合稳岗返还条件,按实缴失业保险费 50% 核定补贴 " + subsidy + " 万元");
} else if (!app.isOverdueTax()) {
decision.addReason("不满足稳岗返还条件(社保连续缴纳满 12 月、裁员率 5% 以下、无社保欠费)");
}
return decision;
}
private double round2(double value) {
return BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP).doubleValue();
}
/** 金额文本:固定两位小数且禁用科学计数法 */
private String money(double value) {
return BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP).toPlainString();
}
}
package com.github.paohaijiao.demo;
import com.github.paohaijiao.demo.model.TaxReliefApplication;
import com.github.paohaijiao.demo.model.TaxReliefDecision;
import com.github.paohaijiao.demo.service.TaxReliefService;
import com.github.paohaijiao.xml.JQuickJava;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* 场景 23:小微企业税费减免 / 稳岗补贴资格判定
* <p>
* 覆盖 6 组企业形态:小规模低档税率、一般纳税人跨档税率、三项标准超标、
* 临界值小微企业、限制行业禁入、裁员率与欠税影响稳岗返还。
*/
public class TaxReliefServiceTest {
private TaxReliefService service;
@Before
public void setUp() {
TaxReliefRules rules = JQuickJava.create()
.createApi(TaxReliefRules.class, "demo/tax-relief.xml");
this.service = new TaxReliefService(rules);
}
/**
* 小规模纳税人,80 人、所得额 80 万、稳岗条件齐全 → 所得税 5% 缴 4 万,补贴 2 万
*/
@Test
public void shouldApplyFivePercentTaxAndStabilizationSubsidy() {
TaxReliefApplication app = baseApplication("TR2026001", "SMALL_SCALE");
app.setEmployeeCount(80);
app.setTotalAssetsWan(1000.0);
app.setAnnualTaxableIncomeWan(80.0);
app.setSocialInsuranceMonths(24);
app.setLayoffRate(2);
app.setPaidUnemploymentInsuranceWan(4.0);
TaxReliefDecision decision = service.evaluate(app);
Assert.assertEquals("APPROVED", decision.getResult());
Assert.assertTrue(decision.isSmallQualified());
Assert.assertEquals(20.0, decision.getStatutoryTaxWan(), 0.001);
Assert.assertEquals(4.0, decision.getIncomeTaxWan(), 0.001);
Assert.assertEquals(16.0, decision.getTaxSavingWan(), 0.001);
Assert.assertEquals(0.01, decision.getVatLevyRate(), 0.00001);
Assert.assertTrue(decision.isStabilizationEligible());
Assert.assertEquals(2.0, decision.getStabilizationSubsidyWan(), 0.001);
}
/**
* 一般纳税人,200 人、所得额 250 万跨档 → 5 + 150×10% = 20 万,社保不足无稳岗
*/
@Test
public void applySegmentedTaxForIncomeOverOneMillion() {
TaxReliefApplication app = baseApplication("TR2026002", "GENERAL");
app.setEmployeeCount(200);
app.setTotalAssetsWan(4000.0);
app.setAnnualTaxableIncomeWan(250.0);
app.setSocialInsuranceMonths(6);
app.setLayoffRate(1);
app.setPaidUnemploymentInsuranceWan(3.0);
TaxReliefDecision decision = service.evaluate(app);
Assert.assertTrue(decision.isSmallQualified());
Assert.assertEquals(62.5, decision.getStatutoryTaxWan(), 0.001);
Assert.assertEquals(20.0, decision.getIncomeTaxWan(), 0.001);
Assert.assertEquals(42.5, decision.getTaxSavingWan(), 0.001);
Assert.assertEquals(0.0, decision.getVatLevyRate(), 0.00001);
Assert.assertFalse(decision.isStabilizationEligible());
Assert.assertEquals(0.0, decision.getStabilizationSubsidyWan(), 0.001);
}
/**
* 400 人、资产 6000 万、所得额 400 万,三项标准全超 → 按 25% 完税,逐条告知
*/
@Test
public void shouldDenySmallTaxBenefitWhenAllLimitsExceeded() {
TaxReliefApplication app = baseApplication("TR2026003", "GENERAL");
app.setEmployeeCount(400);
app.setTotalAssetsWan(6000.0);
app.setAnnualTaxableIncomeWan(400.0);
app.setSocialInsuranceMonths(0);
app.setLayoffRate(0);
TaxReliefDecision decision = service.evaluate(app);
Assert.assertFalse(decision.isSmallQualified());
Assert.assertEquals(100.0, decision.getIncomeTaxWan(), 0.001);
Assert.assertEquals(0.0, decision.getTaxSavingWan(), 0.001);
Assert.assertTrue(decision.getReasons().contains("从业人数 400 人超过 300 人标准"));
Assert.assertTrue(decision.getReasons().contains("资产总额 6000.00 万元超过 5000 万元标准"));
Assert.assertTrue(decision.getReasons().contains("年应纳税所得额超过 300 万元标准"));
}
/**
* 人数 300、资产 5000 万、所得额 300 万恰在临界值 → 仍具备小微资格,税 25 万
*/
@Test
public void shouldQualifyAtExactBoundaryValues() {
TaxReliefApplication app = baseApplication("TR2026004", "GENERAL");
app.setEmployeeCount(300);
app.setTotalAssetsWan(5000.0);
app.setAnnualTaxableIncomeWan(300.0);
app.setSocialInsuranceMonths(24);
app.setLayoffRate(0);
TaxReliefDecision decision = service.evaluate(app);
Assert.assertTrue(decision.isSmallQualified());
Assert.assertEquals(75.0, decision.getStatutoryTaxWan(), 0.001);
Assert.assertEquals(25.0, decision.getIncomeTaxWan(), 0.001);
Assert.assertEquals(50.0, decision.getTaxSavingWan(), 0.001);
}
/**
* 限制行业企业即使规模符合 → 全面禁止享受,按法定税率完税
*/
@Test
public void shouldDenyAllBenefitsForRestrictedIndustry() {
TaxReliefApplication app = baseApplication("TR2026005", "SMALL_SCALE");
app.setEmployeeCount(50);
app.setTotalAssetsWan(500.0);
app.setAnnualTaxableIncomeWan(80.0);
app.setSocialInsuranceMonths(36);
app.setLayoffRate(0);
app.setPaidUnemploymentInsuranceWan(2.0);
app.setRestrictedIndustry(true);
TaxReliefDecision decision = service.evaluate(app);
Assert.assertEquals("DENIED", decision.getResult());
Assert.assertFalse(decision.isSmallQualified());
Assert.assertEquals(20.0, decision.getIncomeTaxWan(), 0.001);
Assert.assertEquals(0.0, decision.getTaxSavingWan(), 0.001);
Assert.assertEquals(0.0, decision.getVatLevyRate(), 0.00001);
Assert.assertFalse(decision.isStabilizationEligible());
Assert.assertTrue(decision.getReasons().contains(
"企业从事限制或禁止行业,不得享受小型微利企业税收优惠及稳岗返还"));
}
/**
* 裁员率 8% 不符稳岗条件;裁员率达标但欠税的,稳岗返还暂缓
*/
@Test
public void shouldBlockStabilizationSubsidyForHighLayoffAndTaxDue() {
TaxReliefApplication highLayoff = baseApplication("TR2026006", "SMALL_SCALE");
highLayoff.setEmployeeCount(100);
highLayoff.setTotalAssetsWan(800.0);
highLayoff.setAnnualTaxableIncomeWan(60.0);
highLayoff.setSocialInsuranceMonths(24);
highLayoff.setLayoffRate(8);
highLayoff.setPaidUnemploymentInsuranceWan(4.0);
TaxReliefDecision d1 = service.evaluate(highLayoff);
Assert.assertTrue(d1.isSmallQualified());
Assert.assertEquals(3.0, d1.getIncomeTaxWan(), 0.001);
Assert.assertFalse(d1.isStabilizationEligible());
Assert.assertEquals(0.0, d1.getStabilizationSubsidyWan(), 0.001);
TaxReliefApplication taxDue = baseApplication("TR2026007", "SMALL_SCALE");
taxDue.setEmployeeCount(100);
taxDue.setTotalAssetsWan(800.0);
taxDue.setAnnualTaxableIncomeWan(60.0);
taxDue.setSocialInsuranceMonths(24);
taxDue.setLayoffRate(2);
taxDue.setPaidUnemploymentInsuranceWan(4.0);
taxDue.setOverdueTax(true);
TaxReliefDecision d2 = service.evaluate(taxDue);
Assert.assertFalse(d2.isStabilizationEligible());
Assert.assertTrue(d2.getReasons().contains("企业存在欠税记录,稳岗返还暂缓拨付,清缴后另行申请"));
}
private TaxReliefApplication baseApplication(String id, String taxpayerType) {
TaxReliefApplication app = new TaxReliefApplication();
app.setEnterpriseId(id);
app.setEnterpriseName("测试小微企业");
app.setTaxpayerType(taxpayerType);
app.setEmployeeCount(100);
app.setTotalAssetsWan(1000.0);
app.setAnnualTaxableIncomeWan(100.0);
app.setRestrictedIndustry(false);
app.setSocialInsuranceMonths(12);
app.setLayoffRate(0);
app.setSocialArrears(false);
app.setOverdueTax(false);
app.setPaidUnemploymentInsuranceWan(0.0);
return app;
}
}

在工程根目录执行:

Terminal window
mvn test -Dtest=TaxReliefServiceTest
测试方法 构造的业务形态 关键断言/期望决策
shouldApplyFivePercentTaxAndStabilizationSubsidy 小规模、80 人、资产 1000 万、所得额 80 万、社保 24 月、裁员 2%、实缴失业险 4 万 APPROVED;法定 20 万、核定 4 万、减免 16 万;征收率 0.01;稳岗成立补贴 2.0 万
applySegmentedTaxForIncomeOverOneMillion 一般纳税人、200 人、资产 4000 万、所得额 250 万、社保仅 6 月 小微资格成立;法定 62.5 万、核定 20 万(5 + 150×10%)、减免 42.5 万;征收率 0;稳岗不成立补贴 0
shouldDenySmallTaxBenefitWhenAllLimitsExceeded 400 人、资产 6000 万、所得额 400 万,三项条件全超 smallQualified=false;按 25% 完税 100 万、减免 0;原因逐条含「400 人超过 300 人」「资产总额 6000.00 万元超过 5000 万元」「所得额超过 300 万元」
shouldQualifyAtExactBoundaryValues 300 人、资产 5000 万、所得额 300 万,三项均压线 临界值含本数,资格成立;法定 75 万、核定 25 万、减免 50 万
shouldDenyAllBenefitsForRestrictedIndustry 小规模、50 人、资产 500 万、所得额 80 万但属于限制行业 DENIED;所得税 20 万、减免 0、征收率 0、稳岗 false;原因含行业禁入说明
shouldBlockStabilizationSubsidyForHighLayoffAndTaxDue 两个子场景:社保 24 月但裁员率 8%;裁员率 2% 但存在欠税 前者稳岗 false、补贴 0(所得税仍享 3 万);后者稳岗 false 且原因含「稳岗返还暂缓拨付,清缴后另行申请」
  • 税率与补贴口径全量外置 XML:5%/10% 分段税负、25% 法定税率、1% 征收率、12 月/5% 稳岗条件、50% 返还比例均在脚本中,年度税费政策调整只需改 XML 重建代理,征管主系统免发版。
  • 超额分段在脚本内一次算清:incomeTaxWan 对 100 万以上所得额按「5.0 + 超出部分 ×10%」计算,避免 Java 侧套表时误把全额按 10% 计税。
  • 行业禁入与欠税暂缓 Java 侧短路:限制行业在所有核算前直接 DENIED 并归零三项优惠;欠税主体在规则判定之后再覆写稳岗资格,区分「不符合条件」与「暂缓拨付」两种政策表述。
  • 布尔正向条件适配脚本语法:脚本不支持 ! 取反,Service 以 !app.isSocialArrears() 在 Java 侧转为正向 noArrears 传入,规则内只用正向嵌套 if 返回 true/false。
  • 金额精度与文书口径在 Java 侧兜底:round2 用 BigDecimal HALF_UP 保留两位小数,money 用 toPlainString 固定两位且禁用科学计数法,保证「资产总额 6000.00 万元」类文书表述规范。
  • 不达标原因逐条装配、可审计可复议:三项规模条件各自独立判断并追加原因,法定税额、减免额、征收率、补贴金额与依据全部进入 reasons,可直接生成惠企兑现通知书。