浏览代码

Merge branch 'master' of huangrui/CostAccount into dev

huangrui 4 年之前
父节点
当前提交
be28693e6d

+ 1 - 1
pom.xml

@@ -103,7 +103,7 @@
             <groupId>mysql</groupId>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
             <artifactId>mysql-connector-java</artifactId>
             <!--最好指定版本,不同环境版本可能不同-->
             <!--最好指定版本,不同环境版本可能不同-->
-            <version>8.0.25</version>
+            <version>8.0.16</version>
         </dependency>
         </dependency>
 
 
         <dependency>
         <dependency>

+ 2 - 0
src/main/java/com/imed/costaccount/common/token/RedisUtil.java

@@ -267,4 +267,6 @@ public class RedisUtil {
         return hashOperations.get(key, hKey);
         return hashOperations.get(key, hKey);
     }
     }
 
 
+
+
 }
 }

+ 62 - 0
src/main/java/com/imed/costaccount/common/util/RedisLock.java

@@ -0,0 +1,62 @@
+package com.imed.costaccount.common.util;
+
+import cn.hutool.core.util.StrUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RedisLock {
+    @Autowired
+    private StringRedisTemplate stringRedisTemplate;
+
+    /**
+     * 加锁
+     * @param lockKey 加锁的Key
+     * @param timeStamp 时间戳:当前时间+超时时间
+     * @return
+     */
+    public boolean lock(String lockKey,String timeStamp){
+        if(stringRedisTemplate.opsForValue().setIfAbsent(lockKey, timeStamp)){
+            // 对应setnx命令,可以成功设置,也就是key不存在,获得锁成功
+            return true;
+        }
+
+        //设置失败,获得锁失败
+        // 判断锁超时 - 防止原来的操作异常,没有运行解锁操作 ,防止死锁
+        String currentLock = stringRedisTemplate.opsForValue().get(lockKey);
+        // 如果锁过期 currentLock不为空且小于当前时间
+        if(StrUtil.isNotEmpty(currentLock) && Long.parseLong(currentLock) < System.currentTimeMillis()){
+            //如果lockKey对应的锁已经存在,获取上一次设置的时间戳之后并重置lockKey对应的锁的时间戳
+            String preLock = stringRedisTemplate.opsForValue().getAndSet(lockKey, timeStamp);
+
+            //假设两个线程同时进来这里,因为key被占用了,而且锁过期了。
+            //获取的值currentLock=A(get取的旧的值肯定是一样的),两个线程的timeStamp都是B,key都是K.锁时间已经过期了。
+            //而这里面的getAndSet一次只会一个执行,也就是一个执行之后,上一个的timeStamp已经变成了B。
+            //只有一个线程获取的上一个值会是A,另一个线程拿到的值是B。
+            if(StrUtil.isNotEmpty(preLock) && preLock.equals(currentLock)){
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * 释放锁
+     * @param lockKey
+     * @param timeStamp
+     */
+    public void release(String lockKey,String timeStamp){
+        try {
+            String currentValue = stringRedisTemplate.opsForValue().get(lockKey);
+            if(!StrUtil.isEmpty(currentValue) && currentValue.equals(timeStamp) ){
+                // 删除锁状态
+                stringRedisTemplate.opsForValue().getOperations().delete(lockKey);
+            }
+        } catch (Exception e) {
+            System.out.println("警报!警报!警报!解锁异常");
+        }
+    }
+}

+ 20 - 0
src/main/java/com/imed/costaccount/mapper/IncomeCollectionMapper.java

@@ -3,6 +3,7 @@ package com.imed.costaccount.mapper;
 import com.imed.costaccount.model.IncomeCollection;
 import com.imed.costaccount.model.IncomeCollection;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.imed.costaccount.model.dto.CollectDTO;
 import com.imed.costaccount.model.dto.CollectDTO;
+import com.imed.costaccount.model.vo.CodeAndNameVO;
 import com.imed.costaccount.model.vo.CollectedVO;
 import com.imed.costaccount.model.vo.CollectedVO;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Param;
@@ -41,4 +42,23 @@ public interface IncomeCollectionMapper extends BaseMapper<IncomeCollection> {
      */
      */
     BigDecimal getTotalAmount(@Param("collectDTO") CollectDTO collectDTO);
     BigDecimal getTotalAmount(@Param("collectDTO") CollectDTO collectDTO);
 
 
+    /**
+     * 纵向计算所有的amount
+     * @param responsibilityCode
+     * @param accountingCodes
+     * @param hospId
+     * @param date
+     * @return
+     */
+    BigDecimal getCountByResponseAndAccounts(@Param("responsibilityCode") String responsibilityCode, @Param("accountingCodes") List<String> accountingCodes, @Param("hospId") Long hospId, @Param("date") String date);
+
+
+    List<CodeAndNameVO> getResponsibility(@Param("hospId") Long hospId, @Param("responsibilityCode") String responsibilityCode, @Param("date") String date);
+
+    List<CodeAndNameVO> getAccount(@Param("hospId") Long hospId, @Param("accountingCode") String accountingCode, @Param("date") String date);
+
+    BigDecimal getCountAccountAndResponsibilities(@Param("hospId") Long hospId, @Param("date") String date, @Param("code") String code, @Param("responsibilityCodes") List<String> responsibilityCodes);
+
+    BigDecimal getCountByResponsibilitiesAndAccounts(@Param("responsibilityCodes") List<String> responsibilityCodes, @Param("accountingCodes") List<String> accountingCodes, @Param("hospId") Long hospId, @Param("date") String date);
+
 }
 }

+ 15 - 0
src/main/java/com/imed/costaccount/model/vo/CodeAndNameVO.java

@@ -0,0 +1,15 @@
+package com.imed.costaccount.model.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CodeAndNameVO {
+
+    private String code;
+
+    private String name;
+}

+ 24 - 0
src/main/java/com/imed/costaccount/model/vo/CollectDataFormVO.java

@@ -0,0 +1,24 @@
+package com.imed.costaccount.model.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CollectDataFormVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    private Map<Integer, String> titleMap;
+
+    private List<Map<Integer, Object>> realData;
+
+    private Map<Integer, Object> totalMap ;
+
+}

+ 10 - 0
src/main/java/com/imed/costaccount/service/IncomeCollectionService.java

@@ -4,6 +4,9 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.imed.costaccount.common.util.PageUtils;
 import com.imed.costaccount.common.util.PageUtils;
 import com.imed.costaccount.model.IncomeCollection;
 import com.imed.costaccount.model.IncomeCollection;
 import com.imed.costaccount.model.dto.CollectDTO;
 import com.imed.costaccount.model.dto.CollectDTO;
+import com.imed.costaccount.model.vo.CollectDataFormVO;
+
+import java.util.List;
 
 
 /**
 /**
  * 归集后列表
  * 归集后列表
@@ -51,5 +54,12 @@ public interface IncomeCollectionService extends IService<IncomeCollection> {
      */
      */
     PageUtils collectList(CollectDTO collectDTO);
     PageUtils collectList(CollectDTO collectDTO);
 
 
+    /**
+     *
+     * @param collectDTO
+     * @return
+     */
+    CollectDataFormVO collectDataForm(CollectDTO collectDTO);
+
 }
 }
 
 

+ 75 - 34
src/main/java/com/imed/costaccount/service/impl/CostCostingGroupServiceImpl.java

@@ -55,7 +55,7 @@ public class CostCostingGroupServiceImpl extends ServiceImpl<CostCostingGroupMap
      * @return
      * @return
      */
      */
     @Override
     @Override
-    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
+    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
     public Result importCostingGroup(List<List<Object>> list, User user, MultipartFile file, String dateTime, Integer fileType) {
     public Result importCostingGroup(List<List<Object>> list, User user, MultipartFile file, String dateTime, Integer fileType) {
         // 先检验当前年月是否存在数据
         // 先检验当前年月是否存在数据
         int year = 0;
         int year = 0;
@@ -114,7 +114,7 @@ public class CostCostingGroupServiceImpl extends ServiceImpl<CostCostingGroupMap
             return Result.build(500, "数据未成功导入", null);
             return Result.build(500, "数据未成功导入", null);
         }
         }
         // 检验收入数据
         // 检验收入数据
-        checkCostData(list, incomeErrorMessageList, departmentMap, productMap, responsibilityMap, accountingMap, responsibilityDepMap, accountProMap, costCostingGroupArrayList,year,month);
+        checkCostData(list, incomeErrorMessageList, departmentMap, productMap, responsibilityMap, accountingMap, responsibilityDepMap, accountProMap, costCostingGroupArrayList, year, month);
         // 文件上传
         // 文件上传
         String uploadFile = costIncomeGroupService.uploadFile(file, UserContext.getCurrentUser());
         String uploadFile = costIncomeGroupService.uploadFile(file, UserContext.getCurrentUser());
         // 上传记录保存
         // 上传记录保存
@@ -130,14 +130,15 @@ public class CostCostingGroupServiceImpl extends ServiceImpl<CostCostingGroupMap
         });
         });
         if (CollectionUtils.isEmpty(incomeErrorMessageList)) {
         if (CollectionUtils.isEmpty(incomeErrorMessageList)) {
             this.saveBatch(costCostingGroupArrayList);
             this.saveBatch(costCostingGroupArrayList);
-            return Result.build(200,"数据导入成功",null);
-        }else {
+            return Result.build(200, "数据导入成功", null);
+        } else {
             return Result.build(500, "数据未成功导入", null);
             return Result.build(500, "数据未成功导入", null);
         }
         }
     }
     }
 
 
     /**
     /**
      * 检验成本数据
      * 检验成本数据
+     *
      * @param list
      * @param list
      * @param incomeErrorMessageList
      * @param incomeErrorMessageList
      * @param departmentMap
      * @param departmentMap
@@ -148,12 +149,24 @@ public class CostCostingGroupServiceImpl extends ServiceImpl<CostCostingGroupMap
      * @param accountProMap
      * @param accountProMap
      * @param costCostingGroupArrayList
      * @param costCostingGroupArrayList
      */
      */
-    private void checkCostData(List<List<Object>> list, List<IncomeErrorMessage> incomeErrorMessageList, Map<String, Department> departmentMap, Map<String, Product> productMap, Map<Long, Responsibility> responsibilityMap, Map<Long, Accounting> accountingMap, Map<Long, Long> responsibilityDepMap, Map<Long, Long> accountProMap, List<CostCostingGroup> costCostingGroupArrayList,Integer year,Integer month) {
+    private void checkCostData(List<List<Object>> list, List<IncomeErrorMessage> incomeErrorMessageList, Map<String, Department> departmentMap, Map<String, Product> productMap, Map<Long, Responsibility> responsibilityMap, Map<Long, Accounting> accountingMap, Map<Long, Long> responsibilityDepMap, Map<Long, Long> accountProMap, List<CostCostingGroup> costCostingGroupArrayList, Integer year, Integer month) {
         List<Object> departmentCodes = list.get(0);
         List<Object> departmentCodes = list.get(0);
         List<Object> departmentNames = list.get(1);
         List<Object> departmentNames = list.get(1);
         //检验数据是否准确
         //检验数据是否准确
         for (int i = 2; i < list.size(); i++) {
         for (int i = 2; i < list.size(); i++) {
             List<Object> data = list.get(i);
             List<Object> data = list.get(i);
+            for (int j = 2; j < departmentCodes.size(); j++) {
+                if (data.size() > j ) {
+                    if (Objects.isNull(data.get(j))){
+                        data.set(j, NumberConstant.ZERO);
+                    }else {
+                        data.set(j, Integer.parseInt(data.get(j).toString()));
+                    }
+                }else if (data.size()<=departmentCodes.size()){
+                    data.add(NumberConstant.ZERO);
+                }
+            }
+
             // 检验成本项目是否正确
             // 检验成本项目是否正确
             CostCostingGroup costCostingGroupRequest = new CostCostingGroup();
             CostCostingGroup costCostingGroupRequest = new CostCostingGroup();
             String productCode = data.get(0).toString();
             String productCode = data.get(0).toString();
@@ -187,49 +200,77 @@ public class CostCostingGroupServiceImpl extends ServiceImpl<CostCostingGroupMap
                 incomeErrorMessage.setErrMessage("成本代码" + productCode + " 成本名称" + productName + "不存在");
                 incomeErrorMessage.setErrMessage("成本代码" + productCode + " 成本名称" + productName + "不存在");
                 incomeErrorMessageList.add(incomeErrorMessage);
                 incomeErrorMessageList.add(incomeErrorMessage);
             }
             }
+            // 0表示全为0 1表示不全为0
+            Integer emptyStatus = 0;
             for (int j = 2; j < data.size()-1 ; j++) {
             for (int j = 2; j < data.size()-1 ; j++) {
-                CostCostingGroup costCostingGroup=costCostingGroupRequest;
-                // 检验科室信息是否准确
-                String departmentCode = departmentCodes.get(j).toString();
-                String departmentName = departmentNames.get(j).toString();
-                Department department = departmentMap.get(departmentCode + departmentName);
-                if (Objects.nonNull(department)) {
-                    // 检测责任中心是否存在
-                    Long id = department.getId();
-                    Long responsibilityId = responsibilityDepMap.get(id);
-                    if (Objects.nonNull(responsibilityId)) {
-                        Responsibility responsibility = responsibilityMap.get(responsibilityId);
-                        if (Objects.nonNull(responsibility)) {
-                            costCostingGroup.setDepartmentCode(departmentCode);
-                            costCostingGroup.setDepartmentName(departmentName);
-                            costCostingGroup.setResponsibilityCode(responsibility.getResponsibilityCode());
-                            costCostingGroup.setResponsibilityName(responsibility.getResponsibilityName());
+                int parseInt = Integer.parseInt(data.get(j).toString());
+                if (!NumberConstant.ZERO.equals(parseInt)) {
+                    emptyStatus = 1;
+                    break;
+                }
+            }
+            Integer combined = Integer.parseInt(data.get(data.size() - 1).toString());
+            if (NumberConstant.ZERO.equals(emptyStatus) && NumberConstant.ZERO.equals(combined)) {
+                // 全为0
+                continue;
+            } else if (!NumberConstant.ZERO.equals(combined) && NumberConstant.ZERO.equals(emptyStatus)) {
+                // 这条数据是保存到其他责任中心的
+                CostCostingGroup costCostingGroup = costCostingGroupRequest;
+                // TODO 设置其他责任中心
+                costCostingGroup.setResponsibilityCode("其他责任中心的Code");
+                costCostingGroup.setResponsibilityName("其他责任中心的Name");
+                costCostingGroup.setAmount(BigDecimal.valueOf(Double.parseDouble(combined.toString())));
+                costCostingGroup.setHospId(UserContext.getHospId());
+                costCostingGroup.setCreateTime(System.currentTimeMillis());
+                costCostingGroup.setDateYear(year);
+                costCostingGroup.setDateMonth(month);
+                costCostingGroupArrayList.add(costCostingGroup);
+            } else {
+                for (int j = 2; j < data.size() - 1; j++) {
+                    CostCostingGroup costCostingGroup = costCostingGroupRequest;
+                    // 检验科室信息是否准确
+                    String departmentCode = departmentCodes.get(j).toString();
+                    String departmentName = departmentNames.get(j).toString();
+                    Department department = departmentMap.get(departmentCode + departmentName);
+                    if (Objects.nonNull(department)) {
+                        // 检测责任中心是否存在
+                        Long id = department.getId();
+                        Long responsibilityId = responsibilityDepMap.get(id);
+                        if (Objects.nonNull(responsibilityId)) {
+                            Responsibility responsibility = responsibilityMap.get(responsibilityId);
+                            if (Objects.nonNull(responsibility)) {
+                                costCostingGroup.setDepartmentCode(departmentCode);
+                                costCostingGroup.setDepartmentName(departmentName);
+                                costCostingGroup.setResponsibilityCode(responsibility.getResponsibilityCode());
+                                costCostingGroup.setResponsibilityName(responsibility.getResponsibilityName());
 
 
+                            } else {
+                                IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
+                                incomeErrorMessage.setTotal(j);
+                                incomeErrorMessage.setErrMessage("第" + j + "列科室信息对应的责任中心不存在");
+                                incomeErrorMessageList.add(incomeErrorMessage);
+                            }
                         } else {
                         } else {
                             IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
                             IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
                             incomeErrorMessage.setTotal(j);
                             incomeErrorMessage.setTotal(j);
-                            incomeErrorMessage.setErrMessage("第" + j + "列科室信息对应的责任中心不存在");
+                            incomeErrorMessage.setErrMessage("第" + j + "列科室信息不存在对应的责任中心");
                             incomeErrorMessageList.add(incomeErrorMessage);
                             incomeErrorMessageList.add(incomeErrorMessage);
                         }
                         }
                     } else {
                     } else {
                         IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
                         IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
                         incomeErrorMessage.setTotal(j);
                         incomeErrorMessage.setTotal(j);
-                        incomeErrorMessage.setErrMessage("第" + j + "列科室信息不存在对应的责任中心");
+                        incomeErrorMessage.setErrMessage("第" + j + "列科室信息不存在");
                         incomeErrorMessageList.add(incomeErrorMessage);
                         incomeErrorMessageList.add(incomeErrorMessage);
                     }
                     }
-                } else {
-                    IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
-                    incomeErrorMessage.setTotal(j);
-                    incomeErrorMessage.setErrMessage("第" + j + "列科室信息不存在");
-                    incomeErrorMessageList.add(incomeErrorMessage);
+                    costCostingGroup.setAmount(BigDecimal.valueOf(Double.parseDouble((Objects.isNull(data.get(j)) || "0".equals(data.get(j).toString())) ? "0.00" : data.get(j).toString())));
+                    costCostingGroup.setHospId(UserContext.getHospId());
+                    costCostingGroup.setCreateTime(System.currentTimeMillis());
+                    costCostingGroup.setDateYear(year);
+                    costCostingGroup.setDateMonth(month);
+                    costCostingGroupArrayList.add(costCostingGroup);
                 }
                 }
-                costCostingGroup.setAmount(BigDecimal.valueOf(Double.parseDouble(("0".equals(data.get(j).toString()) || StrUtil.isBlank(data.get(j).toString())) ?"0.00":data.get(j).toString())));
-                costCostingGroup.setHospId(UserContext.getHospId());
-                costCostingGroup.setCreateTime(System.currentTimeMillis());
-                costCostingGroup.setDateYear(year);
-                costCostingGroup.setDateMonth(month);
-                costCostingGroupArrayList.add(costCostingGroup);
             }
             }
+
         }
         }
     }
     }
 }
 }

+ 3 - 0
src/main/java/com/imed/costaccount/service/impl/CostIncomeGroupServiceImpl.java

@@ -329,6 +329,9 @@ public class CostIncomeGroupServiceImpl extends ServiceImpl<CostIncomeGroupMappe
             String openDepartmentCode = data.get(3).toString();
             String openDepartmentCode = data.get(3).toString();
             String startDepartmentName = data.get(4).toString();
             String startDepartmentName = data.get(4).toString();
             String startDepartmentCode = data.get(5).toString();
             String startDepartmentCode = data.get(5).toString();
+            if (StrUtil.isBlank(openDepartmentCode) && StrUtil.isBlank(openDepartmentName) && StrUtil.isBlank(startDepartmentCode) && StrUtil.isBlank(startDepartmentName)){
+                continue;
+            }
             BigDecimal beforeMoney = BigDecimal.valueOf(Double.parseDouble(("0".equals(data.get(15).toString()) || StrUtil.isBlank(data.get(15).toString())) ?"0.00":data.get(15).toString()));
             BigDecimal beforeMoney = BigDecimal.valueOf(Double.parseDouble(("0".equals(data.get(15).toString()) || StrUtil.isBlank(data.get(15).toString())) ?"0.00":data.get(15).toString()));
             boolean checkNull = StrUtil.isBlank(data.get(15).toString());
             boolean checkNull = StrUtil.isBlank(data.get(15).toString());
             boolean checkOne = "0".equals(data.get(15).toString());
             boolean checkOne = "0".equals(data.get(15).toString());

+ 177 - 61
src/main/java/com/imed/costaccount/service/impl/IncomeCollectionServiceImpl.java

@@ -1,20 +1,24 @@
 package com.imed.costaccount.service.impl;
 package com.imed.costaccount.service.impl;
 
 
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.imed.costaccount.common.exception.CostException;
 import com.imed.costaccount.common.exception.CostException;
 import com.imed.costaccount.common.util.PageUtils;
 import com.imed.costaccount.common.util.PageUtils;
+import com.imed.costaccount.common.util.RedisLock;
 import com.imed.costaccount.mapper.CostIncomeGroupMapper;
 import com.imed.costaccount.mapper.CostIncomeGroupMapper;
 import com.imed.costaccount.mapper.IncomeCollectionMapper;
 import com.imed.costaccount.mapper.IncomeCollectionMapper;
-import com.imed.costaccount.model.AfterIncomegroup;
-import com.imed.costaccount.model.CostIncomeGroup;
-import com.imed.costaccount.model.IncomeCollection;
+import com.imed.costaccount.model.*;
 import com.imed.costaccount.model.dto.CollectDTO;
 import com.imed.costaccount.model.dto.CollectDTO;
+import com.imed.costaccount.model.vo.CodeAndNameVO;
+import com.imed.costaccount.model.vo.CollectDataFormVO;
 import com.imed.costaccount.model.vo.CollectedVO;
 import com.imed.costaccount.model.vo.CollectedVO;
 import com.imed.costaccount.model.vo.CollectionVO;
 import com.imed.costaccount.model.vo.CollectionVO;
+import com.imed.costaccount.service.AccountingService;
 import com.imed.costaccount.service.IncomeCollectionService;
 import com.imed.costaccount.service.IncomeCollectionService;
+import com.imed.costaccount.service.ResponsibilityService;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Propagation;
@@ -33,10 +37,19 @@ public class IncomeCollectionServiceImpl
         extends ServiceImpl<IncomeCollectionMapper, IncomeCollection>
         extends ServiceImpl<IncomeCollectionMapper, IncomeCollection>
         implements IncomeCollectionService {
         implements IncomeCollectionService {
 
 
+    private final RedisLock redisLock;
+
     private final CostIncomeGroupMapper incomeGroupMapper;
     private final CostIncomeGroupMapper incomeGroupMapper;
 
 
-    public IncomeCollectionServiceImpl(CostIncomeGroupMapper incomeGroupMapper) {
+    private final ResponsibilityService responsibilityService;
+
+    private final AccountingService accountingService;
+
+    public IncomeCollectionServiceImpl(RedisLock redisLock, CostIncomeGroupMapper incomeGroupMapper, ResponsibilityService responsibilityService, AccountingService accountingService) {
+        this.redisLock = redisLock;
         this.incomeGroupMapper = incomeGroupMapper;
         this.incomeGroupMapper = incomeGroupMapper;
+        this.responsibilityService = responsibilityService;
+        this.accountingService = accountingService;
     }
     }
 
 
     /**
     /**
@@ -83,65 +96,84 @@ public class IncomeCollectionServiceImpl
     @Override
     @Override
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
     public void collect(Integer year, Integer month, Long hospId) {
     public void collect(Integer year, Integer month, Long hospId) {
-        //  可能几十万次数据 需要分段异步多线程处理,分布式锁处理,
-        List<CostIncomeGroup> costIncomeGroups = incomeGroupMapper.selectList(
-                new LambdaQueryWrapper<CostIncomeGroup>()
-                        .eq(CostIncomeGroup::getDateYear, year)
-                        .eq(CostIncomeGroup::getDateMonth, month)
-                        .eq(CostIncomeGroup::getHospId, hospId)
-        );
-        if (costIncomeGroups.isEmpty()) {
-            String format = StrUtil.format("{}年{}月数据不存在,请先导入数据", year, month);
-            throw new CostException(format);
-        }
-        // 根据会计科目和成本项目归纳所有数据
-        Map<String, List<CostIncomeGroup>> collectMap = costIncomeGroups.stream()
-                .collect(Collectors.groupingBy(i -> i.getAccountCode() + "cost" + i.getProductCode()));
-
-        // 遍历map 组装成List保存
-        List<IncomeCollection> list = new LinkedList<>();
-        Set<Map.Entry<String, List<CostIncomeGroup>>> entries = collectMap.entrySet();
-        entries.stream().map(Map.Entry::getValue).flatMap(Collection::stream).forEach(costIncomeGroup -> {
-            IncomeCollection incomeCollection = new IncomeCollection();
-            incomeCollection.setYear(year);
-            incomeCollection.setMonth(month);
-            incomeCollection.setAccountingCode(costIncomeGroup.getAccountCode());
-            incomeCollection.setAccountingName(costIncomeGroup.getAccountName());
-            incomeCollection.setProductName(costIncomeGroup.getProductName());
-            incomeCollection.setProductCode(costIncomeGroup.getProductCode());
-            incomeCollection.setAmount(costIncomeGroup.getAmount());
-            incomeCollection.setHospId(hospId);
-            // todo 来源id暂时不确定
-            incomeCollection.setFileId(costIncomeGroup.getFileId());
-            incomeCollection.setCreateTime(System.currentTimeMillis());
-            String afterIncomeGroupStr = costIncomeGroup.getAfterIncomeGroup();
-            AfterIncomegroup afterIncomegroup = JSONUtil.toBean(afterIncomeGroupStr, AfterIncomegroup.class);
-            if (Objects.isNull(afterIncomegroup)) {
-                throw new CostException("未能正确归集对应的....");
-            }
-            // 转换一下其他的
-            if (afterIncomegroup.getDirectStatus() == 2) {
-                afterIncomegroup.setDirectStatus(0);
-            }
-            incomeCollection.setIsDirectIncome(afterIncomegroup.getDirectStatus());
-            // 开单中心的数据
-            incomeCollection.setDepartmentCode(afterIncomegroup.getOpenDepartmentCode());
-            incomeCollection.setDepartmentName(afterIncomegroup.getOpenDepartmentName());
-            incomeCollection.setResponsibilityCode(afterIncomegroup.getResponsibilityCode());
-            incomeCollection.setResponsibilityName(afterIncomegroup.getResponsibilityName());
-
-            list.add(incomeCollection);
-            // 执行科室数据
-            incomeCollection.setDepartmentCode(afterIncomegroup.getStartDepartmentCode());
-            incomeCollection.setDepartmentName(afterIncomegroup.getStartDepartmentName());
-            incomeCollection.setResponsibilityCode(afterIncomegroup.getResponsibilityCode());
-            incomeCollection.setResponsibilityName(afterIncomegroup.getResponsibilityName());
-            list.add(incomeCollection);
-        });
 
 
+        // todo  可能几十万次数据 需要分段异步多线程处理,
+        // 1个小时
+        String key = "collect" + hospId;
+        String timestamp = DateUtil.offsetMillisecond(DateUtil.date(), 60 * 60).getTime() + "";
+        boolean lock = redisLock.lock(key, timestamp);
+        try {
+            if (lock) {
+                List<CostIncomeGroup> costIncomeGroups = incomeGroupMapper.selectList(
+                        new LambdaQueryWrapper<CostIncomeGroup>()
+                                .eq(CostIncomeGroup::getDateYear, year)
+                                .eq(CostIncomeGroup::getDateMonth, month)
+                                .eq(CostIncomeGroup::getHospId, hospId)
+                );
+                if (costIncomeGroups.isEmpty()) {
+                    String format = StrUtil.format("{}年{}月数据不存在,请先导入数据", year, month);
+                    throw new CostException(format);
+                }
+
+                // 删掉已归集的数据
+                this.remove(
+                        new LambdaQueryWrapper<IncomeCollection>().eq(IncomeCollection::getYear, year).eq(IncomeCollection::getMonth, month).eq(IncomeCollection::getHospId, hospId)
+                );
+                // 根据会计科目和成本项目归纳所有数据
+                Map<String, List<CostIncomeGroup>> collectMap = costIncomeGroups.stream()
+                        .collect(Collectors.groupingBy(i -> i.getAccountCode() + "cost" + i.getProductCode()));
+
+                // 遍历map 组装成List保存
+                List<IncomeCollection> list = new LinkedList<>();
+                Set<Map.Entry<String, List<CostIncomeGroup>>> entries = collectMap.entrySet();
+                entries.stream().map(Map.Entry::getValue).flatMap(Collection::stream).forEach(costIncomeGroup -> {
+                    IncomeCollection incomeCollection = new IncomeCollection();
+                    incomeCollection.setYear(year);
+                    incomeCollection.setMonth(month);
+                    incomeCollection.setAccountingCode(costIncomeGroup.getAccountCode());
+                    incomeCollection.setAccountingName(costIncomeGroup.getAccountName());
+                    incomeCollection.setProductName(costIncomeGroup.getProductName());
+                    incomeCollection.setProductCode(costIncomeGroup.getProductCode());
+                    incomeCollection.setAmount(costIncomeGroup.getAmount());
+                    incomeCollection.setHospId(hospId);
+                    // todo 来源id暂时不确定
+                    incomeCollection.setFileId(costIncomeGroup.getFileId());
+                    incomeCollection.setCreateTime(System.currentTimeMillis());
+                    String afterIncomeGroupStr = costIncomeGroup.getAfterIncomeGroup();
+                    AfterIncomegroup afterIncomegroup = JSONUtil.toBean(afterIncomeGroupStr, AfterIncomegroup.class);
+                    if (Objects.isNull(afterIncomegroup)) {
+                        throw new CostException("未能正确归集对应的....");
+                    }
+                    // 转换一下其他的
+                    if (afterIncomegroup.getDirectStatus() == 2) {
+                        afterIncomegroup.setDirectStatus(0);
+                    }
+                    incomeCollection.setIsDirectIncome(afterIncomegroup.getDirectStatus());
+                    // 开单中心的数据
+                    incomeCollection.setDepartmentCode(afterIncomegroup.getOpenDepartmentCode());
+                    incomeCollection.setDepartmentName(afterIncomegroup.getOpenDepartmentName());
+                    incomeCollection.setResponsibilityCode(afterIncomegroup.getResponsibilityCode());
+                    incomeCollection.setResponsibilityName(afterIncomegroup.getResponsibilityName());
+
+                    list.add(incomeCollection);
+                    // 执行科室数据
+                    incomeCollection.setDepartmentCode(afterIncomegroup.getStartDepartmentCode());
+                    incomeCollection.setDepartmentName(afterIncomegroup.getStartDepartmentName());
+                    incomeCollection.setResponsibilityCode(afterIncomegroup.getResponsibilityCode());
+                    incomeCollection.setResponsibilityName(afterIncomegroup.getResponsibilityName());
+                    list.add(incomeCollection);
+                });
+
+
+                // TODO: 2021/8/10 几十万条数据如何处理 待测试处理
+                this.saveBatch(list);
+            } else {
+                throw new CostException("已有人在操作,请稍后重试");
+            }
+        } finally {
+            redisLock.release(key, timestamp);
+        }
 
 
-        // TODO: 2021/8/10 几十万条数据如何处理 待测试处理
-        this.saveBatch(list);
     }
     }
 
 
     /**
     /**
@@ -184,4 +216,88 @@ public class IncomeCollectionServiceImpl
 
 
         return new PageUtils(list, count, pageSize, current, totalAmount);
         return new PageUtils(list, count, pageSize, current, totalAmount);
     }
     }
+
+    /**
+     * 数据报表
+     *
+     * @param collectDTO
+     * @return
+     */
+    @Override
+    public CollectDataFormVO collectDataForm(CollectDTO collectDTO) {
+        Long hospId = collectDTO.getHospId();
+        String date = collectDTO.getDate();
+        // 1. 得到所有的标题栏 责任中心代码
+        List<CodeAndNameVO> responsibilities = this.baseMapper.getResponsibility(hospId, collectDTO.getResponsibilityCode(), date).stream().distinct().collect(Collectors.toList());
+        if (responsibilities.isEmpty()) {
+            return new CollectDataFormVO();
+        }
+        List<String> responsibilityCodes = responsibilities.stream().map(CodeAndNameVO::getCode).collect(Collectors.toList());
+        responsibilities.add(0, new CodeAndNameVO("#", "#"));
+        responsibilities.add(responsibilities.size(), new CodeAndNameVO("合计", "合计"));
+        List<String> titleData = responsibilities.stream().map(CodeAndNameVO::getName).collect(Collectors.toList());
+        Map<Integer, String> titleMap = new HashMap<>();
+        for (int i = 0; i < titleData.size(); i++) {
+            titleMap.put(i + 1, titleData.get(i));
+        }
+
+        // 所有的数据格式
+        List<CodeAndNameVO> realData = this.baseMapper.getAccount(hospId, collectDTO.getAccountingCode(), date);
+        if (realData.isEmpty()) {
+            return new CollectDataFormVO();
+        }
+        // realData [#,123,123,"合计"]
+        List<Map<Integer, Object>> realDatas = new ArrayList<>();
+        List<CodeAndNameVO> accounts = realData.stream().distinct().collect(Collectors.toList());
+
+        for (CodeAndNameVO account : accounts) {
+            Map<Integer, Object> map = new HashMap<>();
+            for (int i = 0; i < responsibilities.size(); i++) {
+                if (i == 0) {
+                    map.put(i + 1, accounts.get(i).getName());
+                    continue;
+                } else if (i == responsibilities.size() - 1) {
+                    // TODO: 2021/8/12 合计
+                    BigDecimal amount = this.baseMapper.getCountAccountAndResponsibilities(hospId, date, account.getCode(), responsibilityCodes);
+                    map.put(i + 1, amount);
+                    continue;
+                }
+                List<IncomeCollection> list = this.list(
+                        new LambdaQueryWrapper<IncomeCollection>().select(IncomeCollection::getAmount)
+                                .eq(IncomeCollection::getHospId, hospId)
+                                .eq(IncomeCollection::getYear, date.substring(0, 4))
+                                .eq(IncomeCollection::getMonth, date.substring(4))
+                                .eq(IncomeCollection::getAccountingCode, account.getCode())
+                                .eq(IncomeCollection::getResponsibilityCode, responsibilities.get(i).getCode())
+                );
+                if (list.isEmpty()) {
+                    map.put(i + 1, new BigDecimal("0.0000"));
+                } else {
+                    BigDecimal reduce = list.stream().map(IncomeCollection::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
+                    map.put(i + 1, reduce);
+                }
+            }
+            realDatas.add(map);
+        }
+//
+        // 合计栏计算
+        // 长度一致的
+        List<String> accountingCodes = realData.stream().map(CodeAndNameVO::getCode).collect(Collectors.toList());
+        Map<Integer, Object> map = new HashMap<>();
+        for (int i = 0; i < responsibilities.size(); i++) {
+            if (i == 0) {
+                map.put(i + 1, "合计");
+                continue;
+            } else if (i == responsibilities.size() - 1) {
+                // 统计问题
+                BigDecimal bigDecimal = this.baseMapper.getCountByResponsibilitiesAndAccounts(responsibilityCodes, accountingCodes, hospId, date);
+                map.put(i + 1, bigDecimal);
+                continue;
+            }
+            BigDecimal bigDecimal = this.baseMapper.getCountByResponseAndAccounts(responsibilities.get(i).getCode(), accountingCodes, hospId, date);
+            map.put(i + 1, bigDecimal);
+        }
+
+        return new CollectDataFormVO(titleMap, realDatas, map);
+    }
 }
 }

+ 10 - 0
src/main/java/com/imed/costaccount/web/IncomeCollectionController.java

@@ -3,12 +3,14 @@ package com.imed.costaccount.web;
 import com.imed.costaccount.common.util.PageUtils;
 import com.imed.costaccount.common.util.PageUtils;
 import com.imed.costaccount.common.util.Result;
 import com.imed.costaccount.common.util.Result;
 import com.imed.costaccount.model.dto.CollectDTO;
 import com.imed.costaccount.model.dto.CollectDTO;
+import com.imed.costaccount.model.vo.CollectDataFormVO;
 import com.imed.costaccount.service.IncomeCollectionService;
 import com.imed.costaccount.service.IncomeCollectionService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
 import javax.validation.Valid;
 import javax.validation.Valid;
+import java.util.List;
 
 
 
 
 /**
 /**
@@ -62,4 +64,12 @@ public class IncomeCollectionController extends AbstractController {
         PageUtils pageUtils = incomeCollectionService.collectList(collectDTO);
         PageUtils pageUtils = incomeCollectionService.collectList(collectDTO);
         return Result.ok(pageUtils);
         return Result.ok(pageUtils);
     }
     }
+
+    @ApiOperation("归集后数据报表")
+    @GetMapping("/collectDataForm")
+    public Result collectDataForm(@ModelAttribute @Valid CollectDTO collectDTO) {
+        collectDTO.setHospId(getHospId());
+        CollectDataFormVO form = incomeCollectionService.collectDataForm(collectDTO);
+        return Result.ok(form);
+    }
 }
 }

+ 1 - 0
src/main/resources/application-dev.yml

@@ -35,6 +35,7 @@ spring:
         max-idle: 10
         max-idle: 10
         max-wait: -1
         max-wait: -1
         min-idle: 0
         min-idle: 0
+  profiles: dev
 
 
 mybatis-plus:
 mybatis-plus:
   mapper-locations: classpath*:/mapper/*.xml
   mapper-locations: classpath*:/mapper/*.xml

+ 61 - 0
src/main/resources/mapper/IncomeCollectionMapper.xml

@@ -68,4 +68,65 @@
     </select>
     </select>
 
 
 
 
+    <select id="getCountByResponseAndAccounts" resultType="java.math.BigDecimal">
+        select IFNULL(sum(amount), 0) as totalAmount
+        from cost_income_collection
+        where delete_time = 0 and hosp_id = #{hospId} and responsibility_code = #{responsibilityCode}
+        <if test="date != null and date != ''">
+            and `year` = YEAR(concat(#{date},'01')) and `month` = MONTH(concat(#{date},'01'))
+        </if>
+        and accounting_code in
+        <foreach collection="accountingCodes" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </select>
+    <select id="getResponsibility" resultType="com.imed.costaccount.model.vo.CodeAndNameVO">
+        select responsibility_code as code ,responsibility_name as name from cost_income_collection
+        where delete_time = 0 and hosp_id = #{hospId}
+        <if test="responsibilityCode != null and responsibilityCode != ''">
+            and responsibility_code = #{responsibilityCode}
+        </if>
+        <if test="date != null and date != ''">
+            and `year` = YEAR(concat(#{date},'01')) and `month` = MONTH(concat(#{date},'01'))
+        </if>
+    </select>
+    <select id="getAccount" resultType="com.imed.costaccount.model.vo.CodeAndNameVO">
+        select accounting_code as code ,accounting_name as name from cost_income_collection
+        where delete_time = 0 and hosp_id = #{hospId}
+        <if test="accountingCode != null and accountingCode != ''">
+            and accounting_code = #{accountingCode}
+        </if>
+        <if test="date != null and date != ''">
+            and `year` = YEAR(concat(#{date},'01')) and `month` = MONTH(concat(#{date},'01'))
+        </if>
+    </select>
+    <select id="getCountAccountAndResponsibilities" resultType="java.math.BigDecimal">
+        select IFNULL(sum(amount), 0) as totalAmount
+        from cost_income_collection
+        where delete_time = 0 and hosp_id = #{hospId} and accounting_code = #{code}
+        <if test="date != null and date != ''">
+            and `year` = YEAR(concat(#{date},'01')) and `month` = MONTH(concat(#{date},'01'))
+        </if>
+        and responsibility_code in
+        <foreach collection="responsibilityCodes" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </select>
+    <select id="getCountByResponsibilitiesAndAccounts" resultType="java.math.BigDecimal">
+        select IFNULL(sum(amount), 0) as totalAmount
+        from cost_income_collection
+        where delete_time = 0 and hosp_id = #{hospId} and responsibility_code in
+        <foreach  collection="responsibilityCodes" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+        <if test="date != null and date != ''">
+            and `year` = YEAR(concat(#{date},'01')) and `month` = MONTH(concat(#{date},'01'))
+        </if>
+        and accounting_code in
+        <foreach collection="accountingCodes" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </select>
+
+
 </mapper>
 </mapper>