Procházet zdrojové kódy

Merge branch 'master' of http://47.100.37.243:10080/wutt/manHourHousekeeper

ggooalice před 2 roky
rodič
revize
8a60da2375

+ 5 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java

@@ -213,5 +213,10 @@ public class UserController {
     @RequestMapping("/batchUpdateRole")
     public HttpRespMsg batchUpdateRole(String userIds, Integer roleId) {return userService.batchUpdateRole(userIds, roleId, request); }
 
+    @RequestMapping("/importMonthCost")
+    public HttpRespMsg importMonthCost(@RequestParam MultipartFile file, String ymonth) {
+        return userService.importMonthCost(file, ymonth, request);
+    }
+
 }
 

+ 9 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/UserSalary.java

@@ -19,7 +19,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2021-05-19
+ * @since 2022-10-19
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -61,6 +61,7 @@ public class UserSalary extends Model<UserSalary> {
     @TableField("salary_type")
     private Integer salaryType;
 
+
     /**
      * 更新时间
      */
@@ -68,6 +69,13 @@ public class UserSalary extends Model<UserSalary> {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
     private LocalDateTime indate;
 
+
+    /**
+     * 所属月份
+     */
+    @TableField("ymonth")
+    private String ymonth;
+
     public static UserSalary copyFromUser(User user) {
         UserSalary userSalary = new UserSalary();
         userSalary.setUserId(user.getId());

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/UserService.java

@@ -73,4 +73,6 @@ public interface UserService extends IService<User> {
     HttpRespMsg getUserListByRole(HttpServletRequest request);
 
     HttpRespMsg loginAdminByThirdParty(String jobNumber, String token);
+
+    HttpRespMsg importMonthCost(MultipartFile file, String ymonth, HttpServletRequest request);
 }

+ 153 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java

@@ -18,8 +18,10 @@ import me.chanjar.weixin.mp.api.WxMpService;
 import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
+import org.apache.commons.io.FileUtils;
 import org.apache.poi.hssf.usermodel.*;
-import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.usermodel.XSSFCell;
 import org.apache.poi.xssf.usermodel.XSSFRow;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
@@ -118,6 +120,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
     @Resource
     private UserSalaryMapper userSalaryMapper;
     @Resource
+    private UserSalaryService userSalaryService;
+    @Resource
     private UserVcodeMapper userVcodeMapper;
     @Resource
     private ProjectBasecostSettingMapper projectBasecostSettingMapper;
@@ -259,6 +263,154 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         return httpRespMsg;
     }
 
+    @Override
+    public HttpRespMsg importMonthCost(MultipartFile multipartFile, String yearMonth, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("TOKEN"));
+        Integer companyId = user.getCompanyId();
+        //然后处理文件
+        String fileName = multipartFile.getOriginalFilename();
+        File file = new File(fileName == null ? "file" : fileName);
+        InputStream inputStream = null;
+        OutputStream outputStream = null;
+        try {
+            inputStream = multipartFile.getInputStream();
+            outputStream = new FileOutputStream(file);
+            byte[] buffer = new byte[4096];
+            int temp = 0;
+            while ((temp = inputStream.read(buffer, 0, 4096)) != -1) {
+                outputStream.write(buffer, 0, temp);
+            }
+            inputStream.close();
+            outputStream.close();
+            //然后解析表格
+            Workbook wb = WorkbookFactory.create(new FileInputStream(file));
+            Sheet sheet = wb.getSheetAt(0);
+            //要插入的账号列表
+            List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+            //获取月成本列表
+            TimeType timeType = timeTypeMapper.selectById(companyId);
+            //需要更新成本的人员数据
+            List<User> updateUserList = new ArrayList<>();
+            String startStr = yearMonth + "-01";
+            String endStr = yearMonth + "-31";
+            BigDecimal monthTotalHours = timeType.getMonthDays().multiply(new BigDecimal(timeType.getAllday()));
+            //由于第一行需要指明列对应的标题
+            for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
+                Row row = sheet.getRow(rowIndex);
+                if (row == null) {
+                    continue;
+                }
+                if (ExcelUtil.isRowEmpty(row)) {
+                    continue;
+                }
+                //工号 姓名 薪资
+                Cell jobNumberCell = row.getCell(0);
+
+                if (jobNumberCell != null) {
+                    jobNumberCell.setCellType(CellType.STRING);
+                }
+
+                Cell nameCell = row.getCell(1);
+                Cell salaryCell = row.getCell(2);
+                nameCell.setCellType(CellType.STRING);
+
+                String name = nameCell.getStringCellValue().trim().replaceAll("\\u00a0", "");
+                if (name.equals(MessageUtils.message("entry.name")) && rowIndex == 0) {
+                    continue;
+                }
+                String cellJobNumber = jobNumberCell != null ?jobNumberCell.getStringCellValue().trim().replaceAll("\\u00a0", ""):null;
+                Optional<User> first = null;
+                if (!StringUtils.isEmpty(cellJobNumber)) {
+                    //优先按照工号匹配
+                    first = userList.stream().filter(u ->
+                            u.getJobNumber() != null && u.getJobNumber().equals(cellJobNumber)).findFirst();
+                }
+                if (first == null || !first.isPresent()) {
+                    //按照姓名匹配
+                    first = userList.stream().filter(u ->
+                            u.getName().equals(name)).findFirst();
+                }
+                if (first != null && first.isPresent()) {
+                    if (salaryCell != null) {
+                        salaryCell.setCellType(CellType.STRING);
+                        String item = salaryCell.getStringCellValue();
+                        BigDecimal monthSalary = item != null ? new BigDecimal(item.trim().replaceAll("\\u00a0", "")) : BigDecimal.valueOf(0);
+                        User localUser = new User();
+                        User findUser = first.get();
+                        localUser.setId(findUser.getId());
+                        localUser.setMonthCost(monthSalary);
+                        localUser.setName(findUser.getName());
+                        localUser.setSalaryType(findUser.getSalaryType());
+                        //计算时薪
+                        localUser.setCost(monthSalary.divide(monthTotalHours, 6, BigDecimal.ROUND_HALF_UP));
+                        updateUserList.add(localUser);
+                    } else {
+                        //薪资为空的跳过
+                        continue;
+                    }
+                } else {
+                    msg.setError(MessageUtils.message("group.userNullById",name,cellJobNumber));
+                    return msg;
+                }
+            }
+
+            if (updateUserList.size() > 0) {
+                //有人员薪资更新
+                updateBatchById(updateUserList);
+                //记录薪资变动
+                List<UserSalary> salaryChangeList = new ArrayList<>();
+                for (User u : updateUserList) {
+                    UserSalary salary = UserSalary.copyFromUser(u);
+                    salary.setYmonth(yearMonth);
+                    salaryChangeList.add(salary);
+                }
+                userSalaryService.saveBatch(salaryChangeList);
+            }
+            //更新该月份的日报相关的成本
+            if (!StringUtils.isEmpty(yearMonth)) {
+                List<Report> reportList = reportMapper.selectSimpleTime(companyId, startStr, endStr);
+                if (reportList.size() > 0) {
+                    List<Report> updateReportList = new ArrayList<>();
+                    for (Report r : reportList) {
+                        Optional<User> first = updateUserList.stream().filter(u -> u.getId().equals(r.getCreatorId())).findFirst();
+                        if (first.isPresent()) {
+                            BigDecimal hourCost = first.get().getCost();
+                            r.setCost(hourCost.multiply(new BigDecimal(r.getWorkingTime())));
+                            r.setCreatorId(null);
+                            r.setWorkingTime(null);
+                            updateReportList.add(r);
+                        }
+                    }
+                    //批量更新日报的成本
+                    if (updateReportList.size() > 0) {
+                        reportService.updateBatchById(updateReportList);
+                    }
+                }
+            }
+        }catch (IOException e){
+            e.printStackTrace();
+            //msg.setError("文件处理错误");
+            msg.setError(MessageUtils.message("file.error"));
+        }catch (InvalidFormatException e) {
+            e.printStackTrace();
+            //msg.setError("文件格式错误,如果安装了加密软件需要先解密再上传");
+            msg.setError(MessageUtils.message("file.FormatErrorAndDecrypt"));
+        } finally {
+            //关闭流
+            try {
+                if (outputStream != null && inputStream != null) {
+                    outputStream.close();
+                    inputStream.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            System.out.println(file.delete());
+        }
+        return msg;
+    }
+
 
     public void setUserRoleMenu(UserVO user) {
         Integer roleId = user.getRoleId();

+ 6 - 6
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml

@@ -78,10 +78,10 @@
     </if>
         <if test="stateKey!=null">
             <if test="stateKey==1">
-                a.state = 1 or a.state=0
+                (a.state = 1 or a.state = 0 or a.state = -1)
             </if>
             <if test="stateKey==2">
-                a.state=0
+                (a.state=0 or a.state = -1)
             </if>
         </if>)
         <if test="startDate != null and startDate != ''">
@@ -160,10 +160,10 @@
     </if>
         <if test="stateKey!=null">
             <if test="stateKey==1">
-                a.state = 1 or a.state=0
+                (a.state = 1 or a.state=0 or a.state = -1)
             </if>
             <if test="stateKey==2">
-                a.state=0
+                (a.state=0 or a.state = -1)
             </if>
         </if>)
         <if test="startDate != null and startDate != ''">
@@ -207,10 +207,10 @@
         </if>
         <if test="stateKey!=null">
             <if test="stateKey==1">
-                a.state = 1 or a.state=0
+                (a.state = 1 or a.state=0 or a.state = -1)
             </if>
             <if test="stateKey==2">
-                a.state=0
+                (a.state=0 or a.state = -1)
             </if>
         </if>
         )

+ 2 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserSalaryMapper.xml

@@ -11,11 +11,12 @@
         <result column="cost" property="cost" />
         <result column="salary_type" property="salaryType" />
         <result column="indate" property="indate" />
+        <result column="ymonth" property="ymonth" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, user_id, user_name, month_cost, cost, salary_type, indate
+        id, user_id, user_name, month_cost, cost, salary_type, indate, ymonth
     </sql>
 
 </mapper>

binární
fhKeeper/formulahousekeeper/management-platform/src/main/resources/upload/Salary Import Template.xlsx


binární
fhKeeper/formulahousekeeper/management-platform/src/main/resources/upload/薪资导入模板.xlsx


+ 2 - 0
fhKeeper/formulahousekeeper/timesheet/src/i18n/en.json

@@ -984,6 +984,7 @@
   "create": "create",
   "gong": "common",
   "addpersonnel": "Add people",
+  "importSalary": "Import Salary",
   "associateenterprisemicroidentity": "Affiliated Enterprise and Micro Identity",
   "customConfiguration": "custom configuration",
   "exportpersonnel": "Export people",
@@ -1052,6 +1053,7 @@
   "configurationoptions": "configuration options",
   "newConfigurationOptions": "Added configuration options",
   "personnelimporttemplate": "Person Import Template",
+  "salaryTemplate": "Salary Import Template",
   "oneWeix": "1. Fill in the corporate WeChat address book Secret",
   "synchronizetheenterprisewechataddressbook": "Synchronize corporate WeChat address book",
   "firststep": "Step 1: Enter the management background",

+ 2 - 0
fhKeeper/formulahousekeeper/timesheet/src/i18n/zh.json

@@ -987,6 +987,7 @@
   "customConfiguration": "自定义配置",
   "exportpersonnel": "导出人员",
   "addpersonnel": "添加人员",
+  "importSalary": "导入薪资",
   "associateenterprisemicroidentity": "关联企微身份",
   "synchronizetheenterprisemicrodirectory": "同步企微通讯录",
   "synchronizetheaddressbook": "同步钉钉通讯录",
@@ -1052,6 +1053,7 @@
   "addededitedconfigurationoptions": "新增/编辑配置选项",
   "batchimportofpersonnel": "人员批量导入",
   "personnelimporttemplate": "人员导入模板",
+  "salaryTemplate": "薪资导入模板",
   "synchronizetheenterprisewechataddressbook": "同步企业微信通讯录",
   "oneWeix": "1. 填写企业微信通讯录Secret",
   "firststep": "第一步:进入管理后台",

+ 78 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/team/index.vue

@@ -100,6 +100,10 @@
                     <el-form-item style="float:right;" v-if="user.dingdingUserid == null && permissions.structureAdd && user.userNameNeedTranslate != '1'">
                         <el-link type="primary" :underline="false" @click="openInsertDialog(null)">{{ $t('addpersonnel') }}</el-link>
                     </el-form-item>
+                    <!--导入薪资-->
+                    <el-form-item style="float:right;" v-if="permissions.structurePersonnel">
+                        <el-link type="primary" :underline="false" @click="importUserSalary(null)">{{ $t('importSalary') }}</el-link>
+                    </el-form-item>
                     
                     <el-form-item style="float:right;" v-if="user.dingdingUserid == null && permissions.structureImport && user.userNameNeedTranslate != '1'">
                         <el-link type="primary" :underline="false" @click="importUserC">{{ $t('bulkimport') }}</el-link>
@@ -636,6 +640,23 @@
             </el-upload>
             </p>
         </el-dialog>
+        <!--薪资导入-->
+        <el-dialog :title="$t('importSalary')" v-if="importUserSalaryDialog" :visible.sync="importUserSalaryDialog" customClass="customWidth" width="500px">
+            <p>1. {{ $t('other.download') }}
+            <el-link type="primary" style="margin-left:5px;" :underline="false" href="./upload/薪资导入模板.xlsx" :download="$t('salaryTemplate')+'.xlsx'">{{$t('salaryTemplate')}}.xlsx</el-link>
+            </p>
+            <p>2. 
+              {{ $t('Selectmonth') }}
+              <el-date-picker v-model="ymonth" type="month" :placeholder="$t('Selectmonth')" format="yyyy-MM" value-format="yyyy-MM"></el-date-picker>
+              <br/><span style="margin-left:10px;margin-top:8px;color:#999;">({{$t('Recalculatereportedcostsforthemonth')}})</span>
+            </p>
+            <p>3. {{ $t('exceltemplateanduploadit') }}。</p>
+            <p style="display: flex;justify-content: center;padding-bottom:1em;">
+                <el-upload ref="uploadSalaryRef"  action="#" :limit="1" :http-request="importSalaryData" :show-file-list="false">
+                <el-button type="primary" :underline="false" :loading="importingSalaryData">{{ $t('other.startImporting') }}</el-button>
+            </el-upload>
+            </p>
+        </el-dialog>
         <el-dialog :title="$t('synchronizetheenterprisewechataddressbook')" v-if="showSyncCWDialog" :visible.sync="showSyncCWDialog" customClass="customWidth" width="500px">
             <p>{{ $t('oneWeix') }} 
                 <el-popover placement="top" width="1200" trigger="hover">
@@ -730,6 +751,9 @@ export default {
   },
   data() {
     return {
+      syncHistoryReport: true,
+      ymonth: null,
+      importingSalaryData: false,
       translation: '1', // 1、文字, 2、部门, 3、人员
       fullscreenLoading: false,
       syncMembByCardTimeResultGialog:false,
@@ -902,6 +926,7 @@ export default {
       status: "1",
       role: "",
       jDarr: [],
+      importUserSalaryDialog: false,
       handleSelectionZzjgDate: [],
       handleSelectionZzjgwillchange: null,
       acquireRoleList: [], // 角色列表
@@ -1958,6 +1983,9 @@ export default {
     importUserC() {
       this.importDialog = true;
     },
+    importUserSalary() {
+      this.importUserSalaryDialog = true;
+    },
     // 批量导入人员
     importUser(item) {
       //首先判断文件类型
@@ -2007,6 +2035,55 @@ export default {
         );
       }
     },
+    //导入人员薪资
+    importSalaryData(item) {
+      //首先判断文件类型
+      let str = item.file.name.split(".");
+      let format = str[str.length - 1];
+
+      if (format != "xls" && format != "xlsx") {
+        this.$message({
+          message: this.$t('other.PleaseselecttheXLSorXLSXfile'),
+          type: "error",
+        });
+      } else {
+        let formData = new FormData();
+        formData.append("file", item.file);
+        formData.append("ymonth", this.ymonth);
+        this.importingSalaryData = true;
+        this.http.uploadFile(
+          "/user/importMonthCost",
+          formData,
+          (res) => {
+            this.importingSalaryData = false;
+            this.$refs.uploadSalaryRef.clearFiles();
+            this.listLoading = false;
+            if (res.code == "ok") {
+              this.$message({
+                message: this.$t('other.importSuccess'),
+                type: "success",
+              });
+              //重新读取列表
+              this.getUser();
+              this.importUserSalaryDialog = false;
+            } else {
+              this.$message({
+                message: res.msg,
+                type: "error",
+              });
+            }
+          },
+          (error) => {
+            this.importingSalaryData = false;
+            this.$refs.uploadSalaryRef.clearFiles();
+            this.$message({
+              message: error,
+              type: "error",
+            });
+          }
+        );
+      }
+    },
 
     //分页
     handleCurrentChange(val) {
@@ -3151,6 +3228,7 @@ export default {
   },
   mounted() {
     this.deactiveDate = util.formatDate.format(new Date(), "yyyy-MM-dd");
+    this.ymonth = util.formatDate.format(new Date(), "yyyy-MM");
     this.getDepartment();
     this.getUser();
     this.getCompanyTimeSetting();