Commit 604d908d5ef7796fbd121e04af6404ee8163fb49

Authored by yeqianyong
2 parents 21f80e3f c6c0d839

Merge remote-tracking branch 'origin/master_0929' into master_0929

... ... @@ -12,6 +12,11 @@ public class ChangeData {
12 12 private List<ChangeItem> otherChangeList;
13 13
14 14 /**
  15 + * 变更时间
  16 + */
  17 + private String changeTime;
  18 +
  19 + /**
15 20 * 核心人员变更前
16 21 */
17 22 private List<CorePersonnelHistory> personnelBeforeChangeList;
... ... @@ -44,4 +49,12 @@ public class ChangeData {
44 49 public void setPersonnelAfterChangeList(List<CorePersonnelHistory> personnelAfterChangeList) {
45 50 this.personnelAfterChangeList = personnelAfterChangeList;
46 51 }
  52 +
  53 + public String getChangeTime() {
  54 + return changeTime;
  55 + }
  56 +
  57 + public void setChangeTime(String changeTime) {
  58 + this.changeTime = changeTime;
  59 + }
47 60 }
... ...
... ... @@ -740,7 +740,7 @@ public class ContractDistributorStandardController extends DefaultBaseController
740 740 || "INTL_INVENTORY_AGMT".equals(data.getType())
741 741 || "INTL_OPEN_SPEC_AGMT".equals(data.getType())) {
742 742 setCellValue(sheet, startRow, 9, contractDistributorLineBo.getProcessingFee()); // I列
743   - setCellValue(sheet, startRow, 10, contractDistributorLineBo.getProcessingFee().add(contractDistributorLineBo.getUnitPrice())); // K列
  743 + setCellValue(sheet, startRow, 10, contractDistributorLineBo.getUnitPrice()); // K列
744 744 } else {
745 745 setCellValue(sheet, startRow, 9, contractDistributorLineBo.getUnitPrice()); // I列
746 746 setCellValue(sheet, startRow, 10, contractDistributorLineBo.getAmountExcludingTax()); // K列
... ...
... ... @@ -193,6 +193,11 @@ public class CustomerCreditHistoryController extends DefaultBaseController {
193 193
194 194 result.setOtherChangeList(differencesWithIndex);
195 195
  196 + LocalDateTime createTime = data.getCreateTime();
  197 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  198 + String newDate = createTime.format(formatter);
  199 + result.setChangeTime(newDate);
  200 +
196 201 return InvokeResultBuilder.success(result);
197 202 }
198 203
... ...
xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/shipments/ReplenishmentOrderController.java renamed from xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/purchase/ReplenishmentOrderController.java
1   -package com.lframework.xingyun.sc.controller.purchase;
  1 +package com.lframework.xingyun.sc.controller.shipments;
2 2
3 3 import com.baomidou.mybatisplus.core.conditions.Wrapper;
4 4 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
... ... @@ -19,7 +19,6 @@ import com.lframework.xingyun.basedata.entity.Workshop;
19 19 import com.lframework.xingyun.basedata.service.customer.CustomerService;
20 20 import com.lframework.xingyun.basedata.service.workshop.WorkshopService;
21 21 import com.lframework.xingyun.basedata.vo.customer.QueryCustomerVo;
22   -import com.lframework.xingyun.sc.bo.contract.QueryContractDistributorStandardBo;
23 22 import com.lframework.xingyun.sc.bo.purchase.GetReplenishmentOrderBo;
24 23 import com.lframework.xingyun.sc.bo.purchase.GetReplenishmentOrderLineBo;
25 24 import com.lframework.xingyun.sc.bo.purchase.QueryReplenishmentOrderBo;
... ... @@ -55,7 +54,7 @@ import java.util.stream.Collectors;
55 54 @Api(tags = "补货单")
56 55 @Validated
57 56 @RestController
58   -@RequestMapping("/purchase/replenishmentOrder")
  57 +@RequestMapping("/shipments/replenishmentOrder")
59 58 public class ReplenishmentOrderController extends DefaultBaseController {
60 59
61 60 @Resource
... ... @@ -80,7 +79,7 @@ public class ReplenishmentOrderController extends DefaultBaseController {
80 79 * 查询列表
81 80 */
82 81 @ApiOperation("查询列表")
83   - @HasPermission({"purchase:replenishmentorder:query"})
  82 + @HasPermission({"shipping-plan-manage:replenishment-order:query"})
84 83 @GetMapping("/query")
85 84 public InvokeResult<PageResult<QueryReplenishmentOrderBo>> query(@Valid QueryReplenishmentOrderVo vo) {
86 85 if (vo != null && StringUtils.isNotBlank(vo.getCustomerName())) {
... ... @@ -160,7 +159,7 @@ public class ReplenishmentOrderController extends DefaultBaseController {
160 159 */
161 160 @ApiOperation("根据ID查询")
162 161 @ApiImplicitParam(value = "id", name = "id", paramType = "query", required = true)
163   - @HasPermission({"purchase:replenishmentorder:query"})
  162 + @HasPermission({"shipping-plan-manage:replenishment-order:query"})
164 163 @GetMapping
165 164 public InvokeResult<GetReplenishmentOrderBo> get(@NotBlank(message = "id不能为空!") String id) {
166 165
... ... @@ -203,7 +202,7 @@ public class ReplenishmentOrderController extends DefaultBaseController {
203 202 * 新增
204 203 */
205 204 @ApiOperation("新增")
206   - @HasPermission({"purchase:replenishmentorder:add"})
  205 + @HasPermission({"shipping-plan-manage:replenishment-order:add"})
207 206 @PostMapping
208 207 public InvokeResult<Void> create(@Valid @RequestBody CreateReplenishmentOrderVo vo) {
209 208
... ... @@ -216,7 +215,7 @@ public class ReplenishmentOrderController extends DefaultBaseController {
216 215 * 修改
217 216 */
218 217 @ApiOperation("修改")
219   - @HasPermission({"purchase:replenishmentorder:modify"})
  218 + @HasPermission({"shipping-plan-manage:replenishment-order:modify"})
220 219 @PutMapping
221 220 public InvokeResult<Void> update(@Valid @RequestBody UpdateReplenishmentOrderVo vo) {
222 221
... ... @@ -231,7 +230,7 @@ public class ReplenishmentOrderController extends DefaultBaseController {
231 230 * 取消
232 231 */
233 232 @ApiOperation("取消")
234   - @HasPermission({"purchase:replenishmentorder:cancel"})
  233 + @HasPermission({"shipping-plan-manage:replenishment-order:cancel"})
235 234 @GetMapping("/cancel")
236 235 public InvokeResult<Void> cancel(@NotBlank(message = "id不能为空!") String id) {
237 236
... ... @@ -246,7 +245,7 @@ public class ReplenishmentOrderController extends DefaultBaseController {
246 245 * 填写补货时间
247 246 */
248 247 @ApiOperation("填写补货时间")
249   - @HasPermission({"purchase:replenishmentorder:fillRestockTime"})
  248 + @HasPermission({"shipping-plan-manage:replenishment-order:fill"})
250 249 @PostMapping("/fillRestockTime")
251 250 public InvokeResult<Void> fillRestockTime(@RequestBody UpdateReplenishmentOrderVo vo) {
252 251
... ...
1 1 package com.lframework.xingyun.sc.controller.shipments.car;
2 2
  3 +import cn.hutool.core.io.resource.ClassPathResource;
3 4 import com.lframework.starter.web.core.annotations.security.HasPermission;
4 5 import com.lframework.starter.web.core.controller.DefaultBaseController;
5 6 import com.lframework.starter.web.core.utils.PageResultUtil;
6 7 import com.lframework.starter.web.core.components.resp.PageResult;
7 8 import com.lframework.starter.web.core.components.resp.InvokeResult;
  9 +import javax.servlet.http.HttpServletResponse;
8 10 import javax.validation.constraints.NotBlank;
9 11 import com.lframework.xingyun.sc.bo.shipments.car.GetCarRequestPlanBo;
10 12 import com.lframework.xingyun.sc.entity.CarRequestPlan;
... ... @@ -21,13 +23,28 @@ import com.lframework.starter.common.exceptions.impl.DefaultClientException;
21 23 import io.swagger.annotations.ApiOperation;
22 24 import com.lframework.starter.common.utils.CollectionUtil;
23 25 import io.swagger.annotations.Api;
  26 +import lombok.extern.slf4j.Slf4j;
  27 +import org.apache.commons.collections4.CollectionUtils;
  28 +import org.apache.poi.ss.usermodel.*;
  29 +import org.apache.poi.ss.util.CellRangeAddress;
  30 +import org.apache.poi.util.IOUtils;
  31 +import org.apache.poi.xssf.usermodel.XSSFWorkbook;
24 32 import org.springframework.web.bind.annotation.DeleteMapping;
25 33 import org.springframework.beans.factory.annotation.Autowired;
26 34 import org.springframework.validation.annotation.Validated;
27 35 import org.springframework.web.bind.annotation.*;
28   -
29 36 import javax.validation.Valid;
  37 +import java.io.FileNotFoundException;
  38 +import java.io.IOException;
  39 +import java.io.InputStream;
  40 +import java.math.BigDecimal;
  41 +import java.math.RoundingMode;
  42 +import java.net.URLEncoder;
  43 +import java.time.LocalDate;
  44 +import java.time.format.DateTimeFormatter;
  45 +import java.util.HashMap;
30 46 import java.util.List;
  47 +import java.util.Map;
31 48 import java.util.stream.Collectors;
32 49
33 50 /**
... ... @@ -35,6 +52,7 @@ import java.util.stream.Collectors;
35 52 *
36 53 */
37 54 @Api(tags = "要车计划表")
  55 +@Slf4j
38 56 @Validated
39 57 @RestController
40 58 @RequestMapping("/carRequestPlan")
... ... @@ -94,7 +112,7 @@ public class CarRequestPlanController extends DefaultBaseController {
94 112 @ApiOperation("新增")
95 113 @HasPermission({"carRequestPlan:carrequestplan:add"})
96 114 @PostMapping
97   - public InvokeResult<Void> create(@Valid CreateCarRequestPlanVo vo) {
  115 + public InvokeResult<Void> create(@Valid @RequestBody CreateCarRequestPlanVo vo) {
98 116
99 117 carRequestPlanService.create(vo);
100 118
... ... @@ -107,7 +125,7 @@ public class CarRequestPlanController extends DefaultBaseController {
107 125 @ApiOperation("修改")
108 126 @HasPermission({"carRequestPlan:carrequestplan:modify"})
109 127 @PutMapping
110   - public InvokeResult<Void> update(@Valid UpdateCarRequestPlanVo vo) {
  128 + public InvokeResult<Void> update(@Valid @RequestBody UpdateCarRequestPlanVo vo) {
111 129
112 130 carRequestPlanService.update(vo);
113 131
... ... @@ -127,4 +145,201 @@ public class CarRequestPlanController extends DefaultBaseController {
127 145
128 146 return InvokeResultBuilder.success();
129 147 }
  148 +
  149 + @ApiOperation("要车计划打印")
  150 + @GetMapping("/printCarRequestPlan")
  151 + public void printCarRequestPlan(@NotBlank(message = "id不能为空") String id, HttpServletResponse response) throws IOException {
  152 + CarRequestPlan data = carRequestPlanService.findById(id);
  153 + // 设置响应头
  154 + setupResponse(response, data.getWorkshopName() + "-" + data.getRequestCarData() + "-要车计划打印.xlsx");
  155 +
  156 + QueryRequestCarTicketVo vo = new QueryRequestCarTicketVo();
  157 + vo.setPlanId(id);
  158 + List<RequestCarTicket> requestCarTicketList = requestCarTicketService.query(vo);
  159 +
  160 +
  161 + try {
  162 + // 加载模板文件
  163 + ClassPathResource templateResource = new ClassPathResource("templates/carRequestPlanTemplate.xlsx");
  164 + try (InputStream inputStream = templateResource.getStream();
  165 + Workbook workbook = new XSSFWorkbook(inputStream)) {
  166 + try {
  167 + Sheet sheet = workbook.getSheetAt(0);
  168 + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  169 + int startRow = 3; // 要车单开始行
  170 + BigDecimal totalQuantity=BigDecimal.ZERO;
  171 + CellStyle borderedStyle = workbook.createCellStyle();
  172 + borderedStyle.setBorderTop(BorderStyle.THIN);
  173 + borderedStyle.setBorderBottom(BorderStyle.THIN);
  174 + borderedStyle.setBorderLeft(BorderStyle.THIN);
  175 + borderedStyle.setBorderRight(BorderStyle.THIN);
  176 + if (CollectionUtils.isNotEmpty(requestCarTicketList)) {
  177 + for (int i = 0; i < requestCarTicketList.size(); i++) {
  178 + RequestCarTicket requestCarTicket = requestCarTicketList.get(i);
  179 + setCellValue(sheet, startRow, 0, i + 1, borderedStyle);
  180 + setCellValue(sheet, startRow, 1, requestCarTicket.getDeptName(), borderedStyle);
  181 + setCellValue(sheet, startRow, 2, requestCarTicket.getDeliveryDate() == null ? "" : requestCarTicket.getDeliveryDate().format(dateFormatter), borderedStyle);
  182 + setCellValue(sheet, startRow, 3, requestCarTicket.getWorkshopName(), borderedStyle);
  183 + setCellValue(sheet, startRow, 4, requestCarTicket.getOrderNo(), borderedStyle);
  184 + setCellValue(sheet, startRow, 5, requestCarTicket.getCustomerShortName(), borderedStyle);
  185 + setCellValue(sheet, startRow, 6, requestCarTicket.getDestination(), borderedStyle);
  186 + setCellValue(sheet, startRow, 7, requestCarTicket.getQuantity(), borderedStyle);
  187 + totalQuantity = totalQuantity.add(requestCarTicket.getQuantity());
  188 + setCellValue(sheet, startRow, 8, requestCarTicket.getConsignee(), borderedStyle);
  189 + setCellValue(sheet, startRow, 9, requestCarTicket.getPhone(), borderedStyle);
  190 + setCellValue(sheet, startRow, 10, requestCarTicket.getReturnPlanArrangement(), borderedStyle);
  191 + setCellValue(sheet, startRow, 11, requestCarTicket.getOther(), borderedStyle);
  192 + setCellValue(sheet, startRow, 12, requestCarTicket.getExternalAuditorName(), borderedStyle);
  193 + setCellValue(sheet, startRow, 13, requestCarTicket.getLoadingTime(), borderedStyle);
  194 + setCellValue(sheet, startRow, 14, requestCarTicket.getSpecialLoadingRequirement(), borderedStyle);
  195 + setCellValue(sheet, startRow, 15, requestCarTicket.getBusinessOfficeAuditorName(), borderedStyle);
  196 + setCellValue(sheet, startRow, 16, requestCarTicket.getOperationsDepartmentAuditorName(), borderedStyle);
  197 + startRow++;
  198 + }
  199 + // === 写合计行(带完整边框,包括合并区域)===
  200 + Row totalRow = sheet.getRow(startRow);
  201 + if (totalRow == null) totalRow = sheet.createRow(startRow);
  202 +
  203 + // 1. 先为合并区域 [0, 6] 的每个单元格设置边框样式(即使内容为空)
  204 + for (int col = 0; col <= 6; col++) {
  205 + Cell cell = totalRow.getCell(col);
  206 + if (cell == null) {
  207 + cell = totalRow.createCell(col);
  208 + }
  209 + cell.setCellStyle(borderedStyle);
  210 + if (col == 0) {
  211 + cell.setCellValue("合计:");
  212 + } else {
  213 + cell.setCellValue(""); // 空内容
  214 + }
  215 + }
  216 +
  217 + // 2. 设置数量列(第7列)
  218 + Cell totalCell = totalRow.getCell(7);
  219 + if (totalCell == null) {
  220 + totalCell = totalRow.createCell(7);
  221 + }
  222 + totalCell.setCellValue(totalQuantity.setScale(4, RoundingMode.HALF_UP).doubleValue());
  223 + totalCell.setCellStyle(borderedStyle);
  224 +
  225 + // 3. 其他列(8~16)也建议补空 + 边框,保持表格整齐(可选但推荐)
  226 + for (int col = 8; col <= 16; col++) {
  227 + Cell cell = totalRow.getCell(col);
  228 + if (cell == null) {
  229 + cell = totalRow.createCell(col);
  230 + }
  231 + cell.setCellStyle(borderedStyle);
  232 + cell.setCellValue("");
  233 + }
  234 +
  235 + // 4. 最后再执行合并(必须在所有单元格创建之后)
  236 + sheet.addMergedRegion(new CellRangeAddress(startRow, startRow, 0, 6));
  237 + }
  238 +
  239 + Map<String, Object> dataMap = new HashMap<>();
  240 + dataMap.put("requestCarData", data.getRequestCarData() == null ? "" : data.getRequestCarData().format(dateFormatter));
  241 +
  242 + processTemplate(workbook, dataMap);
  243 +
  244 + // 写入响应流
  245 + workbook.write(response.getOutputStream());
  246 + response.getOutputStream().flush();
  247 + } finally {
  248 + IOUtils.closeQuietly(workbook);
  249 + }
  250 +
  251 + } catch (FileNotFoundException e) {
  252 + throw new RuntimeException("模板文件不存在: templates/carRequestPlanTemplate.xlsx", e);
  253 + } catch (IOException e) {
  254 + throw new RuntimeException("无法读取模板文件: templates/carRequestPlanTemplate.xlsx", e);
  255 + }
  256 + } catch (Exception e) {
  257 + log.error("要车计划打印: {}", e.getMessage(), e);
  258 + throw e;
  259 + }
  260 + }
  261 +
  262 + /**
  263 + * 设置HTTP响应头
  264 + */
  265 + private void setupResponse(HttpServletResponse response, String fileName) throws IOException {
  266 + String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
  267 +
  268 + response.setContentType("application/vnd.ms-excel");
  269 + response.setCharacterEncoding("UTF-8");
  270 + response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName);
  271 + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
  272 + }
  273 +
  274 + /**
  275 + * 设置单元格值
  276 + */
  277 + private static void setCellValue(Sheet sheet, int rowNum, int colNum, Object value, CellStyle style) {
  278 + Row row = sheet.getRow(rowNum);
  279 + if (row == null) {
  280 + row = sheet.createRow(rowNum);
  281 + }
  282 + Cell cell = row.getCell(colNum);
  283 + if (cell == null) {
  284 + cell = row.createCell(colNum);
  285 + }
  286 + cell.setCellStyle(style); // 应用边框样式
  287 +
  288 + if (value == null) {
  289 + cell.setCellValue("");
  290 + } else if (value instanceof String) {
  291 + cell.setCellValue((String) value);
  292 + } else if (value instanceof Integer) {
  293 + cell.setCellValue((Integer) value);
  294 + } else if (value instanceof Double || value instanceof BigDecimal) {
  295 + cell.setCellValue(((Number) value).doubleValue());
  296 + } else if (value instanceof LocalDate) {
  297 + cell.setCellValue(((LocalDate) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
  298 + } else {
  299 + cell.setCellValue(value.toString());
  300 + }
  301 + }
  302 +
  303 + private void processTemplate(Workbook workbook, Map<String, Object> dataMap) {
  304 + Sheet sheet = workbook.getSheetAt(0);
  305 +
  306 + for (Row row : sheet) {
  307 + for (Cell cell : row) {
  308 + if (cell.getCellTypeEnum() == CellType.STRING) {
  309 + String cellValue = cell.getStringCellValue();
  310 + String newValue = replacePlaceholders(cellValue, dataMap);
  311 + if (!cellValue.equals(newValue)) {
  312 + cell.setCellValue(newValue);
  313 + }
  314 + }
  315 + }
  316 + }
  317 + }
  318 +
  319 + private String replacePlaceholders(String text, Map<String, Object> dataMap) {
  320 + if (text == null || text.isEmpty()) {
  321 + return text;
  322 + }
  323 +
  324 + String result = text;
  325 + for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
  326 + String placeholder = "${" + entry.getKey() + "}";
  327 + String value = entry.getValue() != null ? entry.getValue().toString() : "";
  328 + // 将数据库中的 \n 转换为 Excel 识别的换行符
  329 + value = value.replace("\\n", "\n");
  330 +
  331 + result = result.replace(placeholder, value);
  332 + }
  333 +
  334 + for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
  335 + String placeholder = "#{" + entry.getKey() + "}";
  336 + String value = entry.getValue() != null ? entry.getValue().toString() : "";
  337 + // 将数据库中的 \n 转换为 Excel 识别的换行符
  338 + value = value.replace("\\n", "\n");
  339 +
  340 + result = result.replace(placeholder, value);
  341 + }
  342 +
  343 + return result;
  344 + }
130 345 }
... ...
... ... @@ -526,6 +526,15 @@ public class ContractDistributorStandardServiceImpl extends
526 526 createPurchaseOrderInfoVo.setContractCreateById(contractDistributorStandard.getCreateById());
527 527 createPurchaseOrderInfoVo.setDeptId(contractDistributorStandard.getDeptId());
528 528 createPurchaseOrderInfoVo.setWorkshopId(contractDistributorStandard.getWorkshopId());
  529 + createPurchaseOrderInfoVo.setExecutionStandard(contractDistributorStandard.getExecutionStandard());
  530 + createPurchaseOrderInfoVo.setExecutionStandardRemarks(contractDistributorStandard.getExecutionStandardRemarks());
  531 + createPurchaseOrderInfoVo.setPieceWeightHeader(contractDistributorStandard.getPieceWeightHead());
  532 + createPurchaseOrderInfoVo.setSurface(contractDistributorStandard.getSurface());
  533 + createPurchaseOrderInfoVo.setTolerance(contractDistributorStandard.getTolerance());
  534 + createPurchaseOrderInfoVo.setPerformance(contractDistributorStandard.getPerformance());
  535 + createPurchaseOrderInfoVo.setElement(contractDistributorStandard.getComponent());
  536 + createPurchaseOrderInfoVo.setPackaging(contractDistributorStandard.getPackaging());
  537 + createPurchaseOrderInfoVo.setRemarks(contractDistributorStandard.getRemarks());
529 538 createPurchaseOrderInfoVo.setType("NO_PRODUCTION");
530 539 createPurchaseOrderInfoVo.setExamineStatus("AUDIT");
531 540
... ...
... ... @@ -28,6 +28,7 @@ import org.springframework.stereotype.Service;
28 28
29 29 import java.text.SimpleDateFormat;
30 30 import java.time.LocalDate;
  31 +import java.time.format.DateTimeFormatter;
31 32 import java.util.Date;
32 33 import java.util.List;
33 34
... ... @@ -67,8 +68,8 @@ public class CarRequestPlanServiceImpl extends BaseMpServiceImpl<CarRequestPlanM
67 68 vo1.setWorkshopId(vo.getWorkshopId());
68 69 LocalDate date = vo.getRequestCarData();
69 70 if (date != null) {
70   - SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
71   - String dateString = formatter.format(date);
  71 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  72 + String dateString = date.format(formatter); // LocalDate 自带 format 方法
72 73 vo1.setRequestCarDataStart(dateString);
73 74 vo1.setRequestCarDataEnd(dateString);
74 75 }
... ...
... ... @@ -108,7 +108,7 @@
108 108 AND tb.status = #{vo.status}
109 109 </if>
110 110 <if test="vo.planId != null and vo.planId != ''">
111   - AND tb.plan_id = #{planId}
  111 + AND tb.plan_id = #{vo.planId}
112 112 </if>
113 113 </where>
114 114 ORDER BY tb.update_time DESC
... ...