From ee089a8ac4a9d99ef0a0491bbf1d80a2d4fbc393 Mon Sep 17 00:00:00 2001
From: sinake <sinake1@qq.com>
Date: 星期二, 10 十一月 2026 09:15:54 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 ruoyi-project/src/main/java/com/ruoyi/project/mapper/ServiceFundtaxMapper.java               |    9 
 ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailVO.java                |   39 +
 ruoyi-common/src/main/java/com/ruoyi/common/tax/TaxtUtils.java                               |   12 
 ruoyi-project/src/main/java/com/ruoyi/project/mapper/CasePanoramaMapper.java                 |   28 +
 ruoyi-project/src/main/java/com/ruoyi/project/service/ICasePanoramaService.java              |   25 +
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/JacksonDateConfig.java              |  272 ++++++++++++
 ruoyi-project/src/main/resources/mapper/project/ServiceFundtaxMapper.xml                     |   14 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/CasePanoramaController.java       |   97 ++++
 ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetail.java                  |   39 +
 ruoyi-project/src/main/java/com/ruoyi/project/service/IServiceFunddetailService.java         |   12 
 ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFunddetailServiceImpl.java |  301 +++++++++----
 ruoyi-project/src/main/java/com/ruoyi/project/domain/vo/TaxMoneySumEO.java                   |   26 +
 ruoyi-project/src/main/resources/mapper/project/ServiceFunddetailMapper.xml                  |   22 +
 ruoyi-project/src/main/resources/mapper/project/CasePanoramaMapper.xml                       |   76 +++
 ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailShared.java            |   33 +
 ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFund.java                        |   39 +
 ruoyi-project/src/main/resources/mapper/project/ServiceFundMapper.xml                        |    8 
 ruoyi-project/src/main/resources/mapper/project/ServiceFunddetailSharedMapper.xml            |    6 
 ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFundServiceImpl.java       |   13 
 ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFundtaxServiceImpl.java    |  106 ++++-
 ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFundtax.java                     |   45 +
 ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailExcel.java             |   34 +
 22 files changed, 1,086 insertions(+), 170 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/CasePanoramaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/CasePanoramaController.java
new file mode 100644
index 0000000..150837c
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/CasePanoramaController.java
@@ -0,0 +1,97 @@
+package com.ruoyi.web.controller.project;
+
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.project.domain.CasePanorama;
+import com.ruoyi.project.domain.CasePanoramaReq;
+import com.ruoyi.project.service.ICasePanoramaService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 妗堜緥鍏ㄦ櫙
+ *
+ * @author ruoyi
+ * @date 2026-10-28
+ */
+@Slf4j
+@Api("妗堜緥鍏ㄦ櫙")
+@RestController
+@RequestMapping("/project/casePanorama")
+public class CasePanoramaController extends BaseController {
+
+    @Autowired
+    private ICasePanoramaService casePanoramaService;
+
+    /**
+     * 鏌ヨ妗堜緥鍏ㄦ櫙
+     */
+    @ApiOperation("鏌ヨ妗堜緥鍏ㄦ櫙")
+    @GetMapping("/list")
+    public TableDataInfo list(CasePanoramaReq req) {
+        startPage();
+        return getDataTable(casePanoramaService.selectCasePanoramaList(req));
+    }
+
+    /**
+     * 瀵煎嚭妗堜緥鍏ㄦ櫙
+     */
+    @ApiOperation("瀵煎嚭妗堜緥鍏ㄦ櫙")
+    @Log(title = "妗堜緥鍏ㄦ櫙", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CasePanoramaReq req) {
+        List<CasePanorama> list = casePanoramaService.selectCasePanoramaList(req);
+        for (CasePanorama row : list) {
+            blankZero(row);
+        }
+        ExcelUtil<CasePanorama> util = new ExcelUtil<CasePanorama>(CasePanorama.class);
+        return util.exportExcel(list, "妗堜緥鍏ㄦ櫙鏁版嵁");
+    }
+
+    /**
+     * 涓氬姟缁勪笅鎷夐�夐」
+     */
+    @ApiOperation("涓氬姟缁勪笅鎷夐�夐」")
+    @GetMapping("/deptOptions")
+    public AjaxResult deptOptions() {
+        return AjaxResult.success(casePanoramaService.selectDeptNames());
+    }
+
+    /**
+     * 閲戦 0 瀵煎嚭涓虹┖
+     */
+    private void blankZero(CasePanorama row) {
+        row.setTotalCost(blankZero(row.getTotalCost()));
+        row.setDonorFamilyCost(blankZero(row.getDonorFamilyCost()));
+        row.setMedCost(blankZero(row.getMedCost()));
+        row.setExpertCost(blankZero(row.getExpertCost()));
+        row.setItemCode34(blankZero(row.getItemCode34()));
+        row.setItemCode42(blankZero(row.getItemCode42()));
+        row.setItemCode46(blankZero(row.getItemCode46()));
+        row.setItemCode50(blankZero(row.getItemCode50()));
+        row.setItemCode44(blankZero(row.getItemCode44()));
+        row.setItemCode47(blankZero(row.getItemCode47()));
+        row.setItemCode48(blankZero(row.getItemCode48()));
+        row.setItemCode21(blankZero(row.getItemCode21()));
+        row.setItemCode12(blankZero(row.getItemCode12()));
+        row.setItemCode17(blankZero(row.getItemCode17()));
+        row.setItemCode23(blankZero(row.getItemCode23()));
+        row.setItemCode25(blankZero(row.getItemCode25()));
+    }
+
+    private BigDecimal blankZero(BigDecimal value) {
+        return (value == null || value.compareTo(BigDecimal.ZERO) == 0) ? null : value;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/tax/TaxtUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/tax/TaxtUtils.java
index a54caba..a28381d 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/tax/TaxtUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/tax/TaxtUtils.java
@@ -66,6 +66,10 @@
 
     /**
      * 閫氳繃绋庡悗宸ヨ祫锛岀畻鍑虹◣鍓嶅伐璧�
+     * <p>
+     * 娉ㄦ剰锛氶櫎鏁板繀椤荤敤瀛楃涓�/甯搁噺鏋勯�犵殑绮剧‘鍊笺�傚師鍏堝啓鎴� {@code new BigDecimal(0.84)} 绛夛紝
+     * 浼氭妸 double 鐨勪簩杩涘埗璇樊甯﹁繘闄ゆ硶锛堝 8313.06 / 0.84 鍙樻垚 9896.500000鈥�001锛夛紝
+     * 鍐嶅彔鍔犲悜涓婂彇鏁村氨澶氬嚭 1 鍒嗛挶锛屽鑷粹�滅◣鍚庡弽绠楃◣鍓嶁�濇棤娉曡繕鍘燂紙8300.00 绫婚噾棰濆弽瑙e嚭 10000.03锛夈��
      *
      * @param money
      * @return
@@ -78,21 +82,21 @@
         }
 //绗竴涓弬鏁版槸闄ゆ暟锛岀浜屼釜鍙傛暟浠h〃淇濈暀鍑犱綅灏忔暟锛岀涓変釜浠h〃鐨勬槸浣跨敤鐨勬ā寮�
         if (money.doubleValue() > 800 && money.doubleValue() <= 3360) {
-            taxMoney = money.subtract(new BigDecimal(160)).divide(new BigDecimal(0.8), 2, BigDecimal.ROUND_CEILING);
+            taxMoney = money.subtract(new BigDecimal(160)).divide(new BigDecimal("0.8"), 2, BigDecimal.ROUND_CEILING);
         }
 
         if (money.doubleValue() > 3360 && money.doubleValue() <= 21000) {
-            taxMoney = money.divide(new BigDecimal(0.84), 2, BigDecimal.ROUND_CEILING);
+            taxMoney = money.divide(new BigDecimal("0.84"), 2, BigDecimal.ROUND_CEILING);
         }
 
         if (money.doubleValue() > 21000 && money.doubleValue() <= 49500) {
             money = money.subtract(new BigDecimal(2000));
-            taxMoney = money.divide(new BigDecimal(0.76), 2, BigDecimal.ROUND_CEILING);
+            taxMoney = money.divide(new BigDecimal("0.76"), 2, BigDecimal.ROUND_CEILING);
         }
 
         if (money.doubleValue() > 49500) {
             money = money.subtract(new BigDecimal(7000));
-            taxMoney = money.divide(new BigDecimal(0.68), 2, BigDecimal.ROUND_CEILING);
+            taxMoney = money.divide(new BigDecimal("0.68"), 2, BigDecimal.ROUND_CEILING);
         }
 
 
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/JacksonDateConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/JacksonDateConfig.java
new file mode 100644
index 0000000..206a4e3
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/JacksonDateConfig.java
@@ -0,0 +1,272 @@
+package com.ruoyi.framework.config;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.BeanDescription;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.DeserializationConfig;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializationConfig;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder;
+import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
+import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
+import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
+import com.fasterxml.jackson.databind.ser.ContextualSerializer;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.io.IOException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TimeZone;
+
+/**
+ * 鏃堕棿鏍煎紡鍏ㄥ眬閰嶇疆锛氭帴鍙e嚭鍙備竴寰嬬簿纭埌鍒嗭紙{@code yyyy-MM-dd HH:mm}锛夛紝鍏ュ弬瀹芥澗鍏煎甯�/涓嶅甫绉掋��
+ *
+ * <p><b>涓轰粈涔堢敤鍏ㄥ眬閰嶇疆鑰屼笉鏄�愬瓧娈垫敼娉ㄨВ锛�</b>绯荤粺閲�
+ * {@code @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")} 鏈� 182 澶勩�亄@code @DateTimeFormat} 73 澶勶紝
+ * 閫愪釜鏀规棦瀹规槗婕忥紙婕忎竴澶勫氨鏄彁浜� 400锛夛紝涔熻鐩栦笉鍒版湭鍔犳敞瑙g殑 {@code Date} 瀛楁銆�
+ * 杩欓噷鐢� Jackson 鐨� {@link BeanSerializerModifier} / {@link BeanDeserializerModifier}
+ * 鍦�<b>涓嶆敼浠讳綍娉ㄨВ</b>鐨勫墠鎻愪笅缁熶竴鏍煎紡鍖栧彛寰勩��
+ *
+ * <p><b>瑙勫垯锛�</b>
+ * <ol>
+ *   <li>搴忓垪鍖栵細鎵�鏈� {@code Date} 杈撳嚭 {@code yyyy-MM-dd HH:mm}锛堟部鐢�
+ *       {@link ApplicationConfig} 閰嶇疆鐨� JVM 榛樿鏃跺尯锛涘瓧娈典笂鏄惧紡澹版槑浜�
+ *       {@code @JsonFormat(timezone=...)} 鐨勪粛鎸夊叾鏃跺尯锛夛紱</li>
+ *   <li>鍙嶅簭鍒楀寲锛氬吋瀹� {@code yyyy-MM-dd HH:mm:ss} / {@code yyyy-MM-dd HH:mm} /
+ *       {@code yyyy-MM-dd} / 鏂滄潬鍒嗛殧 / ISO8601 / 鏃堕棿鎴� 鈥斺�� 杩欐牱鍓嶇鍥炲~"鏃犵"鐨勫�煎師鏍锋彁浜や篃涓嶄細 400锛�</li>
+ *   <li>杩愮淮鏃ュ織锛堟搷浣滄棩蹇�/鐧诲綍鏃ュ織/瀹氭椂浠诲姟鏃ュ織锛�<b>淇濈暀绉�</b>锛屼究浜庢帓鏌ラ棶棰樸��</li>
+ * </ol>
+ *
+ * <p><b>涓嶅奖鍝嶇殑鑼冨洿锛�</b>鏁版嵁搴撳瓨鍌紙浠嶄负 datetime锛岀浣嶇収甯镐繚鐣欙級銆�
+ * Excel 瀵煎叆瀵煎嚭锛堣蛋 {@code @Excel.dateFormat}锛屾湭鏀瑰姩锛夈��
+ * 鑷磋繙鍗忓悓鎺ㄩ�佹姤鏂囷紙鑷缓 {@code SimpleDateFormat}锛屾湭鏀瑰姩锛夈��
+ * 閽夐拤娑堟伅鏃堕棿锛坽@code FundNotifyMessageBuilder} 鑷缓鏍煎紡锛夈��
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class JacksonDateConfig {
+
+    /** 鏃犵鏍煎紡 */
+    private static final String PATTERN_NO_SECONDS = "yyyy-MM-dd HH:mm";
+    /** 鏈夌鏍煎紡锛堣繍缁存棩蹇楃敤锛� */
+    private static final String PATTERN_WITH_SECONDS = "yyyy-MM-dd HH:mm:ss";
+
+    /** 淇濈暀绉掔殑绫伙細杩愮淮鏃ュ織锛岀瀵规帓鏌ユ湁鐢� */
+    private static final Set<String> KEEP_SECONDS_CLASSES = new HashSet<String>(Arrays.asList(
+            "com.ruoyi.system.domain.SysOperLog",
+            "com.ruoyi.system.domain.SysLogininfor",
+            "com.ruoyi.quartz.domain.SysJobLog"
+    ));
+
+    /** 鍙嶅簭鍒楀寲灏濊瘯椤哄簭锛氫粠鏈�鍏蜂綋鍒版渶瀹芥澗 */
+    private static final String[] PARSE_PATTERNS = new String[]{
+            "yyyy-MM-dd HH:mm:ss.SSS",
+            "yyyy-MM-dd HH:mm:ss",
+            "yyyy-MM-dd HH:mm",
+            "yyyy-MM-dd'T'HH:mm:ss.SSS",
+            "yyyy-MM-dd'T'HH:mm:ss",
+            "yyyy-MM-dd'T'HH:mm",
+            "yyyy/MM/dd HH:mm:ss",
+            "yyyy/MM/dd HH:mm",
+            "yyyy-MM-dd",
+            "yyyy/MM/dd",
+            "yyyyMMddHHmmss",
+            "yyyyMMdd"
+    };
+
+    /**
+     * 2026-10-15 鏀归�狅細涓嶅啀鐢� {@code Jackson2ObjectMapperBuilderCustomizer} + {@code modulesToInstall}銆�
+     *
+     * <p><b>涓轰粈涔堟敼锛�</b>{@code Jackson2ObjectMapperBuilder.modulesToInstall(...)} 鐨勮涔夋槸
+     * "璁剧疆"妯″潡鍒楄〃锛堜笉鏄拷鍔狅級锛岃�� Spring Boot 鑷韩涔熺敤鍚屼竴鏂规硶娉ㄥ唽瀹冭嚜甯︾殑妯″潡锛圝avaTime 绛夛級锛�
+     * 涓や釜瀹氬埗鍣ㄤ簰鐩歌鐩栵紝璋佸悗鎵ц璋佺殑鍒楄〃鐢熸晥銆傚疄娴嬪悗鏋滐細鏈ā鍧楄涓㈡帀 鈥斺��
+     * 琛ㄧ幇涓�"绫诲湪鍖呴噷銆乥ean 涔熷垱寤轰簡锛屼絾 Date 鐨勫鏉捐В鏋愪笌鍘荤搴忓垪鍖栭兘涓嶈捣浣滅敤"锛�
+     * 鍓嶇鎸� {@code yyyy-MM-dd} 鎻愪氦鏃剁洿鎺� 400锛圕annot deserialize ... expected format yyyy-MM-dd HH:mm:ss锛夈��
+     *
+     * <p>鏀逛负鎶婃ā鍧楀0鏄庢垚 {@code SimpleModule} bean锛歋pring Boot 閫氳繃 {@code ObjectProvider<Module>}
+     * 缁熶竴鏀堕泦鎵�鏈� Module bean 骞朵竴娆℃�у畨瑁咃紝涓庡畾鍒跺櫒鐨勬墽琛岄『搴忔棤鍏炽��
+     */
+    @Bean
+    public SimpleModule dateNoSecondsModule() {
+        SimpleModule module = new SimpleModule("dateNoSecondsModule");
+        module.addSerializer(Date.class, new NoSecondsDateSerializer());
+        module.setSerializerModifier(new NoSecondsDateSerializerModifier());
+        module.setDeserializerModifier(new LenientDateDeserializerModifier());
+        // 鍚姩鑷瘉锛氳繖鏉℃棩蹇楀嚭鐜板嵆璇存槑妯″潡宸茶鍒涘缓骞朵細琚� Spring Boot 瀹夎
+        LoggerFactory.getLogger(JacksonDateConfig.class).info(
+                "[JacksonDateConfig] 宸插惎鐢細Date 鍑哄弬鍘荤({})锛屽叆鍙傚鏉惧吋瀹�({})",
+                PATTERN_NO_SECONDS, String.join(" / ", PARSE_PATTERNS));
+        return module;
+    }
+
+    /**
+     * 搴忓垪鍖栧櫒锛氭寜鍒嗛挓杈撳嚭銆�
+     * 鍙綔鐢ㄤ簬搴忓垪鍖栵紝<b>涓嶅奖鍝嶅叆鍙傝В鏋�</b>銆�
+     */
+    static class NoSecondsDateSerializer extends JsonSerializer<Date> implements ContextualSerializer {
+
+        private final DateTimeFormatter formatter;
+
+        NoSecondsDateSerializer() {
+            this.formatter = null;
+        }
+
+        private NoSecondsDateSerializer(TimeZone timeZone, boolean keepSeconds) {
+            this.formatter = DateTimeFormatter
+                    .ofPattern(keepSeconds ? PATTERN_WITH_SECONDS : PATTERN_NO_SECONDS)
+                    .withZone((timeZone == null ? TimeZone.getDefault() : timeZone).toZoneId());
+        }
+
+        @Override
+        public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) {
+            TimeZone timeZone = resolveTimeZone(prov.getConfig().getTimeZone(),
+                    property == null ? null : property.getMember());
+            return new NoSecondsDateSerializer(timeZone, isKeepSeconds(property == null ? null : property.getMember()));
+        }
+
+        @Override
+        public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+            if (value == null) {
+                gen.writeNull();
+                return;
+            }
+            if (formatter != null) {
+                gen.writeString(formatter.format(value.toInstant()));
+                return;
+            }
+            // 鍏滃簳锛氭湭琚� contextualize 鏃舵寜褰撳墠閰嶇疆鏃跺尯銆佹棤绉掕緭鍑�
+            gen.writeString(DateTimeFormatter.ofPattern(PATTERN_NO_SECONDS)
+                    .withZone(serializers.getConfig().getTimeZone().toZoneId())
+                    .format(value.toInstant()));
+        }
+    }
+
+    /**
+     * 璁� Bean 灞炴�т笂鐨勬棩鏈熶篃璧颁笂闈㈢殑搴忓垪鍖栧櫒銆�
+     * 瀛楁绾� {@code @JsonFormat} 鐢熸垚鐨勫簭鍒楀寲鍣ㄤ紭鍏堢骇鏇撮珮锛屽繀椤诲湪杩欓噷鏇挎崲鎺夛紝鍚﹀垯娉ㄨВ瀛楁浠嶅甫绉掋��
+     */
+    static class NoSecondsDateSerializerModifier extends BeanSerializerModifier {
+        @Override
+        @SuppressWarnings({"unchecked", "rawtypes"})
+        public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc,
+                                                         List<BeanPropertyWriter> beanProperties) {
+            boolean keepSeconds = KEEP_SECONDS_CLASSES.contains(beanDesc.getBeanClass().getName());
+            for (BeanPropertyWriter writer : beanProperties) {
+                if (Date.class.isAssignableFrom(writer.getType().getRawClass())) {
+                    TimeZone timeZone = resolveTimeZone(config.getTimeZone(), writer.getMember());
+                    writer.assignSerializer((JsonSerializer) new NoSecondsDateSerializer(timeZone, keepSeconds));
+                }
+            }
+            return beanProperties;
+        }
+    }
+
+    /**
+     * 鍏ュ弬瑙f瀽锛氬吋瀹瑰甫绉�/涓嶅甫绉�/绾棩鏈�/ISO/鏃堕棿鎴筹紝閬垮厤"鍑哄弬鏃犵銆佸洖濉悗鍐嶆彁浜�"瀵艰嚧 400銆�
+     */
+    static class LenientDateDeserializerModifier extends BeanDeserializerModifier {
+        @Override
+        @SuppressWarnings({"unchecked", "rawtypes"})
+        public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BeanDescription beanDesc,
+                                                     BeanDeserializerBuilder builder) {
+            Iterator<SettableBeanProperty> properties = builder.getProperties();
+            List<SettableBeanProperty> replaced = new ArrayList<SettableBeanProperty>();
+            while (properties.hasNext()) {
+                SettableBeanProperty property = properties.next();
+                if (property.getType() != null && Date.class.isAssignableFrom(property.getType().getRawClass())) {
+                    TimeZone timeZone = resolveTimeZone(config.getTimeZone(), property.getMember());
+                    replaced.add(property.withValueDeserializer(new LenientDateDeserializer(timeZone)));
+                }
+            }
+            // 涓嶈兘杈归亶鍘嗚竟鏀癸紝鍏堟敹闆嗗啀鏇挎崲
+            for (SettableBeanProperty property : replaced) {
+                builder.addOrReplaceProperty(property, true);
+            }
+            return builder;
+        }
+    }
+
+    /** 瀹芥澗鏃ユ湡瑙f瀽鍣� */
+    static class LenientDateDeserializer extends JsonDeserializer<Date> {
+
+        private final TimeZone timeZone;
+
+        LenientDateDeserializer(TimeZone timeZone) {
+            this.timeZone = timeZone == null ? TimeZone.getDefault() : timeZone;
+        }
+
+        @Override
+        public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+            if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
+                return new Date(p.getLongValue());
+            }
+            String text = p.getValueAsString();
+            if (text == null || text.trim().isEmpty()) {
+                return null;
+            }
+            text = text.trim();
+            for (String pattern : PARSE_PATTERNS) {
+                SimpleDateFormat format = new SimpleDateFormat(pattern);
+                format.setLenient(false);
+                format.setTimeZone(timeZone);
+                ParsePosition position = new ParsePosition(0);
+                Date parsed = format.parse(text, position);
+                // 蹇呴』鏁翠覆琚秷璐癸紝鍚﹀垯 "yyyy-MM-dd" 浼氭妸 "2026-10-08 15:23" 鐨勬椂鍒嗛潤榛樹涪鎺�
+                if (parsed != null && position.getIndex() == text.length()) {
+                    return parsed;
+                }
+            }
+            try {
+                return Date.from(Instant.parse(text));
+            } catch (Exception ignore) {
+                // 钀藉埌涓嬮潰缁熶竴鎶ラ敊
+            }
+            throw ctxt.weirdStringException(text, Date.class,
+                    "鏃犳硶瑙f瀽鐨勬椂闂存牸寮忥紝鏀寔 yyyy-MM-dd[ HH:mm[:ss]]");
+        }
+    }
+
+    /** 灞炴�т笂鏄惧紡澹版槑鐨勬椂鍖轰紭鍏堬紝鍚﹀垯鐢ㄥ叏灞�閰嶇疆锛堝嵆 JVM 榛樿鏃跺尯锛� */
+    private static TimeZone resolveTimeZone(TimeZone fallback, AnnotatedMember member) {
+        if (member != null) {
+            try {
+                JsonFormat jsonFormat = member.getAnnotation(JsonFormat.class);
+                if (jsonFormat != null && jsonFormat.timezone() != null
+                        && !jsonFormat.timezone().isEmpty()
+                        && !"##default".equals(jsonFormat.timezone())) {
+                    return TimeZone.getTimeZone(jsonFormat.timezone());
+                }
+            } catch (Exception ignore) {
+                // 鍙栦笉鍒版敞璁版椂鐢ㄥ叏灞�鏃跺尯
+            }
+        }
+        return fallback == null ? TimeZone.getDefault() : fallback;
+    }
+
+    /** 杩愮淮鏃ュ織绫讳繚鐣欑 */
+    private static boolean isKeepSeconds(AnnotatedMember member) {
+        return member != null && KEEP_SECONDS_CLASSES.contains(member.getDeclaringClass().getName());
+    }
+}
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFund.java b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFund.java
index edd6442..1040455 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFund.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFund.java
@@ -299,10 +299,37 @@
     private Double pretaxcost;
 
     /**
-     * 绋庡悗閲戦
+     * 澧炲�肩◣鍚堣
      */
-    @ApiModelProperty("绋庡悗閲戦")
-    @Excel(name = "绋庡悗閲戦")
+    @ApiModelProperty("澧炲�肩◣鍚堣")
+    @Excel(name = "澧炲�肩◣")
+    private Double vatCost;
+
+    /**
+     * 鍩庡缓绋庡悎璁�
+     */
+    @ApiModelProperty("鍩庡缓绋庡悎璁�")
+    @Excel(name = "鍩庡缓绋�")
+    private Double cityTaxCost;
+
+    /**
+     * 鍔冲姟绋庡墠鍚堣
+     */
+    @ApiModelProperty("鍔冲姟绋庡墠鍚堣")
+    @Excel(name = "鍔冲姟绋庡墠")
+    private Double laborPretaxCost;
+
+    /**
+     * 绋庡彛寰勭増鏈細v1=鍘嗗彶鍙e緞锛堟棤澧炲�肩◣/鍩庡缓绋庯級锛寁2=鏂板鍙e緞
+     */
+    @ApiModelProperty("绋庡彛寰勭増鏈�")
+    private String taxVersion;
+
+    /**
+     * 鍔冲姟绋庡悗锛堝師鈥滅◣鍚庨噾棰濃�濓級
+     */
+    @ApiModelProperty("鍔冲姟绋庡悗")
+    @Excel(name = "鍔冲姟绋庡悗")
     private Double taxedcost;
 
     /**
@@ -387,10 +414,10 @@
     private Long fundTaxId = null;
 
     /**
-     * 绋庨噾
+     * 鍔冲姟涓◣鍚堣锛堝師鈥滅◣閲戔�濓級
      */
-    @ApiModelProperty("绋庨噾")
-    @Excel(name = "绋庨噾")
+    @ApiModelProperty("鍔冲姟涓◣鍚堣")
+    @Excel(name = "鍔冲姟涓◣")
     private Double taxcost;
 
     @ApiModelProperty("鍗忓弸瑕佹眰鍐嶆鍙戣捣鏃讹紝甯︿笂杩欎釜鍊�")
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetail.java b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetail.java
index 437f4cb..d709f5e 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetail.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetail.java
@@ -217,11 +217,38 @@
     private Double prepaidamount;
 
     /**
-     * 鎵g◣閲戦
+     * 鍔冲姟涓◣锛堝師鈥滄墸绋庨噾棰濃�濓級
      */
-    @ApiModelProperty("鎵g◣閲戦")
-    @Excel(name = "鎵g◣閲戦")
+    @ApiModelProperty("鍔冲姟涓◣")
+    @Excel(name = "鍔冲姟涓◣")
     private Double taxamount;
+
+    /**
+     * 澧炲�肩◣
+     */
+    @ApiModelProperty("澧炲�肩◣")
+    @Excel(name = "澧炲�肩◣")
+    private Double vatAmount;
+
+    /**
+     * 鍩庡缓绋�
+     */
+    @ApiModelProperty("鍩庡缓绋�")
+    @Excel(name = "鍩庡缓绋�")
+    private Double cityTaxAmount;
+
+    /**
+     * 鍔冲姟绋庡墠閲戦
+     */
+    @ApiModelProperty("鍔冲姟绋庡墠閲戦")
+    @Excel(name = "鍔冲姟绋庡墠")
+    private Double laborPretaxAmount;
+
+    /**
+     * 绋庡彛寰勭増鏈細v1=鍘嗗彶鍙e緞锛堟棤澧炲�肩◣/鍩庡缓绋庯級锛寁2=鏂板鍙e緞
+     */
+    @ApiModelProperty("绋庡彛寰勭増鏈�")
+    private String taxVersion;
 
     /**
      * 鍙戠エ寮犳暟
@@ -237,10 +264,10 @@
     @Excel(name = "涓婁紶鏃堕棿")
     private BigDecimal reimbursementamount;
     /**
-     * 绋庡悗閲戦
+     * 鍔冲姟绋庡悗锛堝師鈥滅◣鍚庨噾棰濃�濓級
      */
-    @ApiModelProperty("绋庡悗閲戦")
-    @Excel(name = "绋庡悗閲戦")
+    @ApiModelProperty("鍔冲姟绋庡悗")
+    @Excel(name = "鍔冲姟绋庡悗")
     private Double taxedamount;
 
     /**
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailExcel.java b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailExcel.java
index ce4672a..1e3edb3 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailExcel.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailExcel.java
@@ -72,13 +72,39 @@
     @Excel(name = "绋庡墠閲戦")
     private Double amount;
 
-
+    /**
+     * 澧炲�肩◣
+     */
+    @ApiModelProperty("澧炲�肩◣")
+    @Excel(name = "澧炲�肩◣")
+    private Double vatAmount;
 
     /**
-     * 绋庡悗閲戦
+     * 鍩庡缓绋�
      */
-    @ApiModelProperty("绋庡悗閲戦")
-    @Excel(name = "绋庡悗閲戦")
+    @ApiModelProperty("鍩庡缓绋�")
+    @Excel(name = "鍩庡缓绋�")
+    private Double cityTaxAmount;
+
+    /**
+     * 鍔冲姟绋庡墠
+     */
+    @ApiModelProperty("鍔冲姟绋庡墠")
+    @Excel(name = "鍔冲姟绋庡墠")
+    private Double laborPretaxAmount;
+
+    /**
+     * 鍔冲姟涓◣
+     */
+    @ApiModelProperty("鍔冲姟涓◣")
+    @Excel(name = "鍔冲姟涓◣")
+    private Double taxamount;
+
+    /**
+     * 鍔冲姟绋庡悗
+     */
+    @ApiModelProperty("鍔冲姟绋庡悗")
+    @Excel(name = "鍔冲姟绋庡悗")
     private Double taxedamount;
 
     /**
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailShared.java b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailShared.java
index 64f6c0b..272bce7 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailShared.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailShared.java
@@ -242,20 +242,41 @@
     private Double amount;
 
     /**
-     * 鎵g◣閲戦
+     * 鍔冲姟涓◣锛堝師鈥滄墸绋庨噾棰濃�濓級
      */
-    @ApiModelProperty("鎵g◣閲戦")
-    @Excel(name = "鎵g◣閲戦")
+    @ApiModelProperty("鍔冲姟涓◣")
+    @Excel(name = "鍔冲姟涓◣")
     private Double taxamount;
 
     /**
-     * 绋庡悗閲戦
+     * 鍔冲姟绋庡悗锛堝師鈥滅◣鍚庨噾棰濃�濓級
      */
-    @ApiModelProperty("绋庡悗閲戦")
-    @Excel(name = "绋庡悗閲戦")
+    @ApiModelProperty("鍔冲姟绋庡悗")
+    @Excel(name = "鍔冲姟绋庡悗")
     private Double taxedamount;
 
     /**
+     * 澧炲�肩◣
+     */
+    @ApiModelProperty("澧炲�肩◣")
+    @Excel(name = "澧炲�肩◣")
+    private Double vatAmount;
+
+    /**
+     * 鍩庡缓绋�
+     */
+    @ApiModelProperty("鍩庡缓绋�")
+    @Excel(name = "鍩庡缓绋�")
+    private Double cityTaxAmount;
+
+    /**
+     * 鍔冲姟绋庡墠閲戦
+     */
+    @ApiModelProperty("鍔冲姟绋庡墠閲戦")
+    @Excel(name = "鍔冲姟绋庡墠")
+    private Double laborPretaxAmount;
+
+    /**
      * 棰勬敮閲戦
      */
     @ApiModelProperty("棰勬敮閲戦")
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailVO.java b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailVO.java
index 3690179..44570d4 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailVO.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetailVO.java
@@ -202,11 +202,38 @@
     private Double prepaidamount;
 
     /**
-     * 鎵g◣閲戦
+     * 鍔冲姟涓◣锛堝師鈥滄墸绋庨噾棰濃�濓級
      */
-    @ApiModelProperty("鎵g◣閲戦")
-    @Excel(name = "鎵g◣閲戦")
+    @ApiModelProperty("鍔冲姟涓◣")
+    @Excel(name = "鍔冲姟涓◣")
     private Double taxamount;
+
+    /**
+     * 澧炲�肩◣
+     */
+    @ApiModelProperty("澧炲�肩◣")
+    @Excel(name = "澧炲�肩◣")
+    private Double vatAmount;
+
+    /**
+     * 鍩庡缓绋�
+     */
+    @ApiModelProperty("鍩庡缓绋�")
+    @Excel(name = "鍩庡缓绋�")
+    private Double cityTaxAmount;
+
+    /**
+     * 鍔冲姟绋庡墠閲戦
+     */
+    @ApiModelProperty("鍔冲姟绋庡墠閲戦")
+    @Excel(name = "鍔冲姟绋庡墠")
+    private Double laborPretaxAmount;
+
+    /**
+     * 绋庡彛寰勭増鏈細v1=鍘嗗彶鍙e緞锛堟棤澧炲�肩◣/鍩庡缓绋庯級锛寁2=鏂板鍙e緞
+     */
+    @ApiModelProperty("绋庡彛寰勭増鏈�")
+    private String taxVersion;
 
     /**
      * 鍙戠エ寮犳暟
@@ -216,10 +243,10 @@
     private Long invoicecount;
 
     /**
-     * 绋庡悗閲戦
+     * 鍔冲姟绋庡悗锛堝師鈥滅◣鍚庨噾棰濃�濓級
      */
-    @ApiModelProperty("绋庡悗閲戦")
-    @Excel(name = "绋庡悗閲戦")
+    @ApiModelProperty("鍔冲姟绋庡悗")
+    @Excel(name = "鍔冲姟绋庡悗")
     private Double taxedamount;
 
     /**
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFundtax.java b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFundtax.java
index 9f391b7..c378ffa 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFundtax.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFundtax.java
@@ -98,24 +98,51 @@
     private BigDecimal pretaxamount;
 
     /**
-     * 绋庡悗閲戦鍚堣
+     * 澧炲�肩◣鍚堣
      */
-    @ApiModelProperty("绋庡悗閲戦鍚堣")
-    @Excel(name = "绋庡悗閲戦鍚堣")
+    @ApiModelProperty("澧炲�肩◣鍚堣")
+    @Excel(name = "澧炲�肩◣鍚堣")
+    private BigDecimal vatAmount;
+
+    /**
+     * 鍩庡缓绋庡悎璁�
+     */
+    @ApiModelProperty("鍩庡缓绋庡悎璁�")
+    @Excel(name = "鍩庡缓绋庡悎璁�")
+    private BigDecimal cityTaxAmount;
+
+    /**
+     * 鍔冲姟绋庡墠鍚堣
+     */
+    @ApiModelProperty("鍔冲姟绋庡墠鍚堣")
+    @Excel(name = "鍔冲姟绋庡墠鍚堣")
+    private BigDecimal laborPretaxAmount;
+
+    /**
+     * 绋庡彛寰勭増鏈細v1=鍘嗗彶鍙e緞锛堟棤澧炲�肩◣/鍩庡缓绋庯級锛寁2=鏂板鍙e緞
+     */
+    @ApiModelProperty("绋庡彛寰勭増鏈�")
+    private String taxVersion;
+
+    /**
+     * 鍔冲姟绋庡悗锛堝師鈥滅◣鍚庨噾棰濆悎璁♀�濓級
+     */
+    @ApiModelProperty("鍔冲姟绋庡悗鍚堣")
+    @Excel(name = "鍔冲姟绋庡悗鍚堣")
     private BigDecimal taxedamount;
 
     /**
-     * 璐圭敤鎬婚噾棰�
+     * 鍔冲姟涓◣鍚堣
      */
-    @ApiModelProperty("璐圭敤鎬婚噾棰�")
-    @Excel(name = "璐圭敤鎬婚噾棰�")
+    @ApiModelProperty("鍔冲姟涓◣鍚堣")
+    @Excel(name = "鍔冲姟涓◣鍚堣")
     private BigDecimal taxamount;
 
     /**
-     * 鎵g◣閲戦
+     * 鍔冲姟涓◣鍚堣锛堝巻鍙插瓧娈� tax_money锛岄〉闈⑩�滄墸绋庨噾棰濃�濆彇姝ゅ垪锛�
      */
-    @ApiModelProperty("鎵g◣閲戦")
-    @Excel(name = "鎵g◣閲戦")
+    @ApiModelProperty("鍔冲姟涓◣锛堟墸绋庨噾棰濓級")
+    @Excel(name = "鍔冲姟涓◣")
     private BigDecimal taxMoney;
 
     /**
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/domain/vo/TaxMoneySumEO.java b/ruoyi-project/src/main/java/com/ruoyi/project/domain/vo/TaxMoneySumEO.java
index d777773..ef77183 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/domain/vo/TaxMoneySumEO.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/domain/vo/TaxMoneySumEO.java
@@ -7,19 +7,35 @@
 public class TaxMoneySumEO extends BaseEntity {
 
     /**
-     * 绋庡墠鎬婚
+     * 绋庡墠鎬婚锛圓mount 鍚堣锛�
      */
     private double amounts;
 
     /**
-     * 绋庢�婚
+     * 澧炲�肩◣鎬婚
+     */
+    private double vatAmounts;
+
+    /**
+     * 鍩庡缓绋庢�婚
+     */
+    private double cityTaxAmounts;
+
+    /**
+     * 鍔冲姟绋庡墠鎬婚锛堝姵鍔′釜绋庣疮璁″熀鏁帮級
+     */
+    private double laborPretaxAmounts;
+
+    /**
+     * 鍔冲姟涓◣鎬婚
      */
     private double taxAmounts;
 
     /**
-     * 绋庡悗鎬婚
+     * 鍔冲姟绋庡悗鎬婚
      */
     private double taxedAmounts;
+
     /**
      * 搴忓彿
      */
@@ -29,5 +45,9 @@
      */
     private String IDCardNo;
 
+    /**
+     * 褰撴湀宸插瓨鍦ㄧ殑鍘嗗彶鍙e緞锛坴1锛夋槑缁嗘潯鏁帮紝鐢ㄤ簬闃绘鍚屼竴鏈堜唤 v1/v2 娣风畻
+     */
+    private Long v1Count;
 
 }
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/mapper/CasePanoramaMapper.java b/ruoyi-project/src/main/java/com/ruoyi/project/mapper/CasePanoramaMapper.java
new file mode 100644
index 0000000..fa67089
--- /dev/null
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/mapper/CasePanoramaMapper.java
@@ -0,0 +1,28 @@
+package com.ruoyi.project.mapper;
+
+import com.ruoyi.project.domain.CasePanorama;
+import com.ruoyi.project.domain.CasePanoramaReq;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 妗堜緥鍏ㄦ櫙Mapper
+ *
+ * @author ruoyi
+ * @date 2026-10-28
+ */
+@Mapper
+public interface CasePanoramaMapper {
+
+    /**
+     * 鏌ヨ妗堜緥鍏ㄦ櫙
+     */
+    List<CasePanorama> selectCasePanoramaList(@Param("req") CasePanoramaReq req);
+
+    /**
+     * 鏌ヨ涓氬姟缁勯�夐」
+     */
+    List<String> selectDeptNames();
+}
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/mapper/ServiceFundtaxMapper.java b/ruoyi-project/src/main/java/com/ruoyi/project/mapper/ServiceFundtaxMapper.java
index 3d36dee..4e0bdfe 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/mapper/ServiceFundtaxMapper.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/mapper/ServiceFundtaxMapper.java
@@ -29,4 +29,13 @@
      * @return
      */
     public Integer getMaxFundTaxId();
+
+    /**
+     * 瀵瑰綋鍓嶆壒娆℃眹鎬诲崟鍔犺閿侊紙SELECT ... FOR UPDATE锛夛紝闃叉骞跺彂閲嶅绠楃◣銆�
+     * 蹇呴』鍦ㄤ簨鍔′腑璋冪敤銆�
+     *
+     * @param id 姹囨�诲崟 ID
+     * @return 姹囨�诲崟锛堜笉瀛樺湪杩斿洖 null锛�
+     */
+    public ServiceFundtax selectByIdForUpdate(Long id);
 }
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/service/ICasePanoramaService.java b/ruoyi-project/src/main/java/com/ruoyi/project/service/ICasePanoramaService.java
new file mode 100644
index 0000000..42c283e
--- /dev/null
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/service/ICasePanoramaService.java
@@ -0,0 +1,25 @@
+package com.ruoyi.project.service;
+
+import com.ruoyi.project.domain.CasePanorama;
+import com.ruoyi.project.domain.CasePanoramaReq;
+
+import java.util.List;
+
+/**
+ * 妗堜緥鍏ㄦ櫙Service
+ *
+ * @author ruoyi
+ * @date 2026-10-28
+ */
+public interface ICasePanoramaService {
+
+    /**
+     * 鏌ヨ妗堜緥鍏ㄦ櫙
+     */
+    List<CasePanorama> selectCasePanoramaList(CasePanoramaReq req);
+
+    /**
+     * 鏌ヨ涓氬姟缁勯�夐」
+     */
+    List<String> selectDeptNames();
+}
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/service/IServiceFunddetailService.java b/ruoyi-project/src/main/java/com/ruoyi/project/service/IServiceFunddetailService.java
index b2e1da2..122bcfd 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/service/IServiceFunddetailService.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/service/IServiceFunddetailService.java
@@ -1,5 +1,6 @@
 package com.ruoyi.project.service;
 
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -62,12 +63,21 @@
     List<ServiceFunddetailVO> getFundDetail(Long id);
 
     /**
-     * 鏍规嵁鏉′欢绠楃◣
+     * 鏍规嵁鏉′欢绠楃◣锛堝姵鍔′釜绋� + 澧炲�肩◣ + 鍩庡缓绋庯級
      *
      * @param serviceFunddetails
      */
     public Boolean calculateTax(List<ServiceFunddetail> serviceFunddetails, Map<String, TaxMoneySumEO> tempTaxSumMap);
 
+    /**
+     * 鏍规嵁鏉′欢绠楃◣锛屽苟鎸囧畾鏈壒绠楃◣鏃堕棿锛堝悓鎵规槑缁� tax_time 涓�鑷达級
+     *
+     * @param serviceFunddetails 鏄庣粏鍒楄〃
+     * @param tempTaxSumMap      鏈湀绱缂撳瓨
+     * @param taxTime            鏈绠楃◣鏃堕棿
+     */
+    public Boolean calculateTax(List<ServiceFunddetail> serviceFunddetails, Map<String, TaxMoneySumEO> tempTaxSumMap, Date taxTime);
+
 //    public Boolean calculateTax2(List<ServiceFunddetail> serviceFunddetails);
 
     /**
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFundServiceImpl.java b/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFundServiceImpl.java
index 49f934e..2d362d4 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFundServiceImpl.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFundServiceImpl.java
@@ -1705,10 +1705,23 @@
             //閫氳繃鍙楃泭浜哄悕绉帮紝灏嗙◣鍓嶃�佺◣鍚庣殑鍊肩浉鍔�
             Map<String, Double> sumAmount = serviceFunddetails.stream().collect(Collectors.groupingBy(ServiceFunddetail::getBeneficiaryname, Collectors.summingDouble(ServiceFunddetail::getAmount)));
             Map<String, Double> sumTaxdAmount = serviceFunddetails.stream().collect(Collectors.groupingBy(ServiceFunddetail::getBeneficiaryname, Collectors.summingDouble(ServiceFunddetail::getTaxedamount)));
+            // 鏂板鍙e緞锛氬鍊肩◣銆佸煄寤虹◣銆佸姵鍔$◣鍓嶃�佸姵鍔′釜绋庢寜鍙楃泭浜哄悎璁�
+            Map<String, Double> sumVat = serviceFunddetails.stream().collect(Collectors.groupingBy(ServiceFunddetail::getBeneficiaryname,
+                    Collectors.summingDouble(d -> d.getVatAmount() == null ? 0.0 : d.getVatAmount())));
+            Map<String, Double> sumCityTax = serviceFunddetails.stream().collect(Collectors.groupingBy(ServiceFunddetail::getBeneficiaryname,
+                    Collectors.summingDouble(d -> d.getCityTaxAmount() == null ? 0.0 : d.getCityTaxAmount())));
+            Map<String, Double> sumLaborPretax = serviceFunddetails.stream().collect(Collectors.groupingBy(ServiceFunddetail::getBeneficiaryname,
+                    Collectors.summingDouble(d -> d.getLaborPretaxAmount() == null ? 0.0 : d.getLaborPretaxAmount())));
+            Map<String, Double> sumTax = serviceFunddetails.stream().collect(Collectors.groupingBy(ServiceFunddetail::getBeneficiaryname,
+                    Collectors.summingDouble(d -> d.getTaxamount() == null ? 0.0 : d.getTaxamount())));
 
             for (String key : sumAmount.keySet()) {
                 ServiceFunddetailExcel serviceFunddetailExcel = new ServiceFunddetailExcel();
                 serviceFunddetailExcel.setAmount(sumAmount.getOrDefault(key, 0.0));
+                serviceFunddetailExcel.setVatAmount(sumVat.getOrDefault(key, 0.0));
+                serviceFunddetailExcel.setCityTaxAmount(sumCityTax.getOrDefault(key, 0.0));
+                serviceFunddetailExcel.setLaborPretaxAmount(sumLaborPretax.getOrDefault(key, 0.0));
+                serviceFunddetailExcel.setTaxamount(sumTax.getOrDefault(key, 0.0));
                 serviceFunddetailExcel.setTaxedamount(sumTaxdAmount.getOrDefault(key, 0.0));
                 for (ServiceFunddetail serviceFunddetail2 : serviceFunddetails) {
                     if (serviceFunddetail2.getBeneficiaryname().equals(key)) {
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFunddetailServiceImpl.java b/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFunddetailServiceImpl.java
index 5a31d9d..6bf6c64 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFunddetailServiceImpl.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFunddetailServiceImpl.java
@@ -13,6 +13,7 @@
 import com.ruoyi.common.exception.base.BaseException;
 import com.ruoyi.common.tax.PerformanceTaxtUtils;
 import com.ruoyi.common.tax.TaxtUtils;
+import com.ruoyi.common.tax.VatTaxUtils;
 import com.ruoyi.common.utils.bean.DtoConversionUtils;
 import com.ruoyi.project.domain.*;
 import com.ruoyi.project.domain.vo.*;
@@ -253,15 +254,22 @@
         Long fundid = serviceFunddetail.getFundid();
         ServiceFund serviceFund = serviceFundMapper.selectById(fundid);
         if (ObjectUtils.isNotEmpty(serviceFund)) {
-            Double pretax = serviceFund.getPretaxcost();
-            Double aftertax = serviceFund.getTaxedcost();
-            pretax = pretax - serviceFunddetail.getAmount();
-            aftertax = aftertax - serviceFunddetail.getTaxedamount();
-            Double amount = pretax + aftertax;
+            // 閲戦涓�寰嬬敤 BigDecimal 绱姞/鎵e噺锛岄伩鍏嶆诞鐐瑰熬宸�
+            BigDecimal pretax = toMoney(serviceFund.getPretaxcost()).subtract(toMoney(serviceFunddetail.getAmount()));
+            BigDecimal aftertax = toMoney(serviceFund.getTaxedcost()).subtract(toMoney(serviceFunddetail.getTaxedamount()));
+            BigDecimal vat = toMoney(serviceFund.getVatCost()).subtract(toMoney(serviceFunddetail.getVatAmount()));
+            BigDecimal cityTax = toMoney(serviceFund.getCityTaxCost()).subtract(toMoney(serviceFunddetail.getCityTaxAmount()));
+            BigDecimal laborPretax = toMoney(serviceFund.getLaborPretaxCost()).subtract(toMoney(serviceFunddetail.getLaborPretaxAmount()));
+            BigDecimal tax = toMoney(serviceFund.getTaxcost()).subtract(toMoney(serviceFunddetail.getTaxamount()));
+            BigDecimal amount = pretax.add(aftertax);
 
-            serviceFund.setPretaxcost(pretax);
-            serviceFund.setTaxedcost(aftertax);
-            serviceFund.setAmountrequested(amount);
+            serviceFund.setPretaxcost(pretax.doubleValue());
+            serviceFund.setTaxedcost(aftertax.doubleValue());
+            serviceFund.setVatCost(vat.doubleValue());
+            serviceFund.setCityTaxCost(cityTax.doubleValue());
+            serviceFund.setLaborPretaxCost(laborPretax.doubleValue());
+            serviceFund.setTaxcost(tax.doubleValue());
+            serviceFund.setAmountrequested(amount.doubleValue());
             int updateAmount = serviceFundMapper.updateById(serviceFund);
         }
         return serviceFunddetailMapper.deleteById(id);
@@ -285,145 +293,228 @@
     }
 
     /**
-     * 鎵归噺绠楃◣涓绘柟娉�
-     * 1. 鏍¢獙鍙傛暟
-     * 2. 鎺掑簭鏄庣粏锛屼繚璇佺◣鏃堕棿涓虹┖鐨勬帓鍦ㄥ悗闈�
-     * 3. 閬嶅巻姣忔潯鏄庣粏锛屽垎韬唤璇佸彿涓虹┖鍜屼笉涓虹┖涓ょ鎯呭喌鍒嗗埆澶勭悊
-     * - 韬唤璇佸彿涓虹┖锛氱洿鎺ユ寜瑙勫垯璧嬪�肩◣鍚庨噾棰濄�佺◣閲�
-     * - 韬唤璇佸彿涓嶄负绌猴細
-     * a. 鏌ヨ鏈湀绗竴澶╋紝鑾峰彇鏈�澶у簭鍙�
-     * b. 鏌ヨ鏈湀绱绋庡墠銆佺◣閲戙�佺◣鍚庨噾棰�
-     * c. 鏍规嵁"绋庡墠/绋庡悗"绫诲瀷鍒嗗埆璁$畻绋庨噾銆佺◣鍚庨噾棰�
-     * d. 璁剧疆绠楃◣鏃堕棿銆佸簭鍙风瓑
-     * 4. 绱鏈壒娆℃�荤◣鍓嶃�佺◣鍚庨噾棰�
-     * 5. 鎵归噺鏇存柊鎵�鏈夋槑缁�
-     * 6. 鏇存柊涓昏〃ServiceFund鐨勬�婚噾棰濄�佺畻绋庢椂闂淬�佺姸鎬�
+     * 鎵归噺绠楃◣涓绘柟娉曪紙鍔冲姟涓◣ + 澧炲�肩◣ + 鍩庡缓绋庯紝v2 鍙e緞锛�
+     * <p>
+     * 閲戦妯″瀷锛�
+     * <pre>
+     * 绋庡墠褰曞叆锛歏 = ceil(P 脳 1%)銆丆 = ceil(V 脳 3.5%)銆丩 = P - V - C銆�
+     *          T = 鍔冲姟涓◣(褰撴湀绱 L) - 鍘熺疮璁� T銆丯 = L - T
+     * 绋庡悗褰曞叆锛歂绱 = 鍘熺疮璁� N + N銆丩绱 = getTaxationBefore(N绱)銆�
+     *          L = L绱 - 鍘熺疮璁� L銆乀 = L - N銆丳/V/C = solveGross(L)
+     * 鏃犺韩浠借瘉锛歏 = C = T = 0锛孡 = N = P
+     * </pre>
      *
      * @param serviceFunddetails 璐圭敤鏄庣粏鍒楄〃
+     * @param tempTaxSumMap      鏈湀绱閲戦缂撳瓨锛堟寜韬唤璇佸彿锛�
      * @return 鏄惁绠楃◣鎴愬姛
      */
     @Override
     public Boolean calculateTax(List<ServiceFunddetail> serviceFunddetails, Map<String, TaxMoneySumEO> tempTaxSumMap) {
+        return calculateTax(serviceFunddetails, tempTaxSumMap, new Date());
+    }
+
+    /**
+     * 鎵归噺绠楃◣锛堟寚瀹氭湰鎵圭畻绋庢椂闂达紝淇濊瘉鍚屾壒鏄庣粏 tax_time 涓�鑷达級
+     *
+     * @param serviceFunddetails 璐圭敤鏄庣粏鍒楄〃
+     * @param tempTaxSumMap      鏈湀绱閲戦缂撳瓨锛堟寜韬唤璇佸彿锛�
+     * @param taxTime            鏈绠楃◣鏃堕棿
+     * @return 鏄惁绠楃◣鎴愬姛
+     */
+    @Override
+    public Boolean calculateTax(List<ServiceFunddetail> serviceFunddetails, Map<String, TaxMoneySumEO> tempTaxSumMap, Date taxTime) {
         // 1. 鏍¢獙鍙傛暟
         if (CollectionUtils.isEmpty(serviceFunddetails)) {
             throw new BaseException("绠楃◣鏉′欢涓虹┖锛岃妫�鏌ュ悗锛屽啀杩涜璁$畻");
         }
-        // 2. 鎺掑簭锛岀◣鏃堕棿涓虹┖鐨勬帓鍚庨潰
-        serviceFunddetails.sort(Comparator.comparing(obj -> ObjectUtils.isEmpty(obj.getTaxTime()) ? 1 : 0));
+        // 2. 鎺掑簭锛氱◣鏃堕棿涓虹┖鐨勬帓鍚庨潰锛屽啀鎸� id 淇濊瘉鍚屾壒椤哄簭绋冲畾
+        serviceFunddetails.sort(Comparator
+                .comparing((ServiceFunddetail obj) -> ObjectUtils.isEmpty(obj.getTaxTime()) ? 1 : 0)
+                .thenComparing(obj -> obj.getId() == null ? Long.MAX_VALUE : obj.getId()));
 
-        // 3. 鑾峰彇鏈壒娆undid鍙婁富琛ㄤ俊鎭�
+        // 3. 鑾峰彇鏈壒娆� fundid 鍙婁富琛ㄤ俊鎭�
         Long fundid = serviceFunddetails.get(0).getFundid();
         log.info("绠楃◣鐨刦undid鐨勫�间负锛歿}", fundid);
         ServiceFund serviceFund1 = serviceFundMapper.selectById(fundid);
-        log.info("fund琛ㄧ殑fundtextime鍊间负锛歿}", serviceFund1.getFundtaxtime());
-        // 4. 鍒濆鍖栫疮璁¢噾棰濄�佸緟鏇存柊鏄庣粏鍒楄〃銆佸簭鍙风紦瀛樸�佺疮璁¢噾棰濈紦瀛�
-        BigDecimal pretaxcost = BigDecimal.ZERO;
-        BigDecimal taxedcost = BigDecimal.ZERO;
+        if (serviceFund1 == null) {
+            throw new BaseException("鏈壘鍒拌垂鐢ㄧ敵璇峰崟锛孖D=" + fundid);
+        }
+        // 鏄庣粏 tax_time 缁熶竴浣跨敤鏈绠楃◣鏃堕棿
+        if (taxTime == null) {
+            taxTime = new Date();
+        }
 
-        //鍒涘缓涓�涓敤浜庡瓨鏀锯�滈渶瑕佹洿鏂板埌鏁版嵁搴撶殑ServiceFunddetail瀵硅薄鈥濈殑鍒楄〃
+        // 4. 鏈壒娆″悎璁★紙鍏ㄩ儴鐢� BigDecimal锛岀姝� double 绱姞锛�
+        BigDecimal pretaxTotal = BigDecimal.ZERO;
+        BigDecimal vatTotal = BigDecimal.ZERO;
+        BigDecimal cityTaxTotal = BigDecimal.ZERO;
+        BigDecimal laborPretaxTotal = BigDecimal.ZERO;
+        BigDecimal taxTotal = BigDecimal.ZERO;
+        BigDecimal taxedTotal = BigDecimal.ZERO;
+
         List<ServiceFunddetail> updateList = new ArrayList<>();
 
-        // 5. 閬嶅巻姣忔潯鏄庣粏锛屽垎鎯呭喌澶勭悊
+        // 5. 閬嶅巻姣忔潯鏄庣粏
         for (ServiceFunddetail detail : serviceFunddetails) {
-            // 5.1 韬唤璇佸彿涓虹┖锛岀洿鎺ヨ祴鍊硷紙涓�浜涗汉鎴栧叕鍙革紝涓嶉渶瑕佺畻绋庯級
+            if (detail.getAmount() == null) {
+                detail.setAmount(0.0);
+            }
+            if (detail.getTaxedamount() == null) {
+                detail.setTaxedamount(0.0);
+            }
+            // 鏈嶅姟璇存槑涓虹┖鎸夆�滈潪绋庡悗鈥濆鐞�
+            String scopeName = detail.getServicesscopename() == null ? "" : detail.getServicesscopename().trim();
+            boolean afterTax = scopeName.contains("绋庡悗");
+
+            // 5.1 韬唤璇佸彿涓虹┖锛氫笉鎵e鍊肩◣/鍩庡缓绋�/鍔冲姟涓◣
             if (StringUtils.isEmpty(detail.getIdcardno())) {
-                if (StringUtils.isEmpty(detail.getServicesscopename()) || !detail.getServicesscopename().contains("绋庡悗")) {
-                    // 鏅�氭槑缁嗭紝绋庡悗閲戦=鐢宠閲戦
-                    detail.setTaxedamount(detail.getAmount());
-                } else {
-                    // 绋庡悗鏄庣粏锛岀敵璇烽噾棰�=绋庡悗閲戦
-                    detail.setAmount(detail.getTaxedamount());
-                }
-                // 绱鏈壒娆℃�婚噾棰�
-                pretaxcost = pretaxcost.add(BigDecimal.valueOf(detail.getAmount()));
-                taxedcost = taxedcost.add(BigDecimal.valueOf(detail.getTaxedamount()));
+                BigDecimal p = afterTax ? toMoney(detail.getTaxedamount()) : toMoney(detail.getAmount());
+                detail.setAmount(p.doubleValue());
+                detail.setVatAmount(0.0);
+                detail.setCityTaxAmount(0.0);
+                detail.setLaborPretaxAmount(p.doubleValue());
                 detail.setTaxamount(0.0);
+                detail.setTaxedamount(p.doubleValue());
+                detail.setTaxVersion(VatTaxUtils.TAX_VERSION_V2);
+                detail.setTaxTime(taxTime);
                 updateList.add(detail);
+
+                pretaxTotal = pretaxTotal.add(p);
+                laborPretaxTotal = laborPretaxTotal.add(p);
+                taxedTotal = taxedTotal.add(p);
                 continue;
             }
 
-            // 5.2 韬唤璇佸彿涓嶄负绌猴紝闇�鏌ュ巻鍙茬疮璁¢噾棰濄�佸簭鍙�
+            // 5.2 韬唤璇佸彿涓嶄负绌猴細鏈湀绱 + 鍒嗘。绠楃◣
             String idcard = detail.getIdcardno().trim();
 
-            // 5.2.1 鏌ヨ鏈湀绱閲戦锛堢紦瀛橀伩鍏嶉噸澶嶆煡搴擄級
-            TaxMoneySumEO taxSum = tempTaxSumMap.getOrDefault(idcard, null);
+            // 5.2.1 鍙栨湰鏈堢疮璁★紙缂撳瓨閬垮厤閲嶅鏌ュ簱锛�
+            TaxMoneySumEO taxSum = tempTaxSumMap.get(idcard);
             if (taxSum == null) {
                 taxSum = new TaxMoneySumEO();
-                taxSum.setXh(1L);
-                detail.setXh(1L);
+                taxSum.setXh(0L);
                 tempTaxSumMap.put(idcard, taxSum);
-                detail.setAllAmount(taxSum.getAmounts());
+            }
+            long xh = (taxSum.getXh() == null ? 0L : taxSum.getXh()) + 1;
+            taxSum.setXh(xh);
+            detail.setXh(xh);
+            // 绱绋庡墠閲戦锛堜笉鍚湰绗旓級锛岀敤浜庨〉闈㈠睍绀�
+            detail.setAllAmount(taxSum.getAmounts());
+
+            BigDecimal prevAmount = toMoney(taxSum.getAmounts());
+            BigDecimal prevLaborPretax = toMoney(taxSum.getLaborPretaxAmounts());
+            BigDecimal prevTax = toMoney(taxSum.getTaxAmounts());
+            BigDecimal prevTaxed = toMoney(taxSum.getTaxedAmounts());
+            BigDecimal prevVat = toMoney(taxSum.getVatAmounts());
+            BigDecimal prevCityTax = toMoney(taxSum.getCityTaxAmounts());
+
+            BigDecimal pretax;
+            BigDecimal vat;
+            BigDecimal cityTax;
+            BigDecimal laborPretax;
+            BigDecimal taxAmount;
+            BigDecimal taxedAmount;
+
+            if (afterTax) {
+                // 5.2.2 绋庡悗褰曞叆锛氬厛鍙嶇畻鍔冲姟绋庡墠锛屽啀寰幆鍙嶈В绋庡墠/澧炲�肩◣/鍩庡缓绋�
+                taxedAmount = toMoney(detail.getTaxedamount());
+                BigDecimal sumTaxed = prevTaxed.add(taxedAmount);
+                BigDecimal sumLaborPretax = new BigDecimal(TaxtUtils.getTaxationBefore(sumTaxed));
+                laborPretax = VatTaxUtils.roundMoney(sumLaborPretax.subtract(prevLaborPretax));
+                if (laborPretax.signum() < 0) {
+                    // 閫愮瑪鍚戜笂鍙栨暣鍙兘甯︽潵鍑犲垎閽辩殑鍙嶇畻璇樊锛屽宸唴鎸� 0 澶勭悊锛涜秴鍑哄宸鏄庢暟鎹紓甯�
+                    if (laborPretax.abs().compareTo(new BigDecimal("0.05")) <= 0) {
+                        log.warn("绋庡悗閲戦鍙嶇畻鍔冲姟绋庡墠鍑虹幇璐熷熬宸紝宸叉寜 0 澶勭悊銆備汉鍛橈細{}锛屽弽绠楀姵鍔$◣鍓�={}锛屽師绱鍔冲姟绋庡墠={}",
+                                safeName(detail), sumLaborPretax, prevLaborPretax);
+                        laborPretax = BigDecimal.ZERO;
+                    } else {
+                        throw new BaseException("绋庡悗閲戦鍙嶇畻鍔冲姟绋庡墠澶辫触锛屼汉鍛橈細" + safeName(detail));
+                    }
+                }
+                taxAmount = VatTaxUtils.roundMoney(laborPretax.subtract(taxedAmount));
+                if (taxAmount.signum() < 0) {
+                    taxAmount = BigDecimal.ZERO;
+                }
+                VatTaxUtils.GrossAmount gross = VatTaxUtils.solveGross(laborPretax);
+                pretax = gross.getPretax();
+                vat = gross.getVat();
+                cityTax = gross.getCityTax();
             } else {
-                long xh = taxSum.getXh() + 1;
-                taxSum.setXh(xh);
-                tempTaxSumMap.put(idcard, taxSum);
-                detail.setXh(xh);
-                detail.setAllAmount(taxSum.getAmounts());
+                // 5.2.3 绋庡墠褰曞叆锛氬厛绠楀鍊肩◣/鍩庡缓绋�/鍔冲姟绋庡墠锛屽啀鎸夌疮璁″姵鍔$◣鍓嶇畻鍔冲姟涓◣
+                pretax = toMoney(detail.getAmount());
+                vat = VatTaxUtils.calcVat(pretax);
+                cityTax = VatTaxUtils.calcCityTax(vat);
+                laborPretax = VatTaxUtils.roundMoney(pretax.subtract(vat).subtract(cityTax));
+                BigDecimal sumLaborPretax = prevLaborPretax.add(laborPretax);
+                BigDecimal sumTax = new BigDecimal(TaxtUtils.getTaxation(sumLaborPretax));
+                taxAmount = VatTaxUtils.roundMoney(sumTax.subtract(prevTax));
+                if (taxAmount.signum() < 0) {
+                    taxAmount = BigDecimal.ZERO;
+                }
+                taxedAmount = VatTaxUtils.roundMoney(laborPretax.subtract(taxAmount));
             }
 
-            // 5.2.3 绠楃◣閫昏緫
-            if (detail.getServicesscopename().contains("绋庡悗")) {
-                // 绋庡悗鏄庣粏锛氱疮璁$◣鍚庨噾棰濓紝鍙嶆帹绋庡墠閲戦鍜岀◣閲�
-//                if (idcard.equals("362329199103224511")) {
-//                    log.info("鏈辩幃瀹�");
-//                }
-                BigDecimal newTaxedAmounts = BigDecimal.valueOf(taxSum.getTaxedAmounts()).add(BigDecimal.valueOf(detail.getTaxedamount()));
-                String taxationBefore = TaxtUtils.getTaxationBefore(newTaxedAmounts);
-                BigDecimal amountNow = new BigDecimal(taxationBefore).subtract(BigDecimal.valueOf(taxSum.getAmounts()));
-                BigDecimal tax = amountNow.subtract(BigDecimal.valueOf(detail.getTaxedamount()));
-                detail.setAmount(amountNow.doubleValue());
-                detail.setTaxamount(tax.doubleValue());
-                if (ObjectUtils.isEmpty(serviceFund1.getFundtaxtime())) {
-                    detail.setTaxTime(new Date());
-                } else {
-                    detail.setTaxTime(serviceFund1.getFundtaxtime());
-                }
-                taxSum.setAmounts((BigDecimal.valueOf(taxSum.getAmounts()).add(amountNow)).doubleValue());
-                taxSum.setTaxAmounts((BigDecimal.valueOf(taxSum.getTaxAmounts()).add(tax)).doubleValue());
-                taxSum.setTaxedAmounts(newTaxedAmounts.doubleValue());
-            } else {
-                // 绋庡墠鏄庣粏锛氱疮璁$◣鍓嶉噾棰濓紝绠楁�荤◣閲戯紝鍐嶇畻鏈绋庨噾鍜岀◣鍚庨噾棰�
-                BigDecimal newAmounts = BigDecimal.valueOf(taxSum.getAmounts()).add(BigDecimal.valueOf(detail.getAmount()));
-//                if (idcard.equals("362329199103224511")) {
-//                    log.info("鏈辩幃瀹�");
-//                }
-                String taxation = TaxtUtils.getTaxation(newAmounts);
-
-                BigDecimal taxAmountNow = new BigDecimal(taxation).subtract(new BigDecimal(String.valueOf(taxSum.getTaxAmounts())));
-                BigDecimal texdAfterNow = BigDecimal.valueOf(detail.getAmount()).subtract(taxAmountNow);
-                detail.setTaxamount(taxAmountNow.doubleValue());
-                detail.setTaxedamount(texdAfterNow.doubleValue());
-
-                if (ObjectUtils.isEmpty(serviceFund1.getFundtaxtime())) {
-                    detail.setTaxTime(new Date());
-                } else {
-                    detail.setTaxTime(serviceFund1.getFundtaxtime());
-                }
-                taxSum.setAmounts(newAmounts.doubleValue());
-                taxSum.setTaxAmounts((BigDecimal.valueOf(taxSum.getTaxAmounts()).add(taxAmountNow).doubleValue()));
-                taxSum.setTaxedAmounts((BigDecimal.valueOf(taxSum.getTaxedAmounts()).add(texdAfterNow)).doubleValue());
-            }
-
+            detail.setAmount(pretax.doubleValue());
+            detail.setVatAmount(vat.doubleValue());
+            detail.setCityTaxAmount(cityTax.doubleValue());
+            detail.setLaborPretaxAmount(laborPretax.doubleValue());
+            detail.setTaxamount(taxAmount.doubleValue());
+            detail.setTaxedamount(taxedAmount.doubleValue());
+            detail.setTaxVersion(VatTaxUtils.TAX_VERSION_V2);
+            detail.setTaxTime(taxTime);
             updateList.add(detail);
 
-            pretaxcost = pretaxcost.add(BigDecimal.valueOf(detail.getAmount()));
-            taxedcost = taxedcost.add(BigDecimal.valueOf(detail.getTaxedamount()));
+            // 5.2.4 鏇存柊鏈湀绱
+            taxSum.setAmounts(prevAmount.add(pretax).doubleValue());
+            taxSum.setVatAmounts(prevVat.add(vat).doubleValue());
+            taxSum.setCityTaxAmounts(prevCityTax.add(cityTax).doubleValue());
+            taxSum.setLaborPretaxAmounts(prevLaborPretax.add(laborPretax).doubleValue());
+            taxSum.setTaxAmounts(prevTax.add(taxAmount).doubleValue());
+            taxSum.setTaxedAmounts(prevTaxed.add(taxedAmount).doubleValue());
 
+            pretaxTotal = pretaxTotal.add(pretax);
+            vatTotal = vatTotal.add(vat);
+            cityTaxTotal = cityTaxTotal.add(cityTax);
+            laborPretaxTotal = laborPretaxTotal.add(laborPretax);
+            taxTotal = taxTotal.add(taxAmount);
+            taxedTotal = taxedTotal.add(taxedAmount);
         }
+
         // 6. 鎵归噺鏇存柊鎵�鏈夋槑缁�
         for (ServiceFunddetail d : updateList) {
             this.updateById(d);
         }
-        // 7. 鏇存柊涓昏〃ServiceFund
-        ServiceFund serviceFund = new ServiceFund();
-        serviceFund.setPretaxcost(pretaxcost.doubleValue());
-        serviceFund.setTaxedcost(taxedcost.doubleValue());
-        serviceFund.setId(serviceFunddetails.get(0).getFundid());
-        serviceFund.setFundtaxtime(new Date());
 
+        // 7. 鏇存柊涓昏〃 service_fund 鐨� 6 涓噾棰濄�佺畻绋庢椂闂淬�佺姸鎬併�佺増鏈�
+        ServiceFund serviceFund = new ServiceFund();
+        serviceFund.setId(fundid);
+        serviceFund.setPretaxcost(pretaxTotal.doubleValue());
+        serviceFund.setVatCost(vatTotal.doubleValue());
+        serviceFund.setCityTaxCost(cityTaxTotal.doubleValue());
+        serviceFund.setLaborPretaxCost(laborPretaxTotal.doubleValue());
+        serviceFund.setTaxcost(taxTotal.doubleValue());
+        serviceFund.setTaxedcost(taxedTotal.doubleValue());
+        serviceFund.setTaxVersion(VatTaxUtils.TAX_VERSION_V2);
+        serviceFund.setFundtaxtime(taxTime);
         serviceFund.setIstax(1);
         serviceFundMapper.updateById(serviceFund);
         return true;
+    }
+
+    /**
+     * null 瀹夊叏鐨勯噾棰濊浆鎹�
+     */
+    private static BigDecimal toMoney(Double value) {
+        return value == null ? BigDecimal.ZERO : BigDecimal.valueOf(value);
+    }
+
+    /**
+     * 鎶ラ敊鏃惰兘瀹氫綅鍒板叿浣撲汉鍛�
+     */
+    private static String safeName(ServiceFunddetail detail) {
+        String name = detail.getBeneficiaryname() == null ? "" : detail.getBeneficiaryname();
+        String idcard = detail.getIdcardno() == null ? "" : detail.getIdcardno();
+        return name + "(" + idcard + ")";
     }
 
 //    @Override
@@ -493,6 +584,10 @@
         //灏嗚绠楀嚭鏉ョ殑鏁版嵁鏀惧埌serviceFunddetail涓�
         serviceFunddetail.setTaxamount(nowSingleTax.doubleValue());
         serviceFunddetail.setTaxedamount(taxAfter.doubleValue());
+        // 缁╂晥涓嶅睘浜庝笓瀹惰垂锛氫笉璁$畻澧炲�肩◣/鍩庡缓绋庯紝鍔冲姟绋庡墠 = 绋庡墠閲戦
+        serviceFunddetail.setVatAmount(0.0);
+        serviceFunddetail.setCityTaxAmount(0.0);
+        serviceFunddetail.setLaborPretaxAmount(serviceFunddetail.getAmount());
         serviceFunddetail.setJxrq(nowMonth);
 
         save(serviceFunddetail);
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFundtaxServiceImpl.java b/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFundtaxServiceImpl.java
index 7664201..b9033a8 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFundtaxServiceImpl.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFundtaxServiceImpl.java
@@ -4,6 +4,7 @@
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.tax.VatTaxUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.project.domain.ServiceFund;
 import com.ruoyi.project.domain.ServiceFunddetail;
@@ -23,6 +24,7 @@
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.ZoneId;
 import java.time.temporal.TemporalAdjusters;
@@ -171,66 +173,128 @@
     /**
      * 鎵归噺绠楃◣涓诲叆鍙�
      * 1. 鏍¢獙鍙傛暟
-     * 2. 鏍¢獙鎵规鍚堟硶鎬э紙濡傛湁蹇呰锛�
-     * 3. 鏌ヨ鏈壒娆℃墍鏈塖erviceFund锛堟寜id鍗囧簭锛�
-     * 4. 棰勬煡璇㈡湰鏈堟墍鏈夎韩浠借瘉鍙风殑绱閲戦锛岀紦瀛樺埌Map锛屾彁鍗囧悗缁畻绋庢晥鐜�
-     * 5. 閬嶅巻姣忎釜ServiceFund锛屾壒閲忕畻绋�
+     * 2. 鍙厑璁告渶鏂版壒娆$畻绋�
+     * 3. 瀵瑰綋鍓嶆壒娆� service_fundtax 鍔犺閿侊紝闃插苟鍙戦噸澶嶇畻绋�
+     * 4. 鏌ヨ鏈壒娆℃墍鏈� ServiceFund锛堟寜 id 鍗囧簭锛夛紝骞堕噸缃� istax
+     * 5. 棰勬煡璇㈡湰鏈堟墍鏈夎韩浠借瘉鍙风殑绱閲戦锛岀紦瀛樺埌 Map
+     * 6. 鏍¢獙褰撴湀鏄惁瀛樺湪鍘嗗彶鍙e緞锛坴1锛夌畻绋庤褰曪紝闃叉鏂版棫鍙e緞娣风畻
+     * 7. 閬嶅巻姣忎釜 ServiceFund 閫愬崟绠楃◣锛屾眹鎬诲悗鍥炲啓 service_fundtax
+     * <p>
+     * 鏁存壒鍦ㄤ竴涓簨鍔″唴瀹屾垚锛氫换涓�鏉″け璐ュ垯鏁存壒鍥炴粴锛屼笉浼氬嚭鐜板崐鎵规暟鎹��
      *
      * @param fundTaxVO 鎵规绠楃◣鍙傛暟
      * @return 鏄惁绠楃◣鎴愬姛
      */
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public Boolean batchFundTax(FundTaxVO fundTaxVO) {
         log.info("鎵归噺绠楃◣鐨刦undTaxVO鍏ュ弬涓猴細{}", fundTaxVO);
         // 1. 鏍¢獙鍙傛暟
         if (fundTaxVO.getFundTaxId() == null) {
             throw new BaseException("鍒嗘壒绠楃◣鍑洪棶棰樹簡,璇锋鏌ュ悗鍐嶈繘琛岃绠�");
         }
-        // 2. 鏍¢獙鎵规鍚堟硶鎬э紙浠呴檺淇敼鎿嶄綔锛�
+        // 2. 鍙厑璁告渶鏂版壒娆$畻绋�
         if (fundTaxVO.getAddOrupdate() == 1) {
             Integer maxFundTaxId = serviceFundtaxMapper.getMaxFundTaxId();
             log.info("鎵归噺绠楃◣鐨刴axFundTaxId涓猴細{}", maxFundTaxId);
-            if (!fundTaxVO.getFundTaxId().equals(Long.valueOf(maxFundTaxId))) {
+            if (maxFundTaxId == null || !fundTaxVO.getFundTaxId().equals(Long.valueOf(maxFundTaxId))) {
                 throw new BaseException("璇ユ壒鏁版嵁涓嶈兘绠楃◣");
             }
         }
 
-        // 3. 鏌ヨ鏈壒娆℃墍鏈塖erviceFund锛堟寜id鍗囧簭锛�
+        // 3. 瀵瑰綋鍓嶆壒娆℃眹鎬诲崟鍔犺閿侊紙浜嬪姟鍐呮湁鏁堬級锛岄槻姝㈠苟鍙戦噸澶嶇畻绋�
+        ServiceFundtax fundtax = serviceFundtaxMapper.selectByIdForUpdate(fundTaxVO.getFundTaxId());
+        if (fundtax == null) {
+            throw new BaseException("鏈壘鍒扮畻绋庢眹鎬诲崟锛孖D=" + fundTaxVO.getFundTaxId());
+        }
+
+        // 4. 鏌ヨ鏈壒娆℃墍鏈� ServiceFund锛堟寜 id 鍗囧簭锛�
         ServiceFund serviceFund = new ServiceFund();
         serviceFund.setFundTaxId(fundTaxVO.getFundTaxId());
         serviceFund.setDel_flag(0);
         List<ServiceFund> serviceFunds = serviceFundService.selectServiceFundList(serviceFund);
-        for (ServiceFund serviceFund1 : serviceFunds) {
-            serviceFundMapper.updateFundIsTexById(serviceFund1.getId(), 0L);
-        }
-
-        // 鎸塱d鍗囧簭鎺掑簭锛屼繚璇佸鐞嗛『搴忎竴鑷�
-        serviceFunds.sort(Comparator.comparing(ServiceFund::getId));
         if (CollectionUtils.isEmpty(serviceFunds)) {
             log.warn("鏈煡璇㈠埌鐩稿叧ServiceFund锛宖undTaxId={}", fundTaxVO.getFundTaxId());
             return false;
         }
+        // 閲嶇疆鏈壒 istax 涓庣畻绋庢椂闂达紝浣挎湰鏈堢疮璁℃煡璇笉浼氶噸澶嶈鍏ユ湰鎵�
+        for (ServiceFund serviceFund1 : serviceFunds) {
+            serviceFundMapper.updateFundIsTexById(serviceFund1.getId(), 0L);
+        }
+        // 鎸� id 鍗囧簭鎺掑簭锛屼繚璇佸鐞嗛『搴忎竴鑷�
+        serviceFunds.sort(Comparator.comparing(ServiceFund::getId));
 
-        // 4. 棰勬煡璇㈡湰鏈堟墍鏈夎韩浠借瘉鍙风殑绱閲戦锛岀紦瀛樺埌Map锛屾彁鍗囧悗缁畻绋庢晥鐜�
-        TaxMoneyByItemEO taxMoneyVO = new TaxMoneyByItemEO();
+        // 5. 棰勬煡璇㈡湰鏈堟墍鏈夎韩浠借瘉鍙风殑绱閲戦锛岀紦瀛樺埌 Map锛屾彁鍗囧悗缁畻绋庢晥鐜�
+        Date taxTime = new Date();
         Date firstDay = Date.from(LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay(ZoneId.systemDefault()).toInstant());
+        TaxMoneyByItemEO taxMoneyVO = new TaxMoneyByItemEO();
         taxMoneyVO.setFirstDay(firstDay);
-        taxMoneyVO.setTaxTime(new Date());
+        taxMoneyVO.setTaxTime(taxTime);
         Map<String, TaxMoneySumEO> tempTaxSumMap = new HashMap<>();
         List<TaxMoneySumEO> taxSum = serviceFunddetailMapper.getTaxSum(taxMoneyVO);
-        for (TaxMoneySumEO taxMoneySumEO : taxSum) {
-            tempTaxSumMap.put(taxMoneySumEO.getIDCardNo(), taxMoneySumEO);
+        if (CollectionUtils.isNotEmpty(taxSum)) {
+            for (TaxMoneySumEO taxMoneySumEO : taxSum) {
+                tempTaxSumMap.put(taxMoneySumEO.getIDCardNo(), taxMoneySumEO);
+                // 6. 褰撴湀宸插瓨鍦ㄧ殑鍘嗗彶鍙e緞锛坴1锛夎褰曚細璁╃疮璁″熀鏁版柊鏃ф贩绠楋紝鐩存帴闃绘
+                if (taxMoneySumEO.getV1Count() != null && taxMoneySumEO.getV1Count() > 0) {
+                    throw new BaseException("褰撴湀宸插瓨鍦ㄦ棫鍙e緞锛坴1锛夌畻绋庤褰曪紝涓洪伩鍏嶆柊鏃у彛寰勬贩绠楋紝"
+                            + "鏈湀璇风户缁娇鐢ㄦ棫鍙e緞鎴栦粠涓嬩釜鏈堣捣鍐嶆寜鏂板彛寰勭畻绋庛�備汉鍛樿韩浠借瘉鍙凤細"
+                            + taxMoneySumEO.getIDCardNo());
+                }
+            }
         }
 
-        // 5. 閬嶅巻姣忎釜ServiceFund锛屾壒閲忕畻绋�
+        // 7. 閬嶅巻姣忎釜 ServiceFund锛岄�愬崟绠楃◣骞舵眹鎬�
+        BigDecimal pretaxTotal = BigDecimal.ZERO;
+        BigDecimal vatTotal = BigDecimal.ZERO;
+        BigDecimal cityTaxTotal = BigDecimal.ZERO;
+        BigDecimal laborPretaxTotal = BigDecimal.ZERO;
+        BigDecimal taxTotal = BigDecimal.ZERO;
+        BigDecimal taxedTotal = BigDecimal.ZERO;
         for (ServiceFund serviceFund1 : serviceFunds) {
             ServiceFunddetail serviceFunddetail = new ServiceFunddetail();
             serviceFunddetail.setFundid(serviceFund1.getId());
             List<ServiceFunddetail> serviceFunddetails = serviceFunddetailMapper.selectServiceFunddetailList(serviceFunddetail);
-            // 浼犲叆绱閲戦缂撳瓨锛屾彁鍗囩畻绋庢晥鐜�
-            serviceFunddetailService.calculateTax(serviceFunddetails, tempTaxSumMap);
+            if (CollectionUtils.isEmpty(serviceFunddetails)) {
+                throw new BaseException("鍗曟嵁娌℃湁鍙畻绋庣殑鏄庣粏锛屽崟鎹甀D=" + serviceFund1.getId()
+                        + "锛屾崘鐚渚�=" + serviceFund1.getDonorname());
+            }
+            // 浼犲叆绱閲戦缂撳瓨涓庣粺涓�绠楃◣鏃堕棿
+            serviceFunddetailService.calculateTax(serviceFunddetails, tempTaxSumMap, taxTime);
+            for (ServiceFunddetail detail : serviceFunddetails) {
+                pretaxTotal = pretaxTotal.add(toMoney(detail.getAmount()));
+                vatTotal = vatTotal.add(toMoney(detail.getVatAmount()));
+                cityTaxTotal = cityTaxTotal.add(toMoney(detail.getCityTaxAmount()));
+                laborPretaxTotal = laborPretaxTotal.add(toMoney(detail.getLaborPretaxAmount()));
+                taxTotal = taxTotal.add(toMoney(detail.getTaxamount()));
+                taxedTotal = taxedTotal.add(toMoney(detail.getTaxedamount()));
+            }
         }
+
+        // 8. 鍥炲啓姹囨�诲崟 service_fundtax锛�6 涓噾棰� + 绠楃◣鐘舵�� + 鐗堟湰锛�
+        ServiceFundtax updateFundtax = new ServiceFundtax();
+        updateFundtax.setId(fundTaxVO.getFundTaxId());
+        updateFundtax.setPretaxamount(VatTaxUtils.roundMoney(pretaxTotal));
+        updateFundtax.setVatAmount(VatTaxUtils.roundMoney(vatTotal));
+        updateFundtax.setCityTaxAmount(VatTaxUtils.roundMoney(cityTaxTotal));
+        updateFundtax.setLaborPretaxAmount(VatTaxUtils.roundMoney(laborPretaxTotal));
+        updateFundtax.setTaxamount(VatTaxUtils.roundMoney(taxTotal));
+        updateFundtax.setTaxMoney(VatTaxUtils.roundMoney(taxTotal));
+        updateFundtax.setTaxedamount(VatTaxUtils.roundMoney(taxedTotal));
+        updateFundtax.setTaxVersion(VatTaxUtils.TAX_VERSION_V2);
+        updateFundtax.setIstax(1);
+        updateFundtax.setTaxedtime(taxTime);
+        serviceFundtaxMapper.updateById(updateFundtax);
+        log.info("鎵归噺绠楃◣瀹屾垚锛宖undTaxId={}锛岀◣鍓�={}锛屽鍊肩◣={}锛屽煄寤虹◣={}锛屽姵鍔$◣鍓�={}锛屽姵鍔′釜绋�={}锛屽姵鍔$◣鍚�={}",
+                fundTaxVO.getFundTaxId(), pretaxTotal, vatTotal, cityTaxTotal, laborPretaxTotal, taxTotal, taxedTotal);
         return true;
     }
 
+    /**
+     * null 瀹夊叏鐨勯噾棰濊浆鎹�
+     */
+    private static BigDecimal toMoney(Double value) {
+        return value == null ? BigDecimal.ZERO : BigDecimal.valueOf(value);
+    }
+
 }
diff --git a/ruoyi-project/src/main/resources/mapper/project/CasePanoramaMapper.xml b/ruoyi-project/src/main/resources/mapper/project/CasePanoramaMapper.xml
new file mode 100644
index 0000000..f1ce44a
--- /dev/null
+++ b/ruoyi-project/src/main/resources/mapper/project/CasePanoramaMapper.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.project.mapper.CasePanoramaMapper">
+
+    <sql id="casePanoramaColumns">
+        id,
+        DonorName AS donorName,
+        ReportTime AS reportTime,
+        deptname AS deptName,
+        ReporterName AS reporterName,
+        Dontiontermination AS terminationFlag,
+        workflow AS workflow,
+        COALESCE(dd.dict_label, CAST(workflow AS CHAR)) AS workflowName,
+        DonateTime AS donateTime,
+        DonationHospital AS donationHospital,
+        OrganName AS organName,
+        OrganProcurement AS organProcurement,
+        OrganTransplantation AS organTransplantation,
+        COALESCE(DonorFamilysCost, 0) + COALESCE(medCost, 0) + COALESCE(ExpertCost, 0) + COALESCE(ItemCode3_4, 0) AS totalCost,
+        DonorFamilysCost AS donorFamilyCost,
+        medCost AS medCost,
+        ExpertCost AS expertCost,
+        ItemCode3_4 AS itemCode34,
+        ItemCode42 AS itemCode42,
+        ItemCode46 AS itemCode46,
+        ItemCode50 AS itemCode50,
+        ItemCode44 AS itemCode44,
+        ItemCode47 AS itemCode47,
+        ItemCode48 AS itemCode48,
+        ItemCode21 AS itemCode21,
+        ItemCode12 AS itemCode12,
+        ItemCode17 AS itemCode17,
+        ItemCode23 AS itemCode23,
+        ItemCode25 AS itemCode25
+    </sql>
+
+    <select id="selectCasePanoramaList" resultType="com.ruoyi.project.domain.CasePanorama">
+        SELECT
+        <include refid="casePanoramaColumns"/>
+        FROM v_donationfeestat v
+        LEFT JOIN (
+            SELECT dict_value, MAX(dict_label) AS dict_label
+            FROM sys_dict_data
+            WHERE dict_type = 'sys_donornode'
+            GROUP BY dict_value
+        ) dd ON dd.dict_value COLLATE utf8mb4_general_ci = CAST(v.workflow AS CHAR) COLLATE utf8mb4_general_ci
+        <where>
+            <if test="req.donorName != null and req.donorName != ''">
+                AND DonorName LIKE CONCAT('%', #{req.donorName}, '%')
+            </if>
+            <if test="req.donateTimeBegin != null and req.donateTimeBegin != ''">
+                AND DonateTime &gt;= #{req.donateTimeBegin}
+            </if>
+            <if test="req.donateTimeEnd != null and req.donateTimeEnd != ''">
+                AND DonateTime &lt;= #{req.donateTimeEnd}
+            </if>
+            <if test="req.deptName != null and req.deptName != ''">
+                AND deptname = #{req.deptName}
+            </if>
+            <if test="req.reporterName != null and req.reporterName != ''">
+                AND ReporterName LIKE CONCAT('%', #{req.reporterName}, '%')
+            </if>
+        </where>
+        ORDER BY ReportTime DESC, id DESC
+    </select>
+
+    <select id="selectDeptNames" resultType="java.lang.String">
+        SELECT DISTINCT deptname
+        FROM v_donationfeestat
+        WHERE deptname IS NOT NULL AND deptname != ''
+        ORDER BY deptname
+    </select>
+
+</mapper>
diff --git a/ruoyi-project/src/main/resources/mapper/project/ServiceFundMapper.xml b/ruoyi-project/src/main/resources/mapper/project/ServiceFundMapper.xml
index 14ab295..c5115cc 100644
--- a/ruoyi-project/src/main/resources/mapper/project/ServiceFundMapper.xml
+++ b/ruoyi-project/src/main/resources/mapper/project/ServiceFundMapper.xml
@@ -51,6 +51,10 @@
         <result property="uploadtime" column="uploadtime"/>
         <result property="flowlevel" column="FlowLevel"/>
         <result property="pretaxcost" column="PretaxCost"/>
+        <result property="vatCost" column="vat_cost"/>
+        <result property="cityTaxCost" column="city_tax_cost"/>
+        <result property="laborPretaxCost" column="labor_pretax_cost"/>
+        <result property="taxVersion" column="tax_version"/>
         <result property="taxedcost" column="TaxedCost"/>
         <result property="backflowlevel" column="backFlowLevel"/>
         <result property="zffs" column="zffs"/>
@@ -87,6 +91,10 @@
                UnitNo,
                UnitUserNo,
                PretaxCost,
+               vat_cost,
+               city_tax_cost,
+               labor_pretax_cost,
+               tax_version,
                TaxedCost,
                Phone,
                AnnexBankCard,
diff --git a/ruoyi-project/src/main/resources/mapper/project/ServiceFunddetailMapper.xml b/ruoyi-project/src/main/resources/mapper/project/ServiceFunddetailMapper.xml
index cb99db2..8070f25 100644
--- a/ruoyi-project/src/main/resources/mapper/project/ServiceFunddetailMapper.xml
+++ b/ruoyi-project/src/main/resources/mapper/project/ServiceFunddetailMapper.xml
@@ -37,6 +37,10 @@
         <result property="amount" column="Amount"/>
         <result property="taxamount" column="TaxAmount"/>
         <result property="taxedamount" column="TaxedAmount"/>
+        <result property="vatAmount" column="vat_amount"/>
+        <result property="cityTaxAmount" column="city_tax_amount"/>
+        <result property="laborPretaxAmount" column="labor_pretax_amount"/>
+        <result property="taxVersion" column="tax_version"/>
         <result property="prepaidamount" column="PrepaidAmount"/>
         <result property="invoicecount" column="InvoiceCount"/>
         <result property="attachcount" column="AttachCount"/>
@@ -108,6 +112,10 @@
                TaxAmount,
                InvoiceCount,
                TaxedAmount,
+               vat_amount,
+               city_tax_amount,
+               labor_pretax_amount,
+               tax_version,
                AttachCount,
                Quantity,
                Price,
@@ -232,6 +240,10 @@
         a.TaxAmount,
         a.InvoiceCount,
         a.TaxedAmount,
+        a.vat_amount,
+        a.city_tax_amount,
+        a.labor_pretax_amount,
+        a.tax_version,
         a.AttachCount,
         a.Quantity,
         a.Price,
@@ -281,7 +293,15 @@
 
     <select id="getTaxSum" parameterType="com.ruoyi.project.domain.vo.TaxMoneyByItemEO"
             resultType="com.ruoyi.project.domain.vo.TaxMoneySumEO">
-        SELECT sum(a.Amount) amounts, sum(a.TaxAmount) taxAmounts, sum(a.TaxedAmount) taxedAmounts, max(a.xh) as xh,a.IDCardNo
+        SELECT sum(a.Amount)                                                     amounts,
+               sum(COALESCE(a.labor_pretax_amount, a.Amount))                     laborPretaxAmounts,
+               sum(COALESCE(a.TaxAmount, 0))                                      taxAmounts,
+               sum(COALESCE(a.TaxedAmount, 0))                                    taxedAmounts,
+               sum(COALESCE(a.vat_amount, 0))                                     vatAmounts,
+               sum(COALESCE(a.city_tax_amount, 0))                                cityTaxAmounts,
+               sum(CASE WHEN a.tax_version = 'v1' THEN 1 ELSE 0 END)              v1Count,
+               max(a.xh)                                                          xh,
+               a.IDCardNo
         FROM service_funddetail a,
              service_fund b
         where a.FundID = b.id
diff --git a/ruoyi-project/src/main/resources/mapper/project/ServiceFunddetailSharedMapper.xml b/ruoyi-project/src/main/resources/mapper/project/ServiceFunddetailSharedMapper.xml
index 390da09..2d5d1bd 100644
--- a/ruoyi-project/src/main/resources/mapper/project/ServiceFunddetailSharedMapper.xml
+++ b/ruoyi-project/src/main/resources/mapper/project/ServiceFunddetailSharedMapper.xml
@@ -37,6 +37,9 @@
         <result property="amount" column="Amount"/>
         <result property="taxamount" column="TaxAmount"/>
         <result property="taxedamount" column="TaxedAmount"/>
+        <result property="vatAmount" column="vat_amount"/>
+        <result property="cityTaxAmount" column="city_tax_amount"/>
+        <result property="laborPretaxAmount" column="labor_pretax_amount"/>
         <result property="prepaidamount" column="PrepaidAmount"/>
         <result property="paidamount" column="paidAmount"/>
         <result property="paidtime" column="paidTime"/>
@@ -96,6 +99,9 @@
                Amount,
                TaxAmount,
                TaxedAmount,
+               vat_amount,
+               city_tax_amount,
+               labor_pretax_amount,
                PrepaidAmount,
                paidAmount,
                paidTime,
diff --git a/ruoyi-project/src/main/resources/mapper/project/ServiceFundtaxMapper.xml b/ruoyi-project/src/main/resources/mapper/project/ServiceFundtaxMapper.xml
index 472b313..2b057b0 100644
--- a/ruoyi-project/src/main/resources/mapper/project/ServiceFundtaxMapper.xml
+++ b/ruoyi-project/src/main/resources/mapper/project/ServiceFundtaxMapper.xml
@@ -15,6 +15,10 @@
         <result property="managerno" column="ManagerNo"/>
         <result property="managername" column="ManagerName"/>
         <result property="pretaxamount" column="Pretaxamount"/>
+        <result property="vatAmount" column="vat_amount"/>
+        <result property="cityTaxAmount" column="city_tax_amount"/>
+        <result property="laborPretaxAmount" column="labor_pretax_amount"/>
+        <result property="taxVersion" column="tax_version"/>
         <result property="taxedamount" column="TaxedAmount"/>
         <result property="taxamount" column="TaxAmount"/>
         <result property="medicalcost" column="MedicalCost"/>
@@ -60,6 +64,10 @@
                Pretaxamount,
                TaxedAmount,
                TaxAmount,
+               vat_amount,
+               city_tax_amount,
+               labor_pretax_amount,
+               tax_version,
                MedicalCost,
                BodyMaintainCost,
                OrganGainCost,
@@ -143,4 +151,10 @@
         where del_flag = 0;
     </select>
 
+    <select id="selectByIdForUpdate" resultMap="ServiceFundtaxResult">
+        <include refid="selectServiceFundtaxVo"/>
+        where ID = #{id}
+        for update
+    </select>
+
 </mapper>
\ No newline at end of file

--
Gitblit v1.9.3