Commit 4a013a64d61c196eda59a8bc0052891c8e3d8ba2

Authored by 房远帅
1 parent f252180e

采购计划:导出

... ... @@ -226,6 +226,12 @@ public class GetProcurementPlanBo extends BaseBo<ProcurementPlan> {
226 226 private String priceId;
227 227
228 228 /**
  229 + * 价格表CODE
  230 + */
  231 + @ApiModelProperty("价格表CODE")
  232 + private String priceCode;
  233 +
  234 + /**
229 235 * 协调事由
230 236 */
231 237 @ApiModelProperty("协调事由")
... ... @@ -352,6 +358,12 @@ public class GetProcurementPlanBo extends BaseBo<ProcurementPlan> {
352 358 private String workshopId;
353 359
354 360 /**
  361 + * 分厂
  362 + */
  363 + @ApiModelProperty("分厂")
  364 + private String workshopName;
  365 +
  366 + /**
355 367 * 关联业务员报价单ID
356 368 */
357 369 @ApiModelProperty("关联业务员报价单ID")
... ... @@ -472,6 +484,12 @@ public class GetProcurementPlanBo extends BaseBo<ProcurementPlan> {
472 484 private String productId;
473 485
474 486 /**
  487 + * 品种名称
  488 + */
  489 + @ApiModelProperty("品种名称")
  490 + private String productName;
  491 +
  492 + /**
475 493 * 料型
476 494 */
477 495 @ApiModelProperty("料型")
... ... @@ -532,6 +550,12 @@ public class GetProcurementPlanBo extends BaseBo<ProcurementPlan> {
532 550 private String workshopId;
533 551
534 552 /**
  553 + * 分厂
  554 + */
  555 + @ApiModelProperty("分厂")
  556 + private String workshopName;
  557 +
  558 + /**
535 559 * 是否展示审核按钮
536 560 */
537 561 @ApiModelProperty("是否展示审核按钮")
... ...
1 1 package com.lframework.xingyun.sc.procurement.controller.plan;
2 2
  3 +import cn.hutool.core.io.resource.ClassPathResource;
3 4 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  5 +import com.lframework.starter.common.exceptions.impl.DefaultClientException;
4 6 import com.lframework.starter.common.utils.CollectionUtil;
5 7 import com.lframework.starter.web.core.annotations.security.HasPermission;
6 8 import com.lframework.starter.web.core.controller.DefaultBaseController;
... ... @@ -8,7 +10,11 @@ import com.lframework.starter.web.core.components.resp.InvokeResult;
8 10 import com.lframework.starter.web.core.components.resp.InvokeResultBuilder;
9 11 import com.lframework.starter.web.core.components.resp.PageResult;
10 12 import com.lframework.starter.web.core.utils.PageResultUtil;
  13 +import com.lframework.starter.web.inner.entity.SysDataDicItem;
  14 +import com.lframework.starter.web.inner.service.system.SysDataDicItemService;
  15 +import com.lframework.xingyun.sc.bo.procurement.GetProcurementBuyoutApplyBo;
11 16 import com.lframework.xingyun.sc.bo.procurement.GetProcurementPlanBo;
  17 +import com.lframework.xingyun.sc.bo.procurement.ProcurementBuyoutApplyLineBo;
12 18 import com.lframework.xingyun.sc.procurement.entity.ProcurementBuyoutApply;
13 19 import com.lframework.xingyun.sc.procurement.entity.ProcurementPlan;
14 20 import com.lframework.xingyun.sc.procurement.service.buyout.ProcurementBuyoutApplyService;
... ... @@ -16,16 +22,16 @@ import com.lframework.xingyun.sc.procurement.service.plan.ProcurementPlanService
16 22 import com.lframework.xingyun.sc.procurement.vo.plan.CreateProcurementPlanVo;
17 23 import com.lframework.xingyun.sc.procurement.vo.plan.QueryProcurementPlanVo;
18 24 import com.lframework.xingyun.sc.procurement.vo.plan.UpdateProcurementPlanVo;
  25 +import com.lframework.xingyun.sc.utils.ExcelUtil;
19 26 import io.swagger.annotations.Api;
20 27 import io.swagger.annotations.ApiImplicitParam;
21 28 import io.swagger.annotations.ApiOperation;
22   -import java.util.HashMap;
23   -import java.util.List;
24   -import java.util.Map;
25   -import java.util.Set;
26   -import java.util.stream.Collectors;
27   -import javax.validation.Valid;
28   -import javax.validation.constraints.NotBlank;
  29 +import lombok.extern.slf4j.Slf4j;
  30 +import org.apache.commons.collections4.CollectionUtils;
  31 +import org.apache.commons.lang3.StringUtils;
  32 +import org.apache.poi.ss.usermodel.*;
  33 +import org.apache.poi.util.IOUtils;
  34 +import org.apache.poi.xssf.usermodel.XSSFWorkbook;
29 35 import org.springframework.beans.factory.annotation.Autowired;
30 36 import org.springframework.validation.annotation.Validated;
31 37 import org.springframework.web.bind.annotation.DeleteMapping;
... ... @@ -35,8 +41,22 @@ import org.springframework.web.bind.annotation.PutMapping;
35 41 import org.springframework.web.bind.annotation.RequestBody;
36 42 import org.springframework.web.bind.annotation.RequestMapping;
37 43 import org.springframework.web.bind.annotation.RestController;
  44 +import javax.servlet.http.HttpServletResponse;
  45 +import javax.validation.Valid;
  46 +import javax.validation.constraints.NotBlank;
  47 +import java.io.FileNotFoundException;
  48 +import java.io.IOException;
  49 +import java.io.InputStream;
  50 +import java.math.BigDecimal;
  51 +import java.net.URLEncoder;
  52 +import java.time.LocalDate;
  53 +import java.time.LocalDateTime;
  54 +import java.time.format.DateTimeFormatter;
  55 +import java.util.*;
  56 +import java.util.stream.Collectors;
38 57
39 58 @Api(tags = "采购计划管理")
  59 +@Slf4j
40 60 @Validated
41 61 @RestController
42 62 @RequestMapping("/procurement/plan")
... ... @@ -46,6 +66,9 @@ public class ProcurementPlanController extends DefaultBaseController {
46 66 private ProcurementPlanService procurementPlanService;
47 67 @Autowired
48 68 private ProcurementBuyoutApplyService procurementBuyoutApplyService;
  69 + @Autowired
  70 + private SysDataDicItemService sysDataDicItemService;
  71 +
49 72
50 73 /**
51 74 * 查询列表
... ... @@ -240,4 +263,289 @@ public class ProcurementPlanController extends DefaultBaseController {
240 263 bo.setShowAbolishBuyoutApply(buyoutFlag && count > 0L);
241 264 }
242 265 }
  266 +
  267 + /**
  268 + * 导出采购计划
  269 + */
  270 + @ApiOperation("导出采购计划")
  271 + @ApiImplicitParam(value = "ID", name = "id", paramType = "query", required = true)
  272 + @HasPermission({"plan-manage:domestic-plan:print"})
  273 + @GetMapping("/export")
  274 + public void export(@NotBlank(message = "ID不能为空!") String id,
  275 + HttpServletResponse response) throws IOException {
  276 +
  277 + GetProcurementPlanBo plan = procurementPlanService.getDetail(id);
  278 + if (plan == null) {
  279 + throw new DefaultClientException("采购计划不存在!");
  280 + }
  281 + setupResponse(response, (plan.getCode() == null ? "" : plan.getCode()) + "-采购计划.xlsx");
  282 +
  283 + GetProcurementBuyoutApplyBo buyoutApply = procurementBuyoutApplyService.findByPlanId(id);
  284 + ClassPathResource templateResource = new ClassPathResource("templates/planTemplate.xlsx");
  285 + if (buyoutApply != null) {
  286 + templateResource = new ClassPathResource("templates/planAndBuyoutTemplate.xlsx");
  287 + }
  288 + try {
  289 + try (InputStream inputStream = templateResource.getStream();
  290 + Workbook workbook = new XSSFWorkbook(inputStream)) {
  291 + try {
  292 + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  293 +
  294 + // === Sheet1:采购计划主表 + 子表 ===
  295 + Sheet sheet1 = workbook.getSheet("计划单");
  296 +
  297 + List<GetProcurementPlanBo.ProcurementPlanLineBo> planLineList = plan.getProcurementPlanLineList();
  298 + int planStartRow = 4; // 采购计划子表开始行,可根据模板调整
  299 + if (CollectionUtils.isNotEmpty(planLineList)) {
  300 + for (int i = 0; i < planLineList.size(); i++) {
  301 + GetProcurementPlanBo.ProcurementPlanLineBo line = planLineList.get(i);
  302 + ExcelUtil.setCellValue(sheet1, planStartRow, 0, line.getProductName());
  303 + ExcelUtil.setCellValue(sheet1, planStartRow, 1, line.getMaterialType());
  304 + ExcelUtil.setCellValue(sheet1, planStartRow, 2, line.getQuantity());
  305 + ExcelUtil.setCellValue(sheet1, planStartRow, 3, line.getActualPurchasePrice());
  306 + ExcelUtil.setCellValue(sheet1, planStartRow, 4, line.getIncludingShippingPrice());
  307 + ExcelUtil.setCellValue(sheet1, planStartRow, 5, line.getPriceListPrices());
  308 + ExcelUtil.setCellValue(sheet1, planStartRow, 6, line.getCoordinationRange());
  309 + ExcelUtil.setCellValue(sheet1, planStartRow, 7, line.getEstimatedLoss());
  310 + ExcelUtil.setCellValue(sheet1, planStartRow, 8, line.getWorkshopName());
  311 + planStartRow++;
  312 + }
  313 + }
  314 +
  315 + Map<String, Object> planDataMap = new HashMap<>();
  316 + planDataMap.put("code", nvl(plan.getCode()) + nvl(plan.getPlanType()));
  317 + planDataMap.put("companyShortName", nvl(plan.getCompanyShortName()));
  318 + planDataMap.put("workshopName", nvl(plan.getWorkshopName()));
  319 + planDataMap.put("purchaseDepartmentName", nvl(plan.getPurchaseDepartmentName()));
  320 + planDataMap.put("regionName", nvl(plan.getRegionName()));
  321 + planDataMap.put("date", plan.getDate() == null ? "" : plan.getDate().format(dateFormatter));
  322 + planDataMap.put("supplierName", nvl(plan.getSupplierName()));
  323 + planDataMap.put("commodityBuyout", plan.getCommodityBuyout() == null ? "□" : (plan.getCommodityBuyout() ? "■" : "□"));
  324 + planDataMap.put("qualityBuyout", plan.getQualityBuyout() == null ? "□" : (plan.getQualityBuyout() ? "■" : "□"));
  325 + planDataMap.put("quantityBuyout", plan.getQuantityBuyout() == null ? "□" : (plan.getQuantityBuyout() ? "■" : "□"));
  326 + planDataMap.put("doorDelivery", plan.getDoorDelivery() == null ? "□" : (plan.getDoorDelivery() ? "■" : "□"));
  327 + planDataMap.put("longTermOperation", plan.getLongTermOperation() == null ? "□" : (plan.getLongTermOperation() ? "■" : "□"));
  328 + planDataMap.put("terminalCustomer", plan.getTerminalCustomer() == null ? "□" : (plan.getTerminalCustomer() ? "■" : "□"));
  329 + planDataMap.put("shippingCostB", plan.getShippingCost() == null ? "□" : "■");
  330 + planDataMap.put("shippingCost", formatDecimal(plan.getShippingCost()));
  331 + planDataMap.put("loadingFeeB", plan.getLoadingFee() == null ? "□" : "■");
  332 + planDataMap.put("loadingFee", formatDecimal(plan.getLoadingFee()));
  333 + planDataMap.put("otherExpenseSettlement", plan.getOtherExpenseSettlement() == null ? "□" : (plan.getOtherExpenseSettlement() ? "■" : "□"));
  334 + planDataMap.put("remark", nvl(plan.getRemark()));
  335 + planDataMap.put("totalQuantity", formatDecimal(plan.getTotalQuantity()));
  336 + planDataMap.put("coordinationReason", nvl(plan.getCoordinationReason()));
  337 + planDataMap.put("invoiceTypeStatus", nvl(plan.getInvoiceTypeStatus()));
  338 + planDataMap.put("invoiceProductName", nvl(plan.getInvoiceProductName()));
  339 + //交货日期
  340 + if (plan.getDeliveryDate() != null) {
  341 + // M 表示不补零的月份,d 表示不补零的日期
  342 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d'提'");
  343 + String formattedDate = plan.getDeliveryDate().format(formatter);
  344 + planDataMap.put("deliveryDate", formattedDate);
  345 + } else {
  346 + planDataMap.put("deliveryDate", ""); // 或者你需要的默认值
  347 + }
  348 + List<SysDataDicItem> deliveryModeList = sysDataDicItemService.findByDicCode("DELIVERY_METHOD");
  349 + Map<String, String> deliveryModeMap = deliveryModeList.stream()
  350 + .collect(Collectors.toMap(SysDataDicItem::getCode, SysDataDicItem::getName, (v1, v2) -> v1));
  351 + planDataMap.put("deliveryMode", deliveryModeMap.get(nvl(plan.getDeliveryMode())));
  352 + planDataMap.put("settlementRatio", formatDecimal(plan.getSettlementRatio()));
  353 + planDataMap.put("priceCode", nvl(plan.getPriceCode()));
  354 + //启用料质状况
  355 + if (Boolean.TRUE.equals(plan.getMaterialConditionEnabled())) {
  356 + planDataMap.put("copperRiceCondition",
  357 + buildMaterialConditionStr("COPPER_RICE", plan.getMaterialConditionCopperRice(), -1));
  358 + // 光亮铜:前4后换行(多股光亮丝/表面光亮的板材/表面光亮的棒材/内外表面光亮的管材;第2行光亮丝/光亮丝铜米)
  359 + planDataMap.put("brightCopperCondition",
  360 + buildMaterialConditionStr("BRIGHT_COPPER", plan.getMaterialConditionBrightCopper(), 4));
  361 + // 一特:前5后换行(火烧丝/火烧扁线/表面氧化的板材/表面氧化的棒材/表面氧化的管材;第2行镀白丝…)
  362 + planDataMap.put("firstClassCondition",
  363 + buildMaterialConditionStr("FIRST_CLASS", plan.getMaterialConditionFirstClass(), 5) + " 注:镀白板不扣杂");
  364 + planDataMap.put("secondClassCondition",
  365 + buildMaterialConditionStr("SECOND_CLASS", plan.getMaterialConditionSecondClass(), -1));
  366 + planDataMap.put("tinCoatedCondition",
  367 + buildMaterialConditionStr("TIN_COATED", plan.getMaterialConditionTinCoated(), -1));
  368 + // 角料:前7后换行(条形料/冲片料/字牌/天线管及管料/黄铜网/铜米/油铜米;第2行火烧拉链米/纽扣/锁球)
  369 + planDataMap.put("scrapCondition",
  370 + buildMaterialConditionStr("SCRAP", plan.getMaterialConditionScrap(), 7));
  371 + planDataMap.put("whiteYellowCondition",
  372 + buildMaterialConditionStr("WHITE_YELLOW", plan.getMaterialConditionWhiteYellow(), -1));
  373 + planDataMap.put("phosphorCopperCondition",
  374 + buildMaterialConditionStr("PHOSPHOR_COPPER", plan.getMaterialConditionPhosphorCopper(), -1));
  375 + } else {
  376 + planDataMap.put("copperRiceCondition", "□清一色通讯电话线加工的米粒状,表面光亮");
  377 + planDataMap.put("brightCopperCondition", "□多股光亮丝 □表面光亮的板材 □表面光亮的棒材 □内外表面光亮的管材\n" +
  378 + "□光亮丝 □光亮丝铜米");
  379 + planDataMap.put("firstClassCondition", "□火烧丝 □火烧扁线 □表面氧化的板材 □表面氧化的棒材 □表面氧化的管材\n" +
  380 + "□镀白丝、各种镀白型材、镀白冲料 注:镀白板不扣杂");
  381 + planDataMap.put("secondClassCondition", "□火烧丝 □火烧扁线 □镀白丝、各种镀白型材、镀白冲料");
  382 + planDataMap.put("tinCoatedCondition", "□镀锡丝 □镀锡针 □镀锡冲料 □镀锡条形料 □火烧镀锡针 □镀锡板 □镀锡棒");
  383 + planDataMap.put("scrapCondition", "□条形料 □冲片料 □字牌 □天线管及管料 □黄铜网 □铜米 □油铜米\n" +
  384 + "□火烧拉链米 □纽扣 □锁球");
  385 + planDataMap.put("whiteYellowCondition", "□条形料 □冲片料 □天线管及管料 □纽扣 □锁球");
  386 + planDataMap.put("phosphorCopperCondition", "□条形料 □冲片料 □磷铜型材 □磷铜网");
  387 + }
  388 + //制单人
  389 + planDataMap.put("createBy", nvl(plan.getCreateBy()));
  390 +
  391 + processTemplateSheet(sheet1, planDataMap);
  392 +
  393 + // === Sheet2:买断操作申请单(仅当存在时填充)===
  394 + if (buyoutApply != null && workbook.getNumberOfSheets() > 1) {
  395 + Sheet sheet2 = workbook.getSheet("买断申请单");
  396 +
  397 + List<ProcurementBuyoutApplyLineBo> buyoutLineList = buyoutApply.getLineList();
  398 + int buyoutStartRow = 3; // 买断单子表开始行,可根据模板调整
  399 + if (CollectionUtils.isNotEmpty(buyoutLineList)) {
  400 + for (int i = 0; i < buyoutLineList.size(); i++) {
  401 + ProcurementBuyoutApplyLineBo line = buyoutLineList.get(i);
  402 + ExcelUtil.setCellValue(sheet2, buyoutStartRow, 2, line.getProductName());
  403 + ExcelUtil.setCellValue(sheet2, buyoutStartRow, 4, line.getQuantity());
  404 + ExcelUtil.setCellValue(sheet2, buyoutStartRow, 6, line.getBuyoutPrice());
  405 + buyoutStartRow++;
  406 + }
  407 + }
  408 +
  409 + int buyoutStartRow1 = 15; // 买断单子表开始行,可根据模板调整
  410 + if (CollectionUtils.isNotEmpty(buyoutLineList)) {
  411 + for (int i = 0; i < buyoutLineList.size(); i++) {
  412 + ProcurementBuyoutApplyLineBo line = buyoutLineList.get(i);
  413 + ExcelUtil.setCellValue(sheet2, buyoutStartRow1, 2, line.getEstimatedLoss());
  414 + ExcelUtil.setCellValue(sheet2, buyoutStartRow1, 5, line.getPureCopperPrice());
  415 + buyoutStartRow1++;
  416 + }
  417 + }
  418 +
  419 + Map<String, Object> buyoutDataMap = new HashMap<>();
  420 + buyoutDataMap.put("code", nvl(buyoutApply.getCode()));
  421 + buyoutDataMap.put("purchaseDepartmentName", nvl(buyoutApply.getPurchaseDepartmentName()));
  422 + buyoutDataMap.put("regionName", nvl(buyoutApply.getRegionName()));
  423 + buyoutDataMap.put("date", buyoutApply.getDate() == null ? "" : buyoutApply.getDate().format(dateFormatter));
  424 + buyoutDataMap.put("supplierName", nvl(buyoutApply.getSupplierName()));
  425 + buyoutDataMap.put("paintLoss", formatDecimal(buyoutApply.getPaintLoss()));
  426 + buyoutDataMap.put("createBy", nvl(buyoutApply.getCreateBy()));
  427 +
  428 + processTemplateSheet(sheet2, buyoutDataMap);
  429 + }
  430 +
  431 + workbook.write(response.getOutputStream());
  432 + response.getOutputStream().flush();
  433 + } finally {
  434 + IOUtils.closeQuietly(workbook);
  435 + }
  436 +
  437 + } catch (FileNotFoundException e) {
  438 + throw new RuntimeException("模板文件不存在: templates/planAndBuyoutTemplate.xlsx", e);
  439 + } catch (IOException e) {
  440 + throw new RuntimeException("无法读取模板文件: templates/planAndBuyoutTemplate.xlsx", e);
  441 + }
  442 + } catch (Exception e) {
  443 + log.error("导出采购计划失败, id={}, {}", id, e.getMessage(), e);
  444 + throw e;
  445 + }
  446 + }
  447 +
  448 + /**
  449 + * 设置HTTP响应头
  450 + */
  451 + private void setupResponse(HttpServletResponse response, String fileName) throws IOException {
  452 + String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
  453 +
  454 + response.setContentType("application/vnd.ms-excel");
  455 + response.setCharacterEncoding("UTF-8");
  456 + response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName);
  457 + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
  458 + }
  459 +
  460 + /**
  461 + * 按单 Sheet 替换模板占位符(${...} / #{...})
  462 + */
  463 + private void processTemplateSheet(Sheet sheet, Map<String, Object> dataMap) {
  464 + for (Row row : sheet) {
  465 + for (Cell cell : row) {
  466 + if (cell.getCellTypeEnum() == CellType.STRING) {
  467 + String cellValue = cell.getStringCellValue();
  468 + String newValue = replacePlaceholders(cellValue, dataMap);
  469 + if (!cellValue.equals(newValue)) {
  470 + cell.setCellValue(newValue);
  471 + }
  472 + }
  473 + }
  474 + }
  475 + }
  476 +
  477 + private String replacePlaceholders(String text, Map<String, Object> dataMap) {
  478 + if (text == null || text.isEmpty()) {
  479 + return text;
  480 + }
  481 +
  482 + String result = text;
  483 + for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
  484 + String placeholder = "${" + entry.getKey() + "}";
  485 + String value = entry.getValue() != null ? entry.getValue().toString() : "";
  486 + value = value.replace("\\n", "\n");
  487 + result = result.replace(placeholder, value);
  488 + }
  489 +
  490 + for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
  491 + String placeholder = "#{" + entry.getKey() + "}";
  492 + String value = entry.getValue() != null ? entry.getValue().toString() : "";
  493 + value = value.replace("\\n", "\n");
  494 + result = result.replace(placeholder, value);
  495 + }
  496 +
  497 + return result;
  498 + }
  499 +
  500 + private String nvl(Object o) {
  501 + return o == null ? "" : o.toString();
  502 + }
  503 +
  504 + private String formatDecimal(BigDecimal bd) {
  505 + if (bd == null) {
  506 + return "";
  507 + }
  508 + return bd.stripTrailingZeros().toPlainString();
  509 + }
  510 +
  511 + /**
  512 + * 料质状况复选框拼接
  513 + *
  514 + * @param dicCode 字典编码
  515 + * @param selectedCodeStr 已选中的字典项code,逗号分隔
  516 + * @param itemsPerLine 每行多少项后换行;&lt;=0 表示不换行
  517 + * @return 形如 ☑选项1 □选项2\n☑选项3
  518 + */
  519 + private String buildMaterialConditionStr(String dicCode, String selectedCodeStr, int itemsPerLine) {
  520 + List<SysDataDicItem> dicItemList = sysDataDicItemService.findByDicCode(dicCode);
  521 + if (CollectionUtils.isEmpty(dicItemList)) {
  522 + return "";
  523 + }
  524 +
  525 + Set<String> selectedCodes = new HashSet<>();
  526 + if (StringUtils.isNotBlank(selectedCodeStr)) {
  527 + selectedCodes = Arrays.stream(selectedCodeStr.split(","))
  528 + .map(String::trim)
  529 + .filter(StringUtils::isNotBlank)
  530 + .collect(Collectors.toSet());
  531 + }
  532 +
  533 + Set<String> finalSelectedCodes = selectedCodes;
  534 + List<String> lines = new ArrayList<>();
  535 + List<String> currentLine = new ArrayList<>();
  536 + int idx = 0;
  537 + for (SysDataDicItem item : dicItemList) {
  538 + String prefix = finalSelectedCodes.contains(item.getCode()) ? "☑" : "□";
  539 + currentLine.add(prefix + item.getName());
  540 + idx++;
  541 + if (itemsPerLine > 0 && idx % itemsPerLine == 0) {
  542 + lines.add(String.join(" ", currentLine));
  543 + currentLine.clear();
  544 + }
  545 + }
  546 + if (!currentLine.isEmpty()) {
  547 + lines.add(String.join(" ", currentLine));
  548 + }
  549 + return String.join("\n", lines);
  550 + }
243 551 }
... ...
... ... @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
5 5 import com.baomidou.mybatisplus.annotation.TableName;
6 6 import com.lframework.starter.web.core.dto.BaseDto;
7 7 import com.lframework.starter.web.core.entity.BaseEntity;
  8 +import io.swagger.annotations.ApiModelProperty;
8 9 import lombok.Data;
9 10 import java.math.BigDecimal;
10 11 import java.time.LocalDate;
... ... @@ -193,6 +194,12 @@ public class ProcurementPlan extends BaseEntity implements BaseDto {
193 194 private String priceId;
194 195
195 196 /**
  197 + * 价格表Code
  198 + */
  199 + @TableField(exist = false)
  200 + private String priceCode;
  201 +
  202 + /**
196 203 * 协调事由
197 204 */
198 205 private String coordinationReason;
... ... @@ -298,6 +305,12 @@ public class ProcurementPlan extends BaseEntity implements BaseDto {
298 305 private String workshopId;
299 306
300 307 /**
  308 + * 分厂
  309 + */
  310 + @TableField(exist = false)
  311 + private String workshopName;
  312 +
  313 + /**
301 314 * 关联业务员报价单ID
302 315 */
303 316 private String salesmanQuotationId;
... ...
... ... @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
5 5 import com.baomidou.mybatisplus.annotation.TableName;
6 6 import com.lframework.starter.web.core.dto.BaseDto;
7 7 import com.lframework.starter.web.core.entity.BaseEntity;
  8 +import io.swagger.annotations.ApiModelProperty;
8 9 import lombok.Data;
9 10
10 11 import java.math.BigDecimal;
... ... @@ -32,6 +33,12 @@ public class ProcurementPlanLine extends BaseEntity implements BaseDto {
32 33 private String productId;
33 34
34 35 /**
  36 + * 品种名称
  37 + */
  38 + @TableField(exist = false)
  39 + private String productName;
  40 +
  41 + /**
35 42 * 料型
36 43 */
37 44 private String materialType;
... ... @@ -82,6 +89,12 @@ public class ProcurementPlanLine extends BaseEntity implements BaseDto {
82 89 private String workshopId;
83 90
84 91 /**
  92 + * 分厂
  93 + */
  94 + @TableField(exist = false)
  95 + private String workshopName;
  96 +
  97 + /**
85 98 * 前端行标识
86 99 */
87 100 private String itemId;
... ...
... ... @@ -230,12 +230,12 @@ public class ProcurementBuyoutApplyServiceImpl extends
230 230 Wrapper<ProcurementBuyoutApply> queryWrapper = Wrappers.lambdaQuery(ProcurementBuyoutApply.class)
231 231 .eq(ProcurementBuyoutApply::getProcurementPlanId, planId);
232 232 ProcurementBuyoutApply apply = this.getOne(queryWrapper);
233   - if (apply == null) {
234   - throw new DefaultClientException("买断操作申请单不存在!");
235   - }
  233 + if (apply != null) {
  234 + List<ProcurementBuyoutApplyLine> lineList = buyoutApplyLineService.getByApplyId(apply.getId());
236 235
237   - List<ProcurementBuyoutApplyLine> lineList = buyoutApplyLineService.getByApplyId(apply.getId());
238   -
239   - return new GetProcurementBuyoutApplyBo(apply, lineList);
  236 + return new GetProcurementBuyoutApplyBo(apply, lineList);
  237 + } else {
  238 + return null;
  239 + }
240 240 }
241 241 }
... ...
... ... @@ -59,10 +59,6 @@ public class ProcurementPlanChangeServiceImpl extends
59 59 "COMPLETED", "ABORTED"
60 60 );
61 61
62   - private static final List<String> CHANGE_DUPLICATE_EXCLUDES = Arrays.asList(
63   - "已作废", "已驳回", "草稿"
64   - );
65   -
66 62 @Override
67 63 @Transactional(rollbackFor = Exception.class)
68 64 @OpLog(type = OtherOpLogType.class, name = "创建采购计划变更单,原计划ID:{},变更单ID:{}", params = {"#vo.procurementPlanId", "#result"})
... ... @@ -83,8 +79,8 @@ public class ProcurementPlanChangeServiceImpl extends
83 79 throw new DefaultClientException("只能选择主计划进行变更!");
84 80 }
85 81
86   - if (StringUtil.isBlank(plan.getApprovalStatus())
87   - || !PROCESS_STATUSES.contains(plan.getApprovalStatus())) {
  82 + if (StringUtil.isBlank(plan.getProcessStatus())
  83 + || !PROCESS_STATUSES.contains(plan.getProcessStatus())) {
88 84 throw new DefaultClientException("原采购计划状态不允许变更,请确认计划已中止/完成");
89 85 }
90 86 String currentUserId = SecurityUtil.getCurrentUser().getId();
... ...
... ... @@ -36,7 +36,7 @@ public class CreateProcurementPlanChangeVo implements BaseVo, Serializable {
36 36 * 变更单编号
37 37 */
38 38 @ApiModelProperty("变更单编号")
39   - private String changeCode;
  39 + private String code;
40 40
41 41 /**
42 42 * 公司简称ID
... ...
... ... @@ -42,7 +42,7 @@ public class UpdateProcurementPlanChangeVo implements Serializable {
42 42 * 变更单编号
43 43 */
44 44 @ApiModelProperty("变更单编号")
45   - private String changeCode;
  45 + private String code;
46 46
47 47 /**
48 48 * 公司简称ID
... ...
... ... @@ -6,6 +6,7 @@
6 6 <id column="id" property="id"/>
7 7 <result column="procurement_plan_id" property="procurementPlanId"/>
8 8 <result column="product_id" property="productId"/>
  9 + <result column="product_name" property="productName"/>
9 10 <result column="material_type" property="materialType"/>
10 11 <result column="quantity" property="quantity"/>
11 12 <result column="actual_purchase_price" property="actualPurchasePrice"/>
... ... @@ -16,6 +17,7 @@
16 17 <result column="application_attrition" property="applicationAttrition"/>
17 18 <result column="paint_damage_ratio" property="paintDamageRatio"/>
18 19 <result column="workshop_id" property="workshopId"/>
  20 + <result column="workshop_name" property="workshopName"/>
19 21 <result column="item_id" property="itemId"/>
20 22 <result column="create_by_id" property="createById"/>
21 23 <result column="create_by" property="createBy"/>
... ... @@ -30,6 +32,7 @@
30 32 ppl.id,
31 33 ppl.procurement_plan_id,
32 34 ppl.product_id,
  35 + br.product_name,
33 36 ppl.material_type,
34 37 ppl.quantity,
35 38 ppl.actual_purchase_price,
... ... @@ -40,6 +43,7 @@
40 43 ppl.application_attrition,
41 44 ppl.paint_damage_ratio,
42 45 ppl.workshop_id,
  46 + ws.name AS workshop_name,
43 47 ppl.item_id,
44 48 ppl.create_by_id,
45 49 ppl.create_by,
... ... @@ -48,6 +52,8 @@
48 52 ppl.create_time,
49 53 ppl.update_time
50 54 FROM procurement_plan_line AS ppl
  55 + LEFT JOIN base_data_breed_relationship br ON br.id = ppl.product_id
  56 + LEFT JOIN base_data_workshop as ws on ws.id = ppl.workshop_id
51 57 </sql>
52 58
53 59 <select id="getByProcurementPlanId" resultMap="ProcurementPlanLine">
... ...
... ... @@ -37,6 +37,7 @@
37 37 <result column="settlement_method" property="settlementMethod"/>
38 38 <result column="settlement_ratio" property="settlementRatio"/>
39 39 <result column="price_id" property="priceId"/>
  40 + <result column="price_code" property="priceCode"/>
40 41 <result column="coordination_reason" property="coordinationReason"/>
41 42 <result column="invoice_type_status" property="invoiceTypeStatus"/>
42 43 <result column="total_quantity" property="totalQuantity"/>
... ... @@ -58,6 +59,7 @@
58 59 <result column="change_status" property="changeStatus"/>
59 60 <result column="replenishment_status" property="replenishmentStatus"/>
60 61 <result column="workshop_id" property="workshopId"/>
  62 + <result column="workshop_name" property="workshopName"/>
61 63 <result column="salesman_quotation_id" property="salesmanQuotationId"/>
62 64 <result column="attachment_file_ids" property="attachmentFileIds"/>
63 65 <result column="attachment_file_names" property="attachmentFileNames"/>
... ... @@ -105,6 +107,7 @@
105 107 pp.settlement_method,
106 108 pp.settlement_ratio,
107 109 pp.price_id,
  110 + dp.code AS price_code,
108 111 pp.coordination_reason,
109 112 pp.invoice_type_status,
110 113 pp.total_quantity,
... ... @@ -126,6 +129,7 @@
126 129 pp.change_status,
127 130 pp.replenishment_status,
128 131 pp.workshop_id,
  132 + ws.name AS workshop_name,
129 133 pp.salesman_quotation_id,
130 134 pp.attachment_file_ids,
131 135 pp.attachment_file_names,
... ... @@ -140,6 +144,8 @@
140 144 LEFT JOIN procurement_domestic_customer_credit pdc ON pdc.id = pp.supplier_id
141 145 LEFT JOIN sys_dept sd ON sd.id = pp.purchase_department
142 146 LEFT JOIN sys_dept sd1 ON sd1.id = pp.region
  147 + LEFT JOIN base_data_workshop as ws on ws.id = pp.workshop_id
  148 + LEFT JOIN base_data_price as dp on dp.id = pp.price_id
143 149 </sql>
144 150
145 151 <select id="query" resultMap="ProcurementPlan">
... ...