Case 39: Property fee waiver eligibility
This case corresponds to Scenario 39 in USE-CASES.md (Requirement 49: property-fee / parking-fee waiver eligibility), in the property & community domain. The rule script owns the one-vote veto reason codes, the waiver percentages for the two fee types, and the guaranteed-area policy; the Service owns veto short-circuiting, guaranteed-area capping, waiver amount calculation, and the parking-space limit, outputting each household’s eligibility verdict, waiver percentages, counted area, itemized amounts, and review notes.
Industry scenario
Section titled “Industry scenario”Owner waiver applications are carried by PropertyWaiverApplication: beyond the household ID and owner information, the core is the household type householdType — SUBSISTENCE (subsistence/extreme hardship), MARTYR (martyr-family preferential care), DISABLED (severe disability), LOW_INCOME (near-subsistence), ELDERLY_ALONE (elderly living alone), ORDINARY (ordinary owner); property data includes the titled area, resident family size, per-capita floor area, the property-fee unit price, and the number of months applied for; parking data includes the number of registered spaces and the monthly fee per space; compliance flags include whether the unit is vacant, rented out, illegally constructed, the number of historical arrears months, and whether there are safety violations such as e-bike fly-wire charging or bringing e-bikes into elevators or homes.
Eligibility starts with four one-vote vetoes: renting out (waivers are for owner-occupiers only), illegal construction, arrears over 6 months, and parking safety violations — hitting any of them immediately returns a reason code (RENTING / ILLEGAL / OVERDUE / SAFETY) without entering waiver calculation. After passing the vetoes, the percentage is set by household type: subsistence, martyr-family, and severely-disabled households get 100% off both property and parking fees; near-subsistence households get 60% off property and 50% off parking; elderly living alone get 50% off property; ordinary owners with a vacant unit pay property fees at 70% (i.e., a 30% waiver) and get no parking waiver.
The guaranteed-area rule prevents “large units enjoying high percentages”: subsistence, martyr-family, severely-disabled, and elderly-living-alone households use a 30 ㎡ per-capita guarantee line, near-subsistence households use 20 ㎡; if per-capita floor area does not exceed the line, the whole unit is counted, otherwise the counted area is capped at “guarantee line × family size” and the excess is not waived; ordinary vacant units do not use the guarantee line and are waived on the whole unit. Parking waivers are strictly limited to 1 registered space — additional spaces in multi-space households are paid normally. The decision result PropertyWaiverDecision outputs the eligibility verdict, veto reason code, counted area, the two waiver percentages and amounts, the total waiver, and review notes.
Business pain points
Section titled “Business pain points”- Livelihood policies are rigid: waiver percentages and guaranteed-area standards come from government documents; renting out, illegal construction, arrears, and safety violations must be one-vote vetoes — looseness in manual calculation leaks subsidies, while over-strictness invites complaints.
- Property and parking fees use two different percentage sets: the same household type has different percentages for the two fees (e.g., near-subsistence 60% vs. 50%), and the parking waiver covers only 1 space — combined calculation is extremely error-prone.
- Guaranteed-area capping is complex: first compare per-capita area against the guarantee line, then compute the capped area from family size, and take the smaller of titled area and capped area as the billing base.
- The vacant-unit policy is easily abused: ordinary owners with vacant units only get a 30% property waiver and no parking waiver; this must not be confused with the 100% waivers for hardship groups.
- Amount precision and audit trail requirements are high: waiver amounts involve government subsidies and owners’ vital interests; they must be exact to the cent, with explainable notes such as “how many square meters in excess are not waived” and “remaining spaces paid normally”.
- Policy standards vary widely by region and change often: guarantee-area lines (30/20 ㎡) and waiver percentages differ across cities; once hard-coded into the billing system, cross-project reuse is difficult.
Solution architecture
Section titled “Solution architecture”| Component | File | Responsibility |
|---|---|---|
| Input model | model/PropertyWaiverApplication.java |
Household type, property and parking data, unit price and months, plus the four compliance flags |
| Decision model | model/PropertyWaiverDecision.java |
Eligibility verdict, veto reason code, counted area, both percentages and amounts, total, notes |
| Rule interface | PropertyWaiverRules.java |
4 rule methods: veto reason, property percentage, parking percentage, guaranteed area |
| Rule script | resources/demo/property-waiver.xml |
Veto conditions, household-type percentage table, per-capita guarantee lines all externalized |
| Orchestration service | service/PropertyWaiverService.java |
Veto short circuit, area-cap selection, amount calculation, parking-space limit, note assembly |
| Tests | PropertyWaiverServiceTest.java |
6 household shapes, including a looped comparison across the four veto types |
Rule method breakdown
Section titled “Rule method breakdown”| Rule method | Inputs (@Param) |
Policy | Returns |
|---|---|---|---|
hardRejectReason |
renting, illegal, overdueMonths, safetyViolation |
Renting returns RENTING; illegal construction ILLEGAL; arrears over 6 months OVERDUE; safety violation SAFETY; otherwise PASS |
String reason code |
propertyWaiverPercent |
householdType, vacant |
Subsistence/martyr/severely-disabled 100%; near-subsistence 60%; elderly living alone 50%; ordinary vacant unit 30%; otherwise 0 | int percentage |
parkingWaiverPercent |
householdType |
Subsistence/martyr/severely-disabled 100% (limited to 1 space); near-subsistence 50%; otherwise 0 | int percentage |
qualifiedArea |
size, perCapita, family, householdType |
Guarantee lines: subsistence/martyr/severely-disabled/elderly-alone 30 ㎡ per capita, near-subsistence 20 ㎡ (default 15 ㎡); under the line counts the whole unit, over the line caps at guarantee line × family size; the smaller value is taken | double counted area |
Code implementation (complete & runnable)
Section titled “Code implementation (complete & runnable)”Place the following files into the JQuick-Java test project by package structure: the two models into src/test/java/com/github/paohaijiao/demo/model/, the rule interface and test into src/test/java/com/github/paohaijiao/demo/, the Service into demo/service/, and the XML into src/test/resources/demo/. Then run:
mvn test -Dtest=PropertyWaiverServiceTestPropertyWaiverApplication.java
Section titled “PropertyWaiverApplication.java”package com.github.paohaijiao.demo.model;
import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;
/** * 业主物业费/停车费减免申请要素 */@Data@NoArgsConstructor@AllArgsConstructorpublic class PropertyWaiverApplication {
/** * 户号 */ private String householdId;
private String ownerName;
/** * 家庭类型:SUBSISTENCE 低保特困 / MARTYR 烈属优抚 / DISABLED 重度残疾 / * LOW_INCOME 低保边缘 / ELDERLY_ALONE 独居老人 / ORDINARY 普通业主 */ private String householdType;
/** * 产权面积(㎡) */ private double propertySize;
/** * 家庭常住人口数 */ private int familySize;
/** * 人均建筑面积(㎡) */ private double perCapitaArea;
/** * 物业费单价(元/㎡/月) */ private double monthlyFeePerSqm;
/** * 申请减免月数 */ private int monthsApplied;
/** * 登记车位数 */ private int parkingSpaceCount;
/** * 单个车位月停车费 */ private double monthlyParkingFee;
/** * 房屋是否空置(未入住毛坯/长期空置,普通业主按 70% 缴纳) */ private boolean vacant;
/** * 是否出租(减免仅限自住) */ private boolean rentingOut;
/** * 是否存在违法建设 */ private boolean illegalConstruction;
/** * 历史欠费月数 */ private int overdueMonths;
/** * 是否存在电动车飞线充电/进梯入户等安全违规 */ private boolean parkingSafetyViolation;}PropertyWaiverDecision.java
Section titled “PropertyWaiverDecision.java”package com.github.paohaijiao.demo.model;
import lombok.Data;
import java.util.ArrayList;import java.util.List;
/** * 物业/停车费减免决策 */@Datapublic class PropertyWaiverDecision {
/** * 户号 */ private String householdId;
/** * 是否通过资格审核 */ private boolean eligible;
/** * 否决原因码:RENTING 出租 / ILLEGAL 违建 / OVERDUE 长期欠费 / SAFETY 安全违规 */ private String rejectReason;
/** * 计入减免的建筑面积(㎡,超出保障面积标准部分不免) */ private double qualifiedArea;
/** * 物业费减免比例(百分比) */ private int propertyWaiverPercent;
/** * 停车费减免比例(百分比) */ private int parkingWaiverPercent;
/** * 物业费减免金额 */ private double propertyWaiverAmount;
/** * 停车费减免金额 */ private double parkingWaiverAmount;
/** * 减免合计 */ private double totalWaiver;
/** * 审核说明 */ private List<String> notes = new ArrayList<String>();
public void addNote(String note) { this.notes.add(note); }}PropertyWaiverRules.java
Section titled “PropertyWaiverRules.java”package com.github.paohaijiao.demo;
import com.github.paohaijiao.xml.param.Param;
/** * 场景 39:物业/停车费减免资格、比例与保障面积规则 */public interface PropertyWaiverRules {
/** * 一票否决原因码:出租/违建/欠费超 6 个月/安全违规,其余 PASS */ String hardRejectReason(@Param("renting") boolean renting, @Param("illegal") boolean illegal, @Param("overdueMonths") int overdueMonths, @Param("safetyViolation") boolean safetyViolation);
/** * 物业费减免比例:低保特困/烈属/重残 100%、边缘困难 60%、独居老人 50%、 * 普通空置房 30%,其余 0 */ int propertyWaiverPercent(@Param("householdType") String householdType, @Param("vacant") boolean vacant);
/** * 停车费减免比例:低保特困/烈属/重残 100%(限 1 个车位)、边缘困难 50%,其余 0 */ int parkingWaiverPercent(@Param("householdType") String householdType);
/** * 计入减免的面积:低保特困/烈属/重残/独居老人按人均 30 ㎡保障线、 * 边缘困难按人均 20 ㎡,超出部分按家庭人口封顶;未超标按整套 */ double qualifiedArea(@Param("size") double size, @Param("perCapita") double perCapita, @Param("family") int family, @Param("householdType") String householdType);}property-waiver.xml
Section titled “property-waiver.xml”<?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.PropertyWaiverRules">
<java name="hardRejectReason" returnClass="java.lang.String"> <![CDATA[ str def hardRejectReason(boolean:renting, boolean:illegal, int:overdueMonths, boolean:safetyViolation) { if (renting) { return "RENTING"; } else if (illegal) { return "ILLEGAL"; } else if (overdueMonths > 6) { return "OVERDUE"; } else if (safetyViolation) { return "SAFETY"; } else { return "PASS"; } } ]]> </java>
<java name="propertyWaiverPercent" returnClass="int"> <![CDATA[ int def propertyWaiverPercent(str:householdType, boolean:vacant) { if (householdType == "SUBSISTENCE") { return 100; } else if (householdType == "MARTYR") { return 100; } else if (householdType == "DISABLED") { return 100; } else if (householdType == "LOW_INCOME") { return 60; } else if (householdType == "ELDERLY_ALONE") { return 50; } else if (vacant) { return 30; } else { return 0; } } ]]> </java>
<java name="parkingWaiverPercent" returnClass="int"> <![CDATA[ int def parkingWaiverPercent(str:householdType) { if (householdType == "SUBSISTENCE") { return 100; } else if (householdType == "MARTYR") { return 100; } else if (householdType == "DISABLED") { return 100; } else if (householdType == "LOW_INCOME") { return 50; } else { return 0; } } ]]> </java>
<java name="qualifiedArea" returnClass="double"> <![CDATA[ double def qualifiedArea(double:size, double:perCapita, int:family, str:householdType) { double cap = 15.0; if (householdType == "SUBSISTENCE") { cap = 30.0; } else if (householdType == "MARTYR") { cap = 30.0; } else if (householdType == "DISABLED") { cap = 30.0; } else if (householdType == "ELDERLY_ALONE") { cap = 30.0; } else if (householdType == "LOW_INCOME") { cap = 20.0; } if (perCapita <= cap) { return size; } double limit = cap * family; if (size < limit) { return size; } else { return limit; } } ]]> </java>
</javas>PropertyWaiverService.java
Section titled “PropertyWaiverService.java”package com.github.paohaijiao.demo.service;
import com.github.paohaijiao.demo.PropertyWaiverRules;import com.github.paohaijiao.demo.model.PropertyWaiverApplication;import com.github.paohaijiao.demo.model.PropertyWaiverDecision;
import java.math.BigDecimal;import java.math.RoundingMode;
/** * 场景 39:物业费/停车费减免资格判定 */public class PropertyWaiverService {
private final PropertyWaiverRules rules;
public PropertyWaiverService(PropertyWaiverRules rules) { this.rules = rules; }
public PropertyWaiverDecision review(PropertyWaiverApplication a) { PropertyWaiverDecision d = new PropertyWaiverDecision(); d.setHouseholdId(a.getHouseholdId());
String reject = rules.hardRejectReason(a.isRentingOut(), a.isIllegalConstruction(), a.getOverdueMonths(), a.isParkingSafetyViolation()); if (!"PASS".equals(reject)) { d.setEligible(false); d.setRejectReason(reject); d.setQualifiedArea(0.0); return d; } d.setEligible(true);
int propertyPercent = rules.propertyWaiverPercent(a.getHouseholdType(), a.isVacant()); int parkingPercent = rules.parkingWaiverPercent(a.getHouseholdType()); d.setPropertyWaiverPercent(propertyPercent); d.setParkingWaiverPercent(parkingPercent);
double area; if ("ORDINARY".equals(a.getHouseholdType()) && a.isVacant()) { area = a.getPropertySize(); } else { area = rules.qualifiedArea(a.getPropertySize(), a.getPerCapitaArea(), a.getFamilySize(), a.getHouseholdType()); } d.setQualifiedArea(money(area)); if (area < a.getPropertySize()) { d.addNote("人均建筑面积超出保障标准,超出的 " + money(a.getPropertySize() - area) + " ㎡ 部分不予减免"); }
double propertyAmount = money(area * a.getMonthlyFeePerSqm() * a.getMonthsApplied() * propertyPercent / 100.0); d.setPropertyWaiverAmount(propertyAmount);
double parkingAmount = 0.0; if (a.getParkingSpaceCount() >= 1 && parkingPercent > 0) { parkingAmount = money(a.getMonthlyParkingFee() * a.getMonthsApplied() * parkingPercent / 100.0); if (a.getParkingSpaceCount() > 1) { d.addNote("停车费减免仅限 1 个登记车位,其余 " + (a.getParkingSpaceCount() - 1) + " 个车位正常缴纳"); } } d.setParkingWaiverAmount(parkingAmount); d.setTotalWaiver(money(propertyAmount + parkingAmount));
if ("ORDINARY".equals(a.getHouseholdType()) && a.isVacant()) { d.addNote("空置房物业费按应缴标准的 70% 收取(减免 30%),停车费不免"); } return d; }
private double money(double v) { return BigDecimal.valueOf(v).setScale(2, RoundingMode.HALF_UP).doubleValue(); }}PropertyWaiverServiceTest.java
Section titled “PropertyWaiverServiceTest.java”package com.github.paohaijiao.demo;
import com.github.paohaijiao.demo.model.PropertyWaiverApplication;import com.github.paohaijiao.demo.model.PropertyWaiverDecision;import com.github.paohaijiao.demo.service.PropertyWaiverService;import com.github.paohaijiao.xml.JQuickJava;import org.junit.Assert;import org.junit.Before;import org.junit.Test;
/** * 场景 39:物业费/停车费减免资格判定 * <p> * 6 组形态:低保户物业停车全免、烈属全免无车位、低保边缘比例减免与车位限制、 * 空置房 70% 缴纳、四类一票否决、独居老人超保障面积封顶。 */public class PropertyWaiverServiceTest {
private PropertyWaiverService service;
@Before public void setUp() { PropertyWaiverRules rules = JQuickJava.create() .createApi(PropertyWaiverRules.class, "demo/property-waiver.xml"); this.service = new PropertyWaiverService(rules); }
/** * 低保户 80 ㎡ 四口之家、6 个月、1 车位 → 物业停车全免 3000 */ @Test public void shouldFullyWaiveForSubsistenceHousehold() { PropertyWaiverApplication a = base("H001", "SUBSISTENCE"); a.setPropertySize(80); a.setFamilySize(4); a.setPerCapitaArea(20); a.setMonthlyFeePerSqm(2.5); a.setMonthsApplied(6); a.setParkingSpaceCount(1); a.setMonthlyParkingFee(300);
PropertyWaiverDecision d = service.review(a);
Assert.assertTrue(d.isEligible()); Assert.assertEquals(80.0, d.getQualifiedArea(), 0.0001); Assert.assertEquals(100, d.getPropertyWaiverPercent()); Assert.assertEquals(100, d.getParkingWaiverPercent()); Assert.assertEquals(1200.0, d.getPropertyWaiverAmount(), 0.0001); Assert.assertEquals(1800.0, d.getParkingWaiverAmount(), 0.0001); Assert.assertEquals(3000.0, d.getTotalWaiver(), 0.0001); }
/** * 烈属 90 ㎡ 人均 30 ㎡ 不超标、全年、无车位 → 全免 2160 */ @Test public void shouldFullyWaivePropertyForMartyrWithoutParking() { PropertyWaiverApplication a = base("H002", "MARTYR"); a.setPropertySize(90); a.setFamilySize(3); a.setPerCapitaArea(30); a.setMonthlyFeePerSqm(2); a.setMonthsApplied(12); a.setParkingSpaceCount(0); a.setMonthlyParkingFee(0);
PropertyWaiverDecision d = service.review(a);
Assert.assertTrue(d.isEligible()); Assert.assertEquals(90.0, d.getQualifiedArea(), 0.0001); Assert.assertEquals(2160.0, d.getPropertyWaiverAmount(), 0.0001); Assert.assertEquals(0.0, d.getParkingWaiverAmount(), 0.0001); Assert.assertEquals(2160.0, d.getTotalWaiver(), 0.0001); }
/** * 低保边缘 70 ㎡ 不超标、2 车位 → 物业 60%、1 个车位停车 50% */ @Test public void shouldPartiallyWaiveForLowIncomeAndLimitOneParkingSpace() { PropertyWaiverApplication a = base("H003", "LOW_INCOME"); a.setPropertySize(70); a.setFamilySize(4); a.setPerCapitaArea(17.5); a.setMonthlyFeePerSqm(2); a.setMonthsApplied(12); a.setParkingSpaceCount(2); a.setMonthlyParkingFee(200);
PropertyWaiverDecision d = service.review(a);
Assert.assertEquals(60, d.getPropertyWaiverPercent()); Assert.assertEquals(70.0, d.getQualifiedArea(), 0.0001); Assert.assertEquals(1008.0, d.getPropertyWaiverAmount(), 0.0001); Assert.assertEquals(1200.0, d.getParkingWaiverAmount(), 0.0001); Assert.assertEquals(2208.0, d.getTotalWaiver(), 0.0001); Assert.assertTrue(join(d).contains("停车费减免仅限 1 个登记车位")); }
/** * 普通业主 100 ㎡ 空置 6 个月 → 按整套减免 30%,停车不免 */ @Test public void shouldWaiveThirtyPercentForVacantApartment() { PropertyWaiverApplication a = base("H004", "ORDINARY"); a.setPropertySize(100); a.setFamilySize(3); a.setPerCapitaArea(33.33); a.setMonthlyFeePerSqm(2); a.setMonthsApplied(6); a.setParkingSpaceCount(1); a.setMonthlyParkingFee(200); a.setVacant(true);
PropertyWaiverDecision d = service.review(a);
Assert.assertTrue(d.isEligible()); Assert.assertEquals(100.0, d.getQualifiedArea(), 0.0001); Assert.assertEquals(30, d.getPropertyWaiverPercent()); Assert.assertEquals(360.0, d.getPropertyWaiverAmount(), 0.0001); Assert.assertEquals(0.0, d.getParkingWaiverAmount(), 0.0001); Assert.assertTrue(join(d).contains("空置房物业费按应缴标准的 70% 收取")); }
/** * 出租、违建、欠费 8 个月、飞线充电 → 四类一票否决 */ @Test public void shouldHardRejectFourVetoConditions() { String[][] cases = { {"LOW_INCOME", "RENTING"}, {"SUBSISTENCE", "ILLEGAL"}, {"MARTYR", "OVERDUE"}, {"DISABLED", "SAFETY"} }; for (String[] c : cases) { PropertyWaiverApplication a = base("H005", c[0]); a.setPropertySize(60); a.setFamilySize(2); a.setPerCapitaArea(30); a.setMonthlyFeePerSqm(2); a.setMonthsApplied(12); if ("RENTING".equals(c[1])) { a.setRentingOut(true); } else if ("ILLEGAL".equals(c[1])) { a.setIllegalConstruction(true); } else if ("OVERDUE".equals(c[1])) { a.setOverdueMonths(8); } else { a.setParkingSafetyViolation(true); } PropertyWaiverDecision d = service.review(a); Assert.assertFalse(c[0] + " 应被否决", d.isEligible()); Assert.assertEquals(c[0] + " 否决原因码不符", c[1], d.getRejectReason()); Assert.assertEquals(0.0, d.getTotalWaiver(), 0.0001); } }
/** * 独居老人 60 ㎡(人均超 30 ㎡保障线)→ 仅 30 ㎡享 50% 减免 */ @Test public void shouldCapElderlyWaiverAtSecurityAreaStandard() { PropertyWaiverApplication a = base("H006", "ELDERLY_ALONE"); a.setPropertySize(60); a.setFamilySize(1); a.setPerCapitaArea(60); a.setMonthlyFeePerSqm(2); a.setMonthsApplied(12); a.setParkingSpaceCount(0);
PropertyWaiverDecision d = service.review(a);
Assert.assertEquals(50, d.getPropertyWaiverPercent()); Assert.assertEquals(30.0, d.getQualifiedArea(), 0.0001); Assert.assertEquals(360.0, d.getPropertyWaiverAmount(), 0.0001); Assert.assertTrue(join(d).contains("超出的 30.0 ㎡ 部分不予减免")); }
private PropertyWaiverApplication base(String id, String type) { PropertyWaiverApplication a = new PropertyWaiverApplication(); a.setHouseholdId(id); a.setOwnerName("测试业主"); a.setHouseholdType(type); a.setPropertySize(0); a.setFamilySize(1); a.setPerCapitaArea(0); a.setMonthlyFeePerSqm(0); a.setMonthsApplied(0); a.setParkingSpaceCount(0); a.setMonthlyParkingFee(0); a.setVacant(false); a.setRentingOut(false); a.setIllegalConstruction(false); a.setOverdueMonths(0); a.setParkingSafetyViolation(false); return a; }
private String join(PropertyWaiverDecision d) { StringBuilder sb = new StringBuilder(); for (String n : d.getNotes()) { sb.append(n).append(';'); } return sb.toString(); }}Run & verified results
Section titled “Run & verified results”Run at the project root:
mvn test -Dtest=PropertyWaiverServiceTestThe tests cover 6 household shapes (the one-vote veto cases loop over 4 household types inside a single test method); the assertions correspond one-to-one with the source code:
| Test method | Business shape | Key assertions |
|---|---|---|
shouldFullyWaiveForSubsistenceHousehold |
Subsistence household, 80 ㎡ family of four (per-capita 20, under the line), 6 months, 1 parking space | Eligible; counted area 80; property/parking both 100%; property waiver 1200 (80×2.5×6), parking 1800 (300×6), total 3000 |
shouldFullyWaivePropertyForMartyrWithoutParking |
Martyr family, 90 ㎡ at per-capita 30 exactly at the line, full year, no parking space | Counted area 90; property waiver 2160 (90×2×12); parking 0; total 2160 |
shouldPartiallyWaiveForLowIncomeAndLimitOneParkingSpace |
Near-subsistence, 70 ㎡ (per-capita 17.5, under the 20 line), 2 parking spaces | Property 60%, counted 70 ㎡, waiver 1008; parking waived 50% on 1 space = 1200; total 2208; note contains “停车费减免仅限 1 个登记车位” |
shouldWaiveThirtyPercentForVacantApartment |
Ordinary owner, 100 ㎡ vacant for 6 months, 1 parking space | Whole unit counted (100 ㎡); property 30% waiver = 360 (100×2×6×30%); parking 0; note contains “空置房物业费按应缴标准的 70% 收取” |
shouldHardRejectFourVetoConditions |
Near-subsistence renting out, subsistence with illegal construction, martyr family 8 months in arrears, severely-disabled with fly-wire charging | All four ineligible; veto codes RENTING/ILLEGAL/OVERDUE/SAFETY respectively; total waiver 0 in all cases |
shouldCapElderlyWaiverAtSecurityAreaStandard |
Elderly living alone, 60 ㎡ single person (per-capita 60 exceeds the 30 ㎡ guarantee line) | Property 50%; counted area capped at 30 ㎡; waiver 360 (30×2×12×50%); note contains “超出的 30.0 ㎡ 部分不予减免” |
Technical highlights
Section titled “Technical highlights”- One-vote vetoes front-loaded with short circuit: once
hardRejectReasonreturns a reason code, the Service ends the flow immediately with counted area and amounts all zeroed; the veto priority (renting → illegal construction → arrears → safety) is expressed as a positive-condition sequence in the script, clear and auditable. - One method, one policy: the four rule methods — veto reason, property percentage, parking percentage, guaranteed area — are fully independent; the property and parking percentage tables are maintained separately, so adjusting one never harms the other.
- Service-side capping and fixed-amount backstops: the guaranteed-area rule returns the area for “whole unit under the line, capped at guarantee line × family size over the line”, while the Service compares it against the titled area and generates the shortfall note; vacant ordinary units take the whole-unit special case; the parking waiver is limited to 1 space on the Java side.
- Amounts exact to the cent: all amounts go through
BigDecimal+HALF_UPto two decimals; property, parking, and total uniformly use themoney()path, so livelihood subsidy amounts carry no floating-point residue. - Externalized rules with hot update: the household-type percentage table (100/60/50/30), the 6-month arrears flag line, and the 30/20 ㎡ per-capita guarantee lines all live in the XML — taking a project to another city only requires swapping the threshold table to reuse the whole skeleton.
- Proxy reuse, ASM, Java 8 / domestic-JDK friendly: the proxy is created once in
@Beforeand shared by all 6 shapes; the engine is based on dynamic proxies and ASM with no heavy dependencies, and can embed into property-billing systems on JDK 8 and domestic (Xinchuang) JDKs.