|
@@ -5,30 +5,40 @@ import com.alibaba.fastjson.JSONObject;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
import com.management.platform.entity.ExpenseItem;
|
|
import com.management.platform.entity.ExpenseItem;
|
|
import com.management.platform.entity.ExpenseSheet;
|
|
import com.management.platform.entity.ExpenseSheet;
|
|
import com.management.platform.entity.Project;
|
|
import com.management.platform.entity.Project;
|
|
import com.management.platform.entity.User;
|
|
import com.management.platform.entity.User;
|
|
import com.management.platform.mapper.ExpenseItemMapper;
|
|
import com.management.platform.mapper.ExpenseItemMapper;
|
|
import com.management.platform.mapper.ExpenseSheetMapper;
|
|
import com.management.platform.mapper.ExpenseSheetMapper;
|
|
|
|
+import com.management.platform.mapper.ProjectMapper;
|
|
import com.management.platform.mapper.UserMapper;
|
|
import com.management.platform.mapper.UserMapper;
|
|
import com.management.platform.service.ExpenseItemService;
|
|
import com.management.platform.service.ExpenseItemService;
|
|
import com.management.platform.service.ExpenseSheetService;
|
|
import com.management.platform.service.ExpenseSheetService;
|
|
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
|
|
|
+import com.management.platform.util.ExcelUtil;
|
|
import com.management.platform.util.HttpRespMsg;
|
|
import com.management.platform.util.HttpRespMsg;
|
|
|
|
+import org.apache.poi.EncryptedDocumentException;
|
|
|
|
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
|
|
|
+import org.apache.poi.ss.usermodel.CellType;
|
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFCell;
|
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFRow;
|
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFSheet;
|
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.util.StringUtils;
|
|
import org.springframework.util.StringUtils;
|
|
-import org.springframework.web.bind.annotation.RequestParam;
|
|
|
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
import javax.annotation.Resource;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
+import java.io.*;
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
+import java.time.Instant;
|
|
import java.time.LocalDate;
|
|
import java.time.LocalDate;
|
|
|
|
+import java.time.ZoneId;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.time.format.DateTimeFormatter;
|
|
-import java.util.ArrayList;
|
|
|
|
-import java.util.HashMap;
|
|
|
|
-import java.util.List;
|
|
|
|
-import java.util.Map;
|
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
|
/**
|
|
/**
|
|
* <p>
|
|
* <p>
|
|
@@ -49,8 +59,8 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
|
|
private ExpenseItemService expenseItemService;
|
|
private ExpenseItemService expenseItemService;
|
|
@Resource
|
|
@Resource
|
|
private ExpenseItemMapper expenseItemMapper;
|
|
private ExpenseItemMapper expenseItemMapper;
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+ @Resource
|
|
|
|
+ private ProjectMapper projectMapper;
|
|
@Override
|
|
@Override
|
|
public HttpRespMsg add(ExpenseSheet sheet, String items, String userId) {
|
|
public HttpRespMsg add(ExpenseSheet sheet, String items, String userId) {
|
|
HttpRespMsg msg = new HttpRespMsg();
|
|
HttpRespMsg msg = new HttpRespMsg();
|
|
@@ -184,4 +194,199 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
|
|
expenseSheetMapper.updateById(sheet);
|
|
expenseSheetMapper.updateById(sheet);
|
|
return new HttpRespMsg();
|
|
return new HttpRespMsg();
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public HttpRespMsg importData(HttpServletRequest request,MultipartFile[] files) {
|
|
|
|
+ HttpRespMsg msg = new HttpRespMsg();
|
|
|
|
+ User user = userMapper.selectById(request.getHeader("token"));
|
|
|
|
+ //然后处理文件
|
|
|
|
+// List<MultipartFile> multipartFiles = JSONArray.parseArray(files, MultipartFile.class);
|
|
|
|
+ for (MultipartFile multipartFile : files) {
|
|
|
|
+ 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();
|
|
|
|
+ //然后解析表格
|
|
|
|
+ XSSFWorkbook workbook = new XSSFWorkbook(file);
|
|
|
|
+ //我们只需要第一个sheet
|
|
|
|
+ XSSFSheet sheet = workbook.getSheetAt(0);
|
|
|
|
+ //获取全部人员
|
|
|
|
+ List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", user.getCompanyId()));
|
|
|
|
+ List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", user.getCompanyId()));
|
|
|
|
+ System.out.println(projectList);
|
|
|
|
+ //由于第一行需要指明报销人列对应的标题
|
|
|
|
+ XSSFRow firstRow = sheet.getRow(2);
|
|
|
|
+ if (firstRow == null) {
|
|
|
|
+ msg.setError("错误数据,导入失败");
|
|
|
|
+ return msg;
|
|
|
|
+ }
|
|
|
|
+ //报销人 填报日期 费用类型 备注
|
|
|
|
+ XSSFCell reimburserCell = firstRow.getCell(0);
|
|
|
|
+ XSSFCell reportDateCell = firstRow.getCell(1);
|
|
|
|
+ XSSFCell expenseTypeCell = firstRow.getCell(2);
|
|
|
|
+ XSSFCell remarksCell = firstRow.getCell(3);
|
|
|
|
+
|
|
|
|
+ if (reimburserCell != null) reimburserCell.setCellType(CellType.STRING);
|
|
|
|
+ if (reportDateCell != null) reportDateCell.setCellType(CellType.NUMERIC);
|
|
|
|
+ if (expenseTypeCell != null) expenseTypeCell.setCellType(CellType.STRING);
|
|
|
|
+ if (remarksCell != null) remarksCell.setCellType(CellType.STRING);
|
|
|
|
+ if (reimburserCell == null) {//报销人为空的直接跳过
|
|
|
|
+ throw new Exception("报销人名称不能为空");
|
|
|
|
+ }
|
|
|
|
+ if (expenseTypeCell == null) {
|
|
|
|
+ throw new Exception("费用类型不能为空");
|
|
|
|
+ }
|
|
|
|
+ ExpenseSheet expenseSheet = new ExpenseSheet();
|
|
|
|
+ //处理编号
|
|
|
|
+ DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyyMMdd");
|
|
|
|
+ String format = yyyyMMdd.format(LocalDate.now());
|
|
|
|
+ List<ExpenseSheet> list = expenseSheetMapper.selectList(new QueryWrapper<ExpenseSheet>()
|
|
|
|
+ .eq("company_id", user.getCompanyId())
|
|
|
|
+ .like("code", format).orderByDesc("id").last("limit 1"));
|
|
|
|
+ int start = 1;
|
|
|
|
+ if (list.size() > 0) {
|
|
|
|
+ String code = list.get(0).getCode();
|
|
|
|
+ code = code.substring(format.length(), code.length());
|
|
|
|
+ System.out.println("code=====" + code);
|
|
|
|
+ if (code.length() > 0) {
|
|
|
|
+ start = Integer.parseInt(code) + 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ expenseSheet.setCode(format + start);
|
|
|
|
+ expenseSheet.setCompanyId(user.getCompanyId());
|
|
|
|
+ LocalDate localDate = Instant.ofEpochMilli(reportDateCell.getDateCellValue().getTime())
|
|
|
|
+ .atZone(ZoneId.systemDefault()).toLocalDate();
|
|
|
|
+ expenseSheet.setCreateDate(localDate);
|
|
|
|
+ Optional<User> first = userList.stream().filter(us -> us.getName().equals(reimburserCell.getStringCellValue())).findFirst();
|
|
|
|
+ if (first.isPresent()) {
|
|
|
|
+ expenseSheet.setOwnerId(first.get().getId());
|
|
|
|
+ expenseSheet.setOwnerName(first.get().getName());
|
|
|
|
+ } else {
|
|
|
|
+ throw new Exception("报销人[" +reimburserCell+"]不存在");
|
|
|
|
+ }
|
|
|
|
+ expenseSheet.setOperatorId(user.getId());
|
|
|
|
+ expenseSheet.setRemark(remarksCell.getStringCellValue());
|
|
|
|
+ switch (expenseTypeCell.getStringCellValue()) {
|
|
|
|
+ case "一般":
|
|
|
|
+ expenseSheet.setType(0);
|
|
|
|
+ break;
|
|
|
|
+ case "差旅":
|
|
|
|
+ expenseSheet.setType(1);
|
|
|
|
+ break;
|
|
|
|
+ case "外包":
|
|
|
|
+ expenseSheet.setType(2);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ expenseSheetMapper.insert(expenseSheet);
|
|
|
|
+ //前提需要指定第一二行为报销人数据 从第三行数据开始处理 报销单据详情
|
|
|
|
+ int rowNum = sheet.getLastRowNum();
|
|
|
|
+ //计算总费用
|
|
|
|
+ BigDecimal bigDecimal = new BigDecimal(0);
|
|
|
|
+ List<ExpenseItem> expenseItemList = new ArrayList<>();
|
|
|
|
+ for (int rowIndex = 5; rowIndex <= rowNum; rowIndex++) {
|
|
|
|
+ XSSFRow row = sheet.getRow(rowIndex);
|
|
|
|
+ if (row == null) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ //跳过空行
|
|
|
|
+ if (ExcelUtil.isRowEmpty(row)) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ //项目编号 费用日期 发拍种类 费用类型 费用金额 发票号 税率 税额 备注
|
|
|
|
+ XSSFCell codeCell = row.getCell(0);
|
|
|
|
+ XSSFCell happenDateCell = row.getCell(1);
|
|
|
|
+ XSSFCell invoiceTypeCell = row.getCell(2);
|
|
|
|
+ XSSFCell subExpenseTypeCell = row.getCell(3);
|
|
|
|
+ XSSFCell amountCell = row.getCell(4);
|
|
|
|
+ XSSFCell invoiceNoCell = row.getCell(5);
|
|
|
|
+ XSSFCell taxPercentCell = row.getCell(6);
|
|
|
|
+ XSSFCell remarkCell = row.getCell(7);
|
|
|
|
+
|
|
|
|
+ if (codeCell != null) codeCell.setCellType(CellType.STRING);
|
|
|
|
+ if (happenDateCell != null) happenDateCell.setCellType(CellType.NUMERIC);
|
|
|
|
+ if (invoiceTypeCell != null) invoiceTypeCell.setCellType(CellType.STRING);
|
|
|
|
+ if (subExpenseTypeCell != null) subExpenseTypeCell.setCellType(CellType.STRING);
|
|
|
|
+ if (amountCell != null) amountCell.setCellType(CellType.NUMERIC);
|
|
|
|
+ if (invoiceNoCell != null) invoiceNoCell.setCellType(CellType.STRING);
|
|
|
|
+ if (taxPercentCell != null) taxPercentCell.setCellType(CellType.NUMERIC);
|
|
|
|
+ if (remarkCell != null) remarkCell.setCellType(CellType.STRING);
|
|
|
|
+ ExpenseItem expenseItem = new ExpenseItem();
|
|
|
|
+ Optional<Project> project = projectList.stream().filter(pro ->(StringUtils.isEmpty(pro.getProjectCode())?"":pro.getProjectCode()).equals(codeCell.getStringCellValue())
|
|
|
|
+ || (StringUtils.isEmpty(pro.getProjectName())?"":pro.getProjectName()).equals(codeCell.getStringCellValue())).findFirst();
|
|
|
|
+ if (project.isPresent()) {
|
|
|
|
+ expenseItem.setProjectId(project.get().getId());
|
|
|
|
+ } else {
|
|
|
|
+ throw new Exception("项目编号为[" + codeCell.getStringCellValue() + "]的项目不存在");
|
|
|
|
+ }
|
|
|
|
+ expenseItem.setExpenseId(expenseSheet.getId());
|
|
|
|
+ LocalDate happenDate = Instant.ofEpochMilli(happenDateCell.getDateCellValue().getTime())
|
|
|
|
+ .atZone(ZoneId.systemDefault()).toLocalDate();
|
|
|
|
+ expenseItem.setHappenDate(String.valueOf(happenDate));
|
|
|
|
+ switch (invoiceTypeCell.getStringCellValue()) {
|
|
|
|
+ case "增值税专用发票":
|
|
|
|
+ expenseItem.setInvoiceType(0);
|
|
|
|
+ break;
|
|
|
|
+ case "增值税普通发票":
|
|
|
|
+ expenseItem.setInvoiceType(1);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ expenseItem.setInvoiceNo(invoiceNoCell.getStringCellValue());
|
|
|
|
+ expenseItem.setAmount(amountCell.getNumericCellValue());
|
|
|
|
+ expenseItem.setRemark(remarkCell.getStringCellValue());
|
|
|
|
+ //计算税额
|
|
|
|
+ BigDecimal bd = new BigDecimal(amountCell.getNumericCellValue());
|
|
|
|
+ //原始金额
|
|
|
|
+ BigDecimal divide = bd.divide(BigDecimal.valueOf((1 + taxPercentCell.getNumericCellValue())),2,BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ BigDecimal subtract = bd.subtract(divide);
|
|
|
|
+ expenseItem.setTaxValue(subtract.doubleValue());
|
|
|
|
+ bigDecimal.add(BigDecimal.valueOf(amountCell.getNumericCellValue()));
|
|
|
|
+ expenseItemList.add(expenseItem);
|
|
|
|
+ }
|
|
|
|
+ expenseSheet.setTotalAmount(bigDecimal.doubleValue());
|
|
|
|
+ expenseSheetMapper.updateById(expenseSheet);
|
|
|
|
+ expenseItemService.saveBatch(expenseItemList);
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ } catch (NullPointerException e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ msg.setError("数据格式有误或存在空数据 导入失败");
|
|
|
|
+ return msg;
|
|
|
|
+ } catch (InvalidFormatException e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ msg.setError("文件格式错误,如果安装了加密软件需要先解密再上传");
|
|
|
|
+ } catch (EncryptedDocumentException e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ msg.setError("文件加密状态,需要先解除加密状态再上传");
|
|
|
|
+ return msg;
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ msg.setError("上传失败:" + e.getMessage());
|
|
|
|
+ return msg;
|
|
|
|
+ } finally {
|
|
|
|
+ //关闭流
|
|
|
|
+ try {
|
|
|
|
+ if (outputStream != null && inputStream != null) {
|
|
|
|
+ outputStream.close();
|
|
|
|
+ inputStream.close();
|
|
|
|
+ System.out.println("流已关闭");
|
|
|
|
+ }
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ }
|
|
|
|
+// file.deleteOnExit();//程序退出时删除临时文件
|
|
|
|
+ System.out.println(file.delete());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return msg;
|
|
|
|
+ }
|
|
}
|
|
}
|