11 changed files with 932 additions and 20 deletions
-
7src/main/java/com/xujie/modules/supplier/service/impl/SupplierPartMoqPriceServiceImpl.java
-
73src/main/java/com/xujie/modules/sys/controller/SysInitialImportController.java
-
38src/main/java/com/xujie/modules/sys/dao/SysInitialImportMapper.java
-
17src/main/java/com/xujie/modules/sys/service/SysInitialImportService.java
-
630src/main/java/com/xujie/modules/sys/service/impl/SysInitialImportServiceImpl.java
-
19src/main/java/com/xujie/modules/sys/vo/SupplierPriceInitialImportPreviewResultVo.java
-
35src/main/java/com/xujie/modules/sys/vo/SupplierPriceInitialImportRowVo.java
-
16src/main/java/com/xujie/modules/sys/vo/SupplierPriceInitialImportSaveVo.java
-
12src/main/resources/mapper/supplier/SupplierPartMoqPriceMapper.xml
-
85src/main/resources/mapper/sys/SysInitialImportMapper.xml
-
18src/main/resources/mapper/sys/SysMenuDao.xml
@ -0,0 +1,73 @@ |
|||||
|
package com.xujie.modules.sys.controller; |
||||
|
|
||||
|
import com.xujie.common.utils.R; |
||||
|
import com.xujie.modules.sys.service.SysInitialImportService; |
||||
|
import com.xujie.modules.sys.vo.SupplierPriceInitialImportPreviewResultVo; |
||||
|
import com.xujie.modules.sys.vo.SupplierPriceInitialImportSaveVo; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.core.io.ByteArrayResource; |
||||
|
import org.springframework.core.io.Resource; |
||||
|
import org.springframework.http.HttpHeaders; |
||||
|
import org.springframework.http.MediaType; |
||||
|
import org.springframework.http.ResponseEntity; |
||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||
|
import org.springframework.web.bind.annotation.PostMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestBody; |
||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||
|
import org.springframework.web.bind.annotation.RestController; |
||||
|
import org.springframework.web.multipart.MultipartFile; |
||||
|
|
||||
|
import java.net.URLEncoder; |
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
|
||||
|
/** |
||||
|
* 系统管理 - 期初导入。 |
||||
|
*/ |
||||
|
@RestController |
||||
|
@RequestMapping("/sys/initialImport") |
||||
|
public class SysInitialImportController { |
||||
|
|
||||
|
@Autowired |
||||
|
private SysInitialImportService initialImportService; |
||||
|
|
||||
|
@GetMapping("/supplierPrice/template") |
||||
|
public ResponseEntity<Resource> downloadSupplierPriceTemplate() { |
||||
|
byte[] bytes = initialImportService.buildSupplierPriceTemplate(); |
||||
|
String fileName = URLEncoder.encode("供应商价格期初导入模板.xlsx", StandardCharsets.UTF_8) |
||||
|
.replace("+", "%20"); |
||||
|
return ResponseEntity.ok() |
||||
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + fileName) |
||||
|
.header(HttpHeaders.CONTENT_LENGTH, String.valueOf(bytes.length)) |
||||
|
.contentType(MediaType.APPLICATION_OCTET_STREAM) |
||||
|
.body(new ByteArrayResource(bytes)); |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/supplierPrice/preview") |
||||
|
public R previewSupplierPrice(@RequestParam("file") MultipartFile file, |
||||
|
@RequestParam("site") String site) { |
||||
|
try { |
||||
|
SupplierPriceInitialImportPreviewResultVo result = initialImportService.previewSupplierPrice(file, site); |
||||
|
return R.ok() |
||||
|
.put("data", result.getRows()) |
||||
|
.put("total", result.getRows().size()) |
||||
|
.put("missingItems", result.getMissingItems()) |
||||
|
.put("missingSuppliers", result.getMissingSuppliers()); |
||||
|
} catch (RuntimeException ex) { |
||||
|
return R.error(ex.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/supplierPrice/save") |
||||
|
public R saveSupplierPrice(@RequestBody SupplierPriceInitialImportSaveVo data) { |
||||
|
try { |
||||
|
int savedCount = initialImportService.saveSupplierPrice(data); |
||||
|
int totalCount = data == null || data.getRows() == null ? 0 : data.getRows().size(); |
||||
|
return R.ok() |
||||
|
.put("savedCount", savedCount) |
||||
|
.put("skippedCount", totalCount - savedCount); |
||||
|
} catch (RuntimeException ex) { |
||||
|
return R.error(ex.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
package com.xujie.modules.sys.dao; |
||||
|
|
||||
|
import org.apache.ibatis.annotations.Mapper; |
||||
|
import org.apache.ibatis.annotations.Param; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 系统期初导入专用数据访问。 |
||||
|
*/ |
||||
|
@Mapper |
||||
|
public interface SysInitialImportMapper { |
||||
|
|
||||
|
List<String> listExistingItems(@Param("site") String site, @Param("items") List<String> items); |
||||
|
|
||||
|
List<String> listExistingSupplierShortNames(@Param("site") String site, |
||||
|
@Param("shortNames") List<String> shortNames); |
||||
|
|
||||
|
List<String> listPartNosByItem(@Param("site") String site, @Param("item") String item); |
||||
|
|
||||
|
List<String> listSupplierNosByShortNpc(@Param("site") String site, |
||||
|
@Param("shortNpc") String shortNpc); |
||||
|
|
||||
|
Integer countSupplierPart(@Param("site") String site, |
||||
|
@Param("supplierNo") String supplierNo, |
||||
|
@Param("partNo") String partNo); |
||||
|
|
||||
|
int updateSupplierPartMoq(@Param("site") String site, |
||||
|
@Param("supplierNo") String supplierNo, |
||||
|
@Param("partNo") String partNo, |
||||
|
@Param("minOrderQty") BigDecimal minOrderQty); |
||||
|
|
||||
|
int insertSupplierPart(@Param("site") String site, |
||||
|
@Param("supplierNo") String supplierNo, |
||||
|
@Param("partNo") String partNo, |
||||
|
@Param("minOrderQty") BigDecimal minOrderQty); |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
package com.xujie.modules.sys.service; |
||||
|
|
||||
|
import com.xujie.modules.sys.vo.SupplierPriceInitialImportPreviewResultVo; |
||||
|
import com.xujie.modules.sys.vo.SupplierPriceInitialImportSaveVo; |
||||
|
import org.springframework.web.multipart.MultipartFile; |
||||
|
|
||||
|
/** |
||||
|
* 系统期初导入服务。 |
||||
|
*/ |
||||
|
public interface SysInitialImportService { |
||||
|
|
||||
|
byte[] buildSupplierPriceTemplate(); |
||||
|
|
||||
|
SupplierPriceInitialImportPreviewResultVo previewSupplierPrice(MultipartFile file, String site); |
||||
|
|
||||
|
int saveSupplierPrice(SupplierPriceInitialImportSaveVo data); |
||||
|
} |
||||
@ -0,0 +1,630 @@ |
|||||
|
package com.xujie.modules.sys.service.impl; |
||||
|
|
||||
|
import com.xujie.modules.supplier.data.SupplierPartTierPriceHistoryMainVo; |
||||
|
import com.xujie.modules.supplier.data.SupplierPartTierPriceItemVo; |
||||
|
import com.xujie.modules.supplier.data.SupplierPartTierPriceQueryVo; |
||||
|
import com.xujie.modules.supplier.mapper.SupplierPartMoqPriceMapper; |
||||
|
import com.xujie.modules.sys.dao.SysInitialImportMapper; |
||||
|
import com.xujie.modules.sys.entity.SysUserEntity; |
||||
|
import com.xujie.modules.sys.service.SysInitialImportService; |
||||
|
import com.xujie.modules.sys.vo.SupplierPriceInitialImportPreviewResultVo; |
||||
|
import com.xujie.modules.sys.vo.SupplierPriceInitialImportRowVo; |
||||
|
import com.xujie.modules.sys.vo.SupplierPriceInitialImportSaveVo; |
||||
|
import org.apache.poi.ss.usermodel.BorderStyle; |
||||
|
import org.apache.poi.ss.usermodel.Cell; |
||||
|
import org.apache.poi.ss.usermodel.CellStyle; |
||||
|
import org.apache.poi.ss.usermodel.CellType; |
||||
|
import org.apache.poi.ss.usermodel.DataFormatter; |
||||
|
import org.apache.poi.ss.usermodel.DateUtil; |
||||
|
import org.apache.poi.ss.usermodel.FillPatternType; |
||||
|
import org.apache.poi.ss.usermodel.Font; |
||||
|
import org.apache.poi.ss.usermodel.FormulaEvaluator; |
||||
|
import org.apache.poi.ss.usermodel.HorizontalAlignment; |
||||
|
import org.apache.poi.ss.usermodel.IndexedColors; |
||||
|
import org.apache.poi.ss.usermodel.Row; |
||||
|
import org.apache.poi.ss.usermodel.Sheet; |
||||
|
import org.apache.poi.ss.usermodel.VerticalAlignment; |
||||
|
import org.apache.poi.ss.usermodel.Workbook; |
||||
|
import org.apache.poi.ss.usermodel.WorkbookFactory; |
||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
||||
|
import org.apache.shiro.SecurityUtils; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
import org.springframework.util.StringUtils; |
||||
|
import org.springframework.web.multipart.MultipartFile; |
||||
|
|
||||
|
import java.io.ByteArrayOutputStream; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.math.RoundingMode; |
||||
|
import java.time.LocalDate; |
||||
|
import java.time.LocalDateTime; |
||||
|
import java.time.ZoneId; |
||||
|
import java.time.format.DateTimeFormatter; |
||||
|
import java.time.format.DateTimeParseException; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.Arrays; |
||||
|
import java.util.Date; |
||||
|
import java.util.LinkedHashSet; |
||||
|
import java.util.List; |
||||
|
import java.util.Locale; |
||||
|
import java.util.Set; |
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@Service |
||||
|
public class SysInitialImportServiceImpl implements SysInitialImportService { |
||||
|
|
||||
|
private static final int MAX_IMPORT_ROWS = 1000; |
||||
|
private static final String SHEET_NAME = "price list"; |
||||
|
private static final List<String> HEADERS = Arrays.asList( |
||||
|
"RAW CODE", "SUPPLIER", "MOQ/COLOR", "START DATE", |
||||
|
"Tier_QTY_1", "Tier_QTY_2", "Tier_QTY_3", "Tier_QTY_4", |
||||
|
"Tier_QTY_5", "Tier_QTY_6", "Tier_QTY_7", "Tier_QTY_8", |
||||
|
"Price_Tier_1", "Price_Tier_2", "Price_Tier_3", "Price_Tier_4", |
||||
|
"Price_Tier_5", "Price_Tier_6", "Price_Tier_7", "Price_Tier_8" |
||||
|
); |
||||
|
private static final List<DateTimeFormatter> DATE_FORMATTERS = Arrays.asList( |
||||
|
DateTimeFormatter.ofPattern("yyyy-M-d", Locale.ENGLISH), |
||||
|
DateTimeFormatter.ofPattern("yyyy/M/d", Locale.ENGLISH), |
||||
|
DateTimeFormatter.ofPattern("M/d/yyyy", Locale.ENGLISH), |
||||
|
DateTimeFormatter.ofPattern("d/M/yyyy", Locale.ENGLISH), |
||||
|
DateTimeFormatter.ofPattern("d-MMM-yy", Locale.ENGLISH), |
||||
|
DateTimeFormatter.ofPattern("d-MMM-yyyy", Locale.ENGLISH), |
||||
|
DateTimeFormatter.ofPattern("MMM d, yyyy", Locale.ENGLISH), |
||||
|
DateTimeFormatter.ofPattern("yyyy年M月d日", Locale.CHINA) |
||||
|
); |
||||
|
private static final List<DateTimeFormatter> DATE_TIME_FORMATTERS = Arrays.asList( |
||||
|
DateTimeFormatter.ofPattern("yyyy-M-d H:m:s", Locale.ENGLISH), |
||||
|
DateTimeFormatter.ofPattern("yyyy/M/d H:m:s", Locale.ENGLISH), |
||||
|
DateTimeFormatter.ofPattern("yyyy-M-d H:m", Locale.ENGLISH), |
||||
|
DateTimeFormatter.ofPattern("yyyy/M/d H:m", Locale.ENGLISH), |
||||
|
DateTimeFormatter.ofPattern("M/d/yyyy H:m:s", Locale.ENGLISH), |
||||
|
DateTimeFormatter.ofPattern("M/d/yyyy H:m", Locale.ENGLISH) |
||||
|
); |
||||
|
|
||||
|
@Autowired |
||||
|
private SysInitialImportMapper initialImportMapper; |
||||
|
|
||||
|
@Autowired |
||||
|
private SupplierPartMoqPriceMapper supplierPartMoqPriceMapper; |
||||
|
|
||||
|
@Override |
||||
|
public byte[] buildSupplierPriceTemplate() { |
||||
|
try (Workbook workbook = new XSSFWorkbook(); ByteArrayOutputStream output = new ByteArrayOutputStream()) { |
||||
|
Sheet sheet = workbook.createSheet(SHEET_NAME); |
||||
|
Row headerRow = sheet.createRow(0); |
||||
|
CellStyle headerStyle = createHeaderStyle(workbook); |
||||
|
for (int i = 0; i < HEADERS.size(); i++) { |
||||
|
Cell cell = headerRow.createCell(i); |
||||
|
cell.setCellValue(HEADERS.get(i)); |
||||
|
cell.setCellStyle(headerStyle); |
||||
|
sheet.setColumnWidth(i, resolveColumnWidth(i) * 256); |
||||
|
} |
||||
|
sheet.createFreezePane(0, 1); |
||||
|
workbook.write(output); |
||||
|
return output.toByteArray(); |
||||
|
} catch (Exception ex) { |
||||
|
throw new RuntimeException("生成供应商价格导入模板失败", ex); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public SupplierPriceInitialImportPreviewResultVo previewSupplierPrice(MultipartFile file, String site) { |
||||
|
validateFile(file); |
||||
|
if (!StringUtils.hasText(site)) { |
||||
|
throw new RuntimeException("登录Site不能为空"); |
||||
|
} |
||||
|
try (Workbook workbook = WorkbookFactory.create(file.getInputStream())) { |
||||
|
if (workbook.getNumberOfSheets() == 0) { |
||||
|
throw new RuntimeException("Excel中没有工作表"); |
||||
|
} |
||||
|
Sheet sheet = workbook.getSheetAt(0); |
||||
|
DataFormatter formatter = new DataFormatter(Locale.ENGLISH); |
||||
|
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator(); |
||||
|
validateHeader(sheet.getRow(0), formatter, evaluator); |
||||
|
|
||||
|
List<SupplierPriceInitialImportRowVo> result = new ArrayList<SupplierPriceInitialImportRowVo>(); |
||||
|
for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) { |
||||
|
Row row = sheet.getRow(rowIndex); |
||||
|
if (isEmptyRow(row, formatter, evaluator)) { |
||||
|
continue; |
||||
|
} |
||||
|
if (result.size() >= MAX_IMPORT_ROWS) { |
||||
|
throw new RuntimeException("单次导入上限是1000行,请分批导入"); |
||||
|
} |
||||
|
result.add(parseRow(row, rowIndex + 1, formatter, evaluator)); |
||||
|
} |
||||
|
if (result.isEmpty()) { |
||||
|
throw new RuntimeException("Excel中没有可预览的数据"); |
||||
|
} |
||||
|
return validatePreviewMappings(site.trim(), result); |
||||
|
} catch (RuntimeException ex) { |
||||
|
throw ex; |
||||
|
} catch (Exception ex) { |
||||
|
throw new RuntimeException("读取Excel失败,请检查文件格式", ex); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
@Transactional(rollbackFor = Exception.class) |
||||
|
public int saveSupplierPrice(SupplierPriceInitialImportSaveVo data) { |
||||
|
if (data == null || !StringUtils.hasText(data.getSite())) { |
||||
|
throw new RuntimeException("登录Site不能为空"); |
||||
|
} |
||||
|
if (data.getRows() == null || data.getRows().isEmpty()) { |
||||
|
throw new RuntimeException("没有可保存的导入数据"); |
||||
|
} |
||||
|
if (data.getRows().size() > MAX_IMPORT_ROWS) { |
||||
|
throw new RuntimeException("单次导入上限是1000行,请分批导入"); |
||||
|
} |
||||
|
|
||||
|
String site = data.getSite().trim(); |
||||
|
String submitBy = resolveSubmitBy(); |
||||
|
int savedCount = 0; |
||||
|
for (int index = 0; index < data.getRows().size(); index++) { |
||||
|
try { |
||||
|
if (saveSupplierPriceRow(site, submitBy, data.getRows().get(index))) { |
||||
|
savedCount++; |
||||
|
} |
||||
|
} catch (RuntimeException ex) { |
||||
|
throw new RuntimeException("Excel第" + (index + 2) + "行:" + ex.getMessage(), ex); |
||||
|
} |
||||
|
} |
||||
|
return savedCount; |
||||
|
} |
||||
|
|
||||
|
private boolean saveSupplierPriceRow(String site, String submitBy, SupplierPriceInitialImportRowVo row) { |
||||
|
if (row == null) { |
||||
|
throw new RuntimeException("数据不能为空"); |
||||
|
} |
||||
|
String item = trimToEmpty(row.getRawCode()); |
||||
|
String shortNpc = trimToEmpty(row.getSupplier()); |
||||
|
if (!StringUtils.hasText(item) || !StringUtils.hasText(shortNpc)) { |
||||
|
return false; |
||||
|
} |
||||
|
List<String> partNos = initialImportMapper.listPartNosByItem(site, item); |
||||
|
List<String> supplierNos = initialImportMapper.listSupplierNosByShortNpc(site, shortNpc); |
||||
|
if (partNos == null || partNos.isEmpty() || supplierNos == null || supplierNos.isEmpty()) { |
||||
|
return false; |
||||
|
} |
||||
|
if (row.getMoqColor() != null && row.getMoqColor().compareTo(BigDecimal.ZERO) < 0) { |
||||
|
throw new RuntimeException("MOQ/COLOR不能小于0"); |
||||
|
} |
||||
|
|
||||
|
String partNo = resolveUniqueCode(partNos, |
||||
|
"Item未找到对应物料:" + item, |
||||
|
"Item对应多个物料,请先处理重复数据:" + item); |
||||
|
String supplierNo = resolveUniqueCode(supplierNos, |
||||
|
"Short_NPC未找到对应供应商:" + shortNpc, |
||||
|
"Short_NPC对应多个供应商,请先处理重复数据:" + shortNpc); |
||||
|
|
||||
|
Integer relationCount = initialImportMapper.countSupplierPart(site, supplierNo, partNo); |
||||
|
if (relationCount != null && relationCount > 0) { |
||||
|
initialImportMapper.updateSupplierPartMoq(site, supplierNo, partNo, row.getMoqColor()); |
||||
|
} else { |
||||
|
initialImportMapper.insertSupplierPart(site, supplierNo, partNo, row.getMoqColor()); |
||||
|
} |
||||
|
|
||||
|
List<SupplierPartTierPriceItemVo> newTierPrices = buildTierPriceList(row); |
||||
|
if (newTierPrices.isEmpty()) { |
||||
|
return true; |
||||
|
} |
||||
|
LocalDate newPriceDate = parseImportDate(row.getStartDate()); |
||||
|
|
||||
|
SupplierPartTierPriceQueryVo query = new SupplierPartTierPriceQueryVo(); |
||||
|
query.setSite(site); |
||||
|
query.setSupplierCode(supplierNo); |
||||
|
query.setPartNo(partNo); |
||||
|
List<SupplierPartTierPriceItemVo> currentTierPrices = supplierPartMoqPriceMapper.listCurrentTierPrice(query); |
||||
|
|
||||
|
if (currentTierPrices != null && !currentTierPrices.isEmpty()) { |
||||
|
LocalDate currentPriceDate = resolveCurrentPriceDate(currentTierPrices); |
||||
|
if (!currentPriceDate.equals(newPriceDate)) { |
||||
|
archiveCurrentTierPrice(site, supplierNo, partNo, submitBy, currentPriceDate, currentTierPrices); |
||||
|
} |
||||
|
supplierPartMoqPriceMapper.deleteCurrentTierPrice(site, supplierNo, partNo); |
||||
|
} |
||||
|
|
||||
|
supplierPartMoqPriceMapper.insertCurrentTierPriceBatch( |
||||
|
site, |
||||
|
supplierNo, |
||||
|
partNo, |
||||
|
newPriceDate.toString(), |
||||
|
"", |
||||
|
submitBy, |
||||
|
newTierPrices |
||||
|
); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
private SupplierPriceInitialImportPreviewResultVo validatePreviewMappings( |
||||
|
String site, List<SupplierPriceInitialImportRowVo> rows) { |
||||
|
Set<String> requestedItems = new LinkedHashSet<>(); |
||||
|
Set<String> requestedSupplierShortNames = new LinkedHashSet<>(); |
||||
|
for (SupplierPriceInitialImportRowVo row : rows) { |
||||
|
if (row != null && StringUtils.hasText(row.getRawCode())) { |
||||
|
requestedItems.add(normalizeLookupValue(row.getRawCode())); |
||||
|
} |
||||
|
if (row != null && StringUtils.hasText(row.getSupplier())) { |
||||
|
requestedSupplierShortNames.add(normalizeLookupValue(row.getSupplier())); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Set<String> existingItems = normalizeLookupValues(requestedItems.isEmpty() |
||||
|
? new ArrayList<>() |
||||
|
: initialImportMapper.listExistingItems(site, new ArrayList<>(requestedItems))); |
||||
|
Set<String> existingSupplierShortNames = normalizeLookupValues(requestedSupplierShortNames.isEmpty() |
||||
|
? new ArrayList<>() |
||||
|
: initialImportMapper.listExistingSupplierShortNames( |
||||
|
site, new ArrayList<>(requestedSupplierShortNames))); |
||||
|
|
||||
|
Set<String> missingItems = new LinkedHashSet<>(); |
||||
|
Set<String> missingSuppliers = new LinkedHashSet<>(); |
||||
|
for (SupplierPriceInitialImportRowVo row : rows) { |
||||
|
String item = row == null ? "" : trimToEmpty(row.getRawCode()); |
||||
|
String supplierShortName = row == null ? "" : trimToEmpty(row.getSupplier()); |
||||
|
boolean itemExists = StringUtils.hasText(item) |
||||
|
&& existingItems.contains(normalizeLookupValue(item)); |
||||
|
boolean supplierExists = StringUtils.hasText(supplierShortName) |
||||
|
&& existingSupplierShortNames.contains(normalizeLookupValue(supplierShortName)); |
||||
|
|
||||
|
if (!itemExists) { |
||||
|
missingItems.add(StringUtils.hasText(item) ? item : "(空)"); |
||||
|
} |
||||
|
if (!supplierExists) { |
||||
|
missingSuppliers.add(StringUtils.hasText(supplierShortName) ? supplierShortName : "(空)"); |
||||
|
} |
||||
|
if (row != null) { |
||||
|
row.setValid(itemExists && supplierExists); |
||||
|
row.setValidationMessage(buildValidationMessage(itemExists, supplierExists)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
SupplierPriceInitialImportPreviewResultVo result = new SupplierPriceInitialImportPreviewResultVo(); |
||||
|
result.setRows(rows); |
||||
|
result.setMissingItems(new ArrayList<>(missingItems)); |
||||
|
result.setMissingSuppliers(new ArrayList<>(missingSuppliers)); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
private Set<String> normalizeLookupValues(List<String> values) { |
||||
|
Set<String> result = new LinkedHashSet<>(); |
||||
|
if (values == null) { |
||||
|
return result; |
||||
|
} |
||||
|
for (String value : values) { |
||||
|
if (StringUtils.hasText(value)) { |
||||
|
result.add(normalizeLookupValue(value)); |
||||
|
} |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
private String normalizeLookupValue(String value) { |
||||
|
return trimToEmpty(value).toUpperCase(Locale.ENGLISH); |
||||
|
} |
||||
|
|
||||
|
private String buildValidationMessage(boolean itemExists, boolean supplierExists) { |
||||
|
if (!itemExists && !supplierExists) { |
||||
|
return "Item和供应商简称不存在"; |
||||
|
} |
||||
|
if (!itemExists) { |
||||
|
return "Item不存在"; |
||||
|
} |
||||
|
if (!supplierExists) { |
||||
|
return "供应商简称不存在"; |
||||
|
} |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
List<SupplierPartTierPriceItemVo> buildTierPriceList(SupplierPriceInitialImportRowVo row) { |
||||
|
BigDecimal[] quantities = { |
||||
|
row.getTierQty1(), row.getTierQty2(), row.getTierQty3(), row.getTierQty4(), |
||||
|
row.getTierQty5(), row.getTierQty6(), row.getTierQty7(), row.getTierQty8() |
||||
|
}; |
||||
|
BigDecimal[] prices = { |
||||
|
row.getPriceTier1(), row.getPriceTier2(), row.getPriceTier3(), row.getPriceTier4(), |
||||
|
row.getPriceTier5(), row.getPriceTier6(), row.getPriceTier7(), row.getPriceTier8() |
||||
|
}; |
||||
|
|
||||
|
List<SupplierPartTierPriceItemVo> result = new ArrayList<>(); |
||||
|
BigDecimal quantityStart = BigDecimal.ZERO; |
||||
|
boolean tierEnded = false; |
||||
|
for (int index = 0; index < quantities.length; index++) { |
||||
|
BigDecimal quantityEnd = quantities[index]; |
||||
|
BigDecimal unitPrice = prices[index]; |
||||
|
if (quantityEnd == null && unitPrice == null) { |
||||
|
tierEnded = true; |
||||
|
continue; |
||||
|
} |
||||
|
if (tierEnded) { |
||||
|
throw new RuntimeException("阶梯数量和价格不能在空档后继续填写"); |
||||
|
} |
||||
|
if (quantityEnd == null || unitPrice == null) { |
||||
|
throw new RuntimeException("第" + (index + 1) + "档的Tier_QTY和Price_Tier必须同时填写"); |
||||
|
} |
||||
|
if (quantityEnd.compareTo(quantityStart) < 0) { |
||||
|
throw new RuntimeException("第" + (index + 1) + "档数量上限必须大于上一档数量上限"); |
||||
|
} |
||||
|
if (unitPrice.compareTo(BigDecimal.ZERO) < 0) { |
||||
|
throw new RuntimeException("第" + (index + 1) + "档价格不能小于0"); |
||||
|
} |
||||
|
|
||||
|
SupplierPartTierPriceItemVo tierPrice = new SupplierPartTierPriceItemVo(); |
||||
|
// Keep every row at the target SQL Server scale. Mixed BigDecimal scales in a |
||||
|
// multi-row VALUES statement can otherwise be inferred as the lowest scale. |
||||
|
tierPrice.setQtyStart(quantityStart.setScale(4, RoundingMode.HALF_UP)); |
||||
|
tierPrice.setQtyEnd(quantityEnd.setScale(4, RoundingMode.HALF_UP)); |
||||
|
tierPrice.setUnitPrice(unitPrice.setScale(6, RoundingMode.HALF_UP)); |
||||
|
tierPrice.setRemark(""); |
||||
|
result.add(tierPrice); |
||||
|
quantityStart = quantityEnd.add(BigDecimal.ONE); |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
private void archiveCurrentTierPrice(String site, |
||||
|
String supplierNo, |
||||
|
String partNo, |
||||
|
String submitBy, |
||||
|
LocalDate priceDate, |
||||
|
List<SupplierPartTierPriceItemVo> currentTierPrices) { |
||||
|
Date submitDate = new Date(); |
||||
|
String versionNo = generateInitialImportVersionNo(); |
||||
|
String attachmentRefs = resolveAttachmentRefs(currentTierPrices); |
||||
|
|
||||
|
SupplierPartTierPriceHistoryMainVo historyMain = new SupplierPartTierPriceHistoryMainVo(); |
||||
|
historyMain.setSite(site); |
||||
|
historyMain.setSupplierCode(supplierNo); |
||||
|
historyMain.setPartNo(partNo); |
||||
|
historyMain.setVersionNo(versionNo); |
||||
|
historyMain.setSubmitDate(submitDate); |
||||
|
historyMain.setPriceDate(java.sql.Date.valueOf(priceDate)); |
||||
|
historyMain.setSubmitBy(submitBy); |
||||
|
historyMain.setCurrency("USD"); |
||||
|
historyMain.setAttachmentRefs(attachmentRefs); |
||||
|
supplierPartMoqPriceMapper.insertHistoryTierPriceMain(historyMain); |
||||
|
if (historyMain.getId() == null) { |
||||
|
throw new RuntimeException("当前价格归档失败"); |
||||
|
} |
||||
|
|
||||
|
supplierPartMoqPriceMapper.insertHistoryTierPriceBatch( |
||||
|
site, |
||||
|
historyMain.getId(), |
||||
|
supplierNo, |
||||
|
partNo, |
||||
|
versionNo, |
||||
|
submitDate, |
||||
|
priceDate.toString(), |
||||
|
attachmentRefs, |
||||
|
submitBy, |
||||
|
currentTierPrices |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
private LocalDate resolveCurrentPriceDate(List<SupplierPartTierPriceItemVo> rows) { |
||||
|
LocalDate priceDate = null; |
||||
|
for (SupplierPartTierPriceItemVo row : rows) { |
||||
|
if (row == null || row.getPriceDate() == null) { |
||||
|
throw new RuntimeException("当前价格记录的价格日期为空"); |
||||
|
} |
||||
|
LocalDate rowPriceDate = toLocalDate(row.getPriceDate()); |
||||
|
if (priceDate == null) { |
||||
|
priceDate = rowPriceDate; |
||||
|
} else if (!priceDate.equals(rowPriceDate)) { |
||||
|
throw new RuntimeException("当前价格记录存在多个价格日期,请先处理异常数据"); |
||||
|
} |
||||
|
} |
||||
|
return priceDate; |
||||
|
} |
||||
|
|
||||
|
private LocalDate toLocalDate(Date value) { |
||||
|
if (value instanceof java.sql.Date) { |
||||
|
return ((java.sql.Date) value).toLocalDate(); |
||||
|
} |
||||
|
return value.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); |
||||
|
} |
||||
|
|
||||
|
private LocalDate parseImportDate(String value) { |
||||
|
if (!StringUtils.hasText(value)) { |
||||
|
throw new RuntimeException("START DATE不能为空"); |
||||
|
} |
||||
|
try { |
||||
|
return LocalDate.parse(value.trim(), DateTimeFormatter.ISO_LOCAL_DATE); |
||||
|
} catch (DateTimeParseException ex) { |
||||
|
throw new RuntimeException("START DATE格式错误,应为yyyy-MM-dd"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private String resolveUniqueCode(List<String> values, String emptyMessage, String duplicateMessage) { |
||||
|
if (values == null || values.isEmpty()) { |
||||
|
throw new RuntimeException(emptyMessage); |
||||
|
} |
||||
|
if (values.size() > 1) { |
||||
|
throw new RuntimeException(duplicateMessage + "(" + String.join("、", values) + ")"); |
||||
|
} |
||||
|
return values.get(0); |
||||
|
} |
||||
|
|
||||
|
private String trimToEmpty(String value) { |
||||
|
return StringUtils.hasText(value) ? value.trim() : ""; |
||||
|
} |
||||
|
|
||||
|
private String resolveSubmitBy() { |
||||
|
Object principal = SecurityUtils.getSubject().getPrincipal(); |
||||
|
if (principal instanceof SysUserEntity && StringUtils.hasText(((SysUserEntity) principal).getUsername())) { |
||||
|
return ((SysUserEntity) principal).getUsername().trim(); |
||||
|
} |
||||
|
return "system"; |
||||
|
} |
||||
|
|
||||
|
private String resolveAttachmentRefs(List<SupplierPartTierPriceItemVo> rows) { |
||||
|
for (SupplierPartTierPriceItemVo row : rows) { |
||||
|
if (row != null && StringUtils.hasText(row.getAttachmentRefs())) { |
||||
|
return row.getAttachmentRefs().trim(); |
||||
|
} |
||||
|
} |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
private String generateInitialImportVersionNo() { |
||||
|
String time = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS").format(LocalDateTime.now()); |
||||
|
String random = UUID.randomUUID().toString().substring(0, 8).toUpperCase(Locale.ENGLISH); |
||||
|
return "INIT-" + time + "-" + random; |
||||
|
} |
||||
|
|
||||
|
private SupplierPriceInitialImportRowVo parseRow(Row row, int excelRowNo, |
||||
|
DataFormatter formatter, FormulaEvaluator evaluator) { |
||||
|
SupplierPriceInitialImportRowVo value = new SupplierPriceInitialImportRowVo(); |
||||
|
value.setRawCode(readText(row.getCell(0), formatter, evaluator)); |
||||
|
value.setSupplier(readText(row.getCell(1), formatter, evaluator)); |
||||
|
value.setMoqColor(readDecimal(row.getCell(2), excelRowNo, HEADERS.get(2), formatter, evaluator)); |
||||
|
value.setStartDate(readDate(row.getCell(3), excelRowNo, formatter, evaluator)); |
||||
|
value.setTierQty1(readDecimal(row.getCell(4), excelRowNo, HEADERS.get(4), formatter, evaluator)); |
||||
|
value.setTierQty2(readDecimal(row.getCell(5), excelRowNo, HEADERS.get(5), formatter, evaluator)); |
||||
|
value.setTierQty3(readDecimal(row.getCell(6), excelRowNo, HEADERS.get(6), formatter, evaluator)); |
||||
|
value.setTierQty4(readDecimal(row.getCell(7), excelRowNo, HEADERS.get(7), formatter, evaluator)); |
||||
|
value.setTierQty5(readDecimal(row.getCell(8), excelRowNo, HEADERS.get(8), formatter, evaluator)); |
||||
|
value.setTierQty6(readDecimal(row.getCell(9), excelRowNo, HEADERS.get(9), formatter, evaluator)); |
||||
|
value.setTierQty7(readDecimal(row.getCell(10), excelRowNo, HEADERS.get(10), formatter, evaluator)); |
||||
|
value.setTierQty8(readDecimal(row.getCell(11), excelRowNo, HEADERS.get(11), formatter, evaluator)); |
||||
|
value.setPriceTier1(readDecimal(row.getCell(12), excelRowNo, HEADERS.get(12), formatter, evaluator)); |
||||
|
value.setPriceTier2(readDecimal(row.getCell(13), excelRowNo, HEADERS.get(13), formatter, evaluator)); |
||||
|
value.setPriceTier3(readDecimal(row.getCell(14), excelRowNo, HEADERS.get(14), formatter, evaluator)); |
||||
|
value.setPriceTier4(readDecimal(row.getCell(15), excelRowNo, HEADERS.get(15), formatter, evaluator)); |
||||
|
value.setPriceTier5(readDecimal(row.getCell(16), excelRowNo, HEADERS.get(16), formatter, evaluator)); |
||||
|
value.setPriceTier6(readDecimal(row.getCell(17), excelRowNo, HEADERS.get(17), formatter, evaluator)); |
||||
|
value.setPriceTier7(readDecimal(row.getCell(18), excelRowNo, HEADERS.get(18), formatter, evaluator)); |
||||
|
value.setPriceTier8(readDecimal(row.getCell(19), excelRowNo, HEADERS.get(19), formatter, evaluator)); |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
private void validateHeader(Row headerRow, DataFormatter formatter, FormulaEvaluator evaluator) { |
||||
|
if (headerRow == null) { |
||||
|
throw new RuntimeException("Excel第一行必须是模板表头"); |
||||
|
} |
||||
|
for (int i = 0; i < HEADERS.size(); i++) { |
||||
|
String actual = normalizeHeader(readText(headerRow.getCell(i), formatter, evaluator)); |
||||
|
String expected = normalizeHeader(HEADERS.get(i)); |
||||
|
if (!expected.equals(actual)) { |
||||
|
throw new RuntimeException("Excel第" + (i + 1) + "列表头应为 " + HEADERS.get(i)); |
||||
|
} |
||||
|
} |
||||
|
short lastCellNum = headerRow.getLastCellNum(); |
||||
|
for (int i = HEADERS.size(); i < lastCellNum; i++) { |
||||
|
if (StringUtils.hasText(readText(headerRow.getCell(i), formatter, evaluator))) { |
||||
|
throw new RuntimeException("Excel表头必须与下载模板一致,不能增加额外栏位"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private String readText(Cell cell, DataFormatter formatter, FormulaEvaluator evaluator) { |
||||
|
if (cell == null) { |
||||
|
return null; |
||||
|
} |
||||
|
String text = formatter.formatCellValue(cell, evaluator); |
||||
|
return StringUtils.hasText(text) ? text.trim() : null; |
||||
|
} |
||||
|
|
||||
|
private BigDecimal readDecimal(Cell cell, int rowNo, String columnName, |
||||
|
DataFormatter formatter, FormulaEvaluator evaluator) { |
||||
|
String text = readText(cell, formatter, evaluator); |
||||
|
if (!StringUtils.hasText(text)) { |
||||
|
return null; |
||||
|
} |
||||
|
try { |
||||
|
String normalized = text.replace('\u00A0', ' ').trim(); |
||||
|
boolean negativeByParentheses = normalized.startsWith("(") && normalized.endsWith(")"); |
||||
|
normalized = normalized.replaceAll("[\\p{Sc}\\p{L}\\s]", "") |
||||
|
.replace(",", "") |
||||
|
.replace("(", "") |
||||
|
.replace(")", ""); |
||||
|
if (!normalized.matches("[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?")) { |
||||
|
throw new NumberFormatException(); |
||||
|
} |
||||
|
BigDecimal number = new BigDecimal(normalized); |
||||
|
return negativeByParentheses ? number.negate() : number; |
||||
|
} catch (NumberFormatException ex) { |
||||
|
throw new RuntimeException("第" + rowNo + "行 " + columnName + " 必须是数字"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private String readDate(Cell cell, int rowNo, DataFormatter formatter, FormulaEvaluator evaluator) { |
||||
|
String text = readText(cell, formatter, evaluator); |
||||
|
if (!StringUtils.hasText(text)) { |
||||
|
return null; |
||||
|
} |
||||
|
if ((cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) |
||||
|
&& DateUtil.isCellDateFormatted(cell)) { |
||||
|
return DateUtil.getLocalDateTime(cell.getNumericCellValue()).toLocalDate().toString(); |
||||
|
} |
||||
|
for (DateTimeFormatter dateFormatter : DATE_FORMATTERS) { |
||||
|
try { |
||||
|
return LocalDate.parse(text, dateFormatter).toString(); |
||||
|
} catch (DateTimeParseException ignored) { |
||||
|
// 继续尝试下一种格式。 |
||||
|
} |
||||
|
} |
||||
|
for (DateTimeFormatter dateTimeFormatter : DATE_TIME_FORMATTERS) { |
||||
|
try { |
||||
|
return LocalDateTime.parse(text, dateTimeFormatter).toLocalDate().toString(); |
||||
|
} catch (DateTimeParseException ignored) { |
||||
|
// 继续尝试下一种格式。 |
||||
|
} |
||||
|
} |
||||
|
throw new RuntimeException("第" + rowNo + "行 START DATE 日期格式无法识别"); |
||||
|
} |
||||
|
|
||||
|
private boolean isEmptyRow(Row row, DataFormatter formatter, FormulaEvaluator evaluator) { |
||||
|
if (row == null) { |
||||
|
return true; |
||||
|
} |
||||
|
for (int i = 0; i < HEADERS.size(); i++) { |
||||
|
if (StringUtils.hasText(readText(row.getCell(i), formatter, evaluator))) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
private void validateFile(MultipartFile file) { |
||||
|
if (file == null || file.isEmpty()) { |
||||
|
throw new RuntimeException("请选择Excel文件"); |
||||
|
} |
||||
|
String fileName = file.getOriginalFilename(); |
||||
|
String lowerName = fileName == null ? "" : fileName.toLowerCase(Locale.ENGLISH); |
||||
|
if (!lowerName.endsWith(".xlsx") && !lowerName.endsWith(".xls")) { |
||||
|
throw new RuntimeException("仅支持.xls或.xlsx文件"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private CellStyle createHeaderStyle(Workbook workbook) { |
||||
|
CellStyle style = workbook.createCellStyle(); |
||||
|
Font font = workbook.createFont(); |
||||
|
font.setBold(true); |
||||
|
style.setFont(font); |
||||
|
style.setAlignment(HorizontalAlignment.CENTER); |
||||
|
style.setVerticalAlignment(VerticalAlignment.CENTER); |
||||
|
style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); |
||||
|
style.setFillPattern(FillPatternType.SOLID_FOREGROUND); |
||||
|
style.setBorderTop(BorderStyle.THIN); |
||||
|
style.setBorderRight(BorderStyle.THIN); |
||||
|
style.setBorderBottom(BorderStyle.THIN); |
||||
|
style.setBorderLeft(BorderStyle.THIN); |
||||
|
return style; |
||||
|
} |
||||
|
|
||||
|
private int resolveColumnWidth(int columnIndex) { |
||||
|
if (columnIndex == 0 || columnIndex == 1) { |
||||
|
return 20; |
||||
|
} |
||||
|
if (columnIndex == 3) { |
||||
|
return 15; |
||||
|
} |
||||
|
return 14; |
||||
|
} |
||||
|
|
||||
|
private String normalizeHeader(String value) { |
||||
|
return value == null ? "" : value.replace("\uFEFF", "").trim(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
package com.xujie.modules.sys.vo; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 供应商价格期初导入预览结果。 |
||||
|
*/ |
||||
|
@Data |
||||
|
public class SupplierPriceInitialImportPreviewResultVo { |
||||
|
|
||||
|
private List<SupplierPriceInitialImportRowVo> rows = new ArrayList<>(); |
||||
|
|
||||
|
private List<String> missingItems = new ArrayList<>(); |
||||
|
|
||||
|
private List<String> missingSuppliers = new ArrayList<>(); |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
package com.xujie.modules.sys.vo; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
|
||||
|
/** |
||||
|
* 供应商价格期初导入预览行。 |
||||
|
*/ |
||||
|
@Data |
||||
|
public class SupplierPriceInitialImportRowVo { |
||||
|
|
||||
|
private String rawCode; |
||||
|
private String supplier; |
||||
|
private BigDecimal moqColor; |
||||
|
private String startDate; |
||||
|
private BigDecimal tierQty1; |
||||
|
private BigDecimal tierQty2; |
||||
|
private BigDecimal tierQty3; |
||||
|
private BigDecimal tierQty4; |
||||
|
private BigDecimal tierQty5; |
||||
|
private BigDecimal tierQty6; |
||||
|
private BigDecimal tierQty7; |
||||
|
private BigDecimal tierQty8; |
||||
|
private BigDecimal priceTier1; |
||||
|
private BigDecimal priceTier2; |
||||
|
private BigDecimal priceTier3; |
||||
|
private BigDecimal priceTier4; |
||||
|
private BigDecimal priceTier5; |
||||
|
private BigDecimal priceTier6; |
||||
|
private BigDecimal priceTier7; |
||||
|
private BigDecimal priceTier8; |
||||
|
private Boolean valid; |
||||
|
private String validationMessage; |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
package com.xujie.modules.sys.vo; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 供应商价格期初导入保存参数。 |
||||
|
*/ |
||||
|
@Data |
||||
|
public class SupplierPriceInitialImportSaveVo { |
||||
|
|
||||
|
private String site; |
||||
|
|
||||
|
private List<SupplierPriceInitialImportRowVo> rows; |
||||
|
} |
||||
@ -0,0 +1,85 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
|
||||
|
<mapper namespace="com.xujie.modules.sys.dao.SysInitialImportMapper"> |
||||
|
|
||||
|
<select id="listExistingItems" resultType="java.lang.String"> |
||||
|
SELECT DISTINCT LTRIM(RTRIM(item)) |
||||
|
FROM part |
||||
|
WHERE site = #{site} |
||||
|
AND UPPER(LTRIM(RTRIM(item))) IN |
||||
|
<foreach collection="items" item="item" open="(" separator="," close=")"> |
||||
|
#{item} |
||||
|
</foreach> |
||||
|
</select> |
||||
|
|
||||
|
<select id="listExistingSupplierShortNames" resultType="java.lang.String"> |
||||
|
SELECT DISTINCT LTRIM(RTRIM(c_short_npc)) |
||||
|
FROM srm_supplier |
||||
|
WHERE site = #{site} |
||||
|
AND UPPER(LTRIM(RTRIM(c_short_npc))) IN |
||||
|
<foreach collection="shortNames" item="shortName" open="(" separator="," close=")"> |
||||
|
#{shortName} |
||||
|
</foreach> |
||||
|
</select> |
||||
|
|
||||
|
<select id="listPartNosByItem" resultType="java.lang.String"> |
||||
|
SELECT DISTINCT part_no |
||||
|
FROM part |
||||
|
WHERE site = #{site} |
||||
|
AND UPPER(LTRIM(RTRIM(item))) = UPPER(#{item}) |
||||
|
ORDER BY part_no |
||||
|
</select> |
||||
|
|
||||
|
<select id="listSupplierNosByShortNpc" resultType="java.lang.String"> |
||||
|
SELECT DISTINCT supplier_no |
||||
|
FROM srm_supplier |
||||
|
WHERE site = #{site} |
||||
|
AND UPPER(LTRIM(RTRIM(c_short_npc))) = UPPER(#{shortNpc}) |
||||
|
ORDER BY supplier_no |
||||
|
</select> |
||||
|
|
||||
|
<select id="countSupplierPart" resultType="java.lang.Integer"> |
||||
|
SELECT COUNT(1) |
||||
|
FROM SupplierforPart |
||||
|
WHERE site = #{site} |
||||
|
AND supplier_no = #{supplierNo} |
||||
|
AND part_no = #{partNo} |
||||
|
</select> |
||||
|
|
||||
|
<update id="updateSupplierPartMoq"> |
||||
|
UPDATE SupplierforPart |
||||
|
SET [minOrderQty] = #{minOrderQty} |
||||
|
WHERE site = #{site} |
||||
|
AND supplier_no = #{supplierNo} |
||||
|
AND part_no = #{partNo} |
||||
|
</update> |
||||
|
|
||||
|
<insert id="insertSupplierPart"> |
||||
|
INSERT INTO SupplierforPart |
||||
|
( |
||||
|
site, |
||||
|
supplier_no, |
||||
|
part_no, |
||||
|
active, |
||||
|
currency, |
||||
|
[minOrderQty], |
||||
|
new_product_audited, |
||||
|
need_new_product_audit, |
||||
|
need_submit_test |
||||
|
) |
||||
|
VALUES |
||||
|
( |
||||
|
#{site}, |
||||
|
#{supplierNo}, |
||||
|
#{partNo}, |
||||
|
'Y', |
||||
|
'USD', |
||||
|
#{minOrderQty}, |
||||
|
'Y', |
||||
|
'N', |
||||
|
'N' |
||||
|
) |
||||
|
</insert> |
||||
|
|
||||
|
</mapper> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue