Merge branch 'master' of https://gitea.zianxin.com/zax/biz-api-cloud-zax
This commit is contained in:
commit
cb5fdc54d8
2 files changed
+66
-17
No files matched your search
+10
-4
@@ -241,18 +241,24 @@ public class CanteenSpuController {
|
||||
/**
|
||||
* Excel 导入菜品(单品 + 套餐)
|
||||
*
|
||||
* @param cover true=覆盖(同名更新),false=仅新增(同名跳过)
|
||||
* @param importMode cover=覆盖更新;skip=同名跳过;force=同名也新增(分类仍复用)。兼容旧参数 cover
|
||||
*/
|
||||
@Operation(summary = "Excel导入菜品", description = "cover=true 覆盖导入;cover=false 新增导入;支持套餐")
|
||||
@Operation(summary = "Excel导入菜品", description = "importMode=cover/skip/force;兼容 cover=true/false")
|
||||
@SysLog("导入菜品spu")
|
||||
@PostMapping("/import")
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenSpu_add')")
|
||||
public R importExcel(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam("merchantId") Long merchantId,
|
||||
@RequestParam(value = "categoryId", required = false) Long categoryId,
|
||||
@RequestParam(value = "cover", defaultValue = "false") boolean cover) throws Exception {
|
||||
@RequestParam(value = "importMode", required = false) String importMode,
|
||||
@RequestParam(value = "cover", required = false) Boolean cover) throws Exception {
|
||||
try {
|
||||
return canteenSpuImportHelper.importExcel(file, merchantId, categoryId, cover);
|
||||
String mode = importMode;
|
||||
if (StrUtil.isBlank(mode) && cover != null) {
|
||||
mode = Boolean.TRUE.equals(cover) ? CanteenSpuImportHelper.MODE_COVER
|
||||
: CanteenSpuImportHelper.MODE_SKIP;
|
||||
}
|
||||
return canteenSpuImportHelper.importExcel(file, merchantId, categoryId, mode);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
return R.failed(ex.getMessage());
|
||||
|
||||
+56
-13
@@ -46,7 +46,7 @@ import java.util.Set;
|
||||
* 菜品列表 Excel 导入/导出(单品 + 套餐)
|
||||
* <ul>
|
||||
* <li>套餐名留空=单品;套餐名相同多行=套餐组成</li>
|
||||
* <li>cover=true:同名更新;cover=false:同名跳过</li>
|
||||
* <li>cover:同名更新;skip:同名跳过;force:同名也新增(分类仍按名称复用)</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Service
|
||||
@@ -190,9 +190,25 @@ public class CanteenSpuImportHelper {
|
||||
return row;
|
||||
}
|
||||
|
||||
/** 覆盖:同名/同ID更新 */
|
||||
public static final String MODE_COVER = "cover";
|
||||
/** 新增:同名跳过 */
|
||||
public static final String MODE_SKIP = "skip";
|
||||
/** 不覆盖:同名套餐/单品也强制新增;分类仍复用 */
|
||||
public static final String MODE_FORCE = "force";
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R importExcel(MultipartFile file, Long merchantId, Long defaultCategoryId, boolean cover)
|
||||
throws IOException {
|
||||
return importExcel(file, merchantId, defaultCategoryId, cover ? MODE_COVER : MODE_SKIP);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R importExcel(MultipartFile file, Long merchantId, Long defaultCategoryId, String importMode)
|
||||
throws IOException {
|
||||
String mode = normalizeImportMode(importMode);
|
||||
boolean cover = MODE_COVER.equals(mode);
|
||||
boolean force = MODE_FORCE.equals(mode);
|
||||
if (merchantId == null) {
|
||||
return R.failed("请选择商户");
|
||||
}
|
||||
@@ -269,7 +285,7 @@ public class CanteenSpuImportHelper {
|
||||
}
|
||||
try {
|
||||
int[] c = upsertCombo(e.getKey(), e.getValue(), merchantId, deptId, defaultCategoryId, categoryByName,
|
||||
cover, errors, cache, pendingUpdates, standaloneDishIds, standaloneNames);
|
||||
mode, errors, cache, pendingUpdates, standaloneDishIds, standaloneNames);
|
||||
created += c[0];
|
||||
updated += c[1];
|
||||
skipped += c[2];
|
||||
@@ -281,7 +297,7 @@ public class CanteenSpuImportHelper {
|
||||
}
|
||||
if (CollUtil.isNotEmpty(singleRows)) {
|
||||
try {
|
||||
int[] c = upsertSingles(singleRows, merchantId, deptId, defaultCategoryId, categoryByName, cover,
|
||||
int[] c = upsertSingles(singleRows, merchantId, deptId, defaultCategoryId, categoryByName, mode,
|
||||
errors, cache, pendingUpdates);
|
||||
created += c[0];
|
||||
updated += c[1];
|
||||
@@ -299,8 +315,11 @@ public class CanteenSpuImportHelper {
|
||||
}
|
||||
String msg = String.format("导入完成:新增 %d,更新 %d,跳过 %d,价格已改 %d", created, updated, skipped,
|
||||
priceChanged);
|
||||
if (!cover && skipped > 0) {
|
||||
msg += ";当前为「新增导入」,同名已跳过。改价格请选「覆盖导入」";
|
||||
if (force) {
|
||||
msg += ";当前为「不覆盖导入」,同名套餐/单品均已新增(分类仍复用)";
|
||||
}
|
||||
else if (!cover && skipped > 0) {
|
||||
msg += ";当前为「新增导入」,同名已跳过。改价格请选「覆盖导入」;同名也要新增请选「不覆盖导入」";
|
||||
}
|
||||
if (cover && singlePriceMissing > 0 && singlePriceParsed == 0) {
|
||||
msg += ";警告:单品行均未读到「菜品单价(元)」,请确认第4列有数值";
|
||||
@@ -477,8 +496,10 @@ public class CanteenSpuImportHelper {
|
||||
|
||||
/** @return [created, updated, skipped, priceChanged] */
|
||||
private int[] upsertSingles(List<CanteenSpuImportExcel> items, Long merchantId, Long deptId,
|
||||
Long defaultCategoryId, Map<String, Long> categoryByName, boolean cover, List<String> errors,
|
||||
Long defaultCategoryId, Map<String, Long> categoryByName, String mode, List<String> errors,
|
||||
ImportCache cache, List<CanteenSpuEntity> pendingUpdates) {
|
||||
boolean cover = MODE_COVER.equals(mode);
|
||||
boolean force = MODE_FORCE.equals(mode);
|
||||
int created = 0;
|
||||
int updated = 0;
|
||||
int skipped = 0;
|
||||
@@ -487,7 +508,7 @@ public class CanteenSpuImportHelper {
|
||||
try {
|
||||
Long categoryId = requireOrCreateCategory(item, defaultCategoryId, categoryByName, merchantId,
|
||||
deptId);
|
||||
List<CanteenSpuEntity> exists = resolveDishes(merchantId, item, cache);
|
||||
List<CanteenSpuEntity> exists = force ? List.of() : resolveDishes(merchantId, item, cache);
|
||||
if (CollUtil.isNotEmpty(exists)) {
|
||||
if (!cover) {
|
||||
skipped++;
|
||||
@@ -513,7 +534,9 @@ public class CanteenSpuImportHelper {
|
||||
CanteenSpuEntity spu = newDish(merchantId, deptId, categoryId, item);
|
||||
canteenSpuService.save(spu);
|
||||
createStock(spu);
|
||||
cache.put(spu);
|
||||
if (!force) {
|
||||
cache.put(spu);
|
||||
}
|
||||
created++;
|
||||
if (resolveDishPriceFen(item) != null) {
|
||||
priceChanged++;
|
||||
@@ -529,9 +552,11 @@ public class CanteenSpuImportHelper {
|
||||
|
||||
/** @return [created, updated, skipped, priceChanged] */
|
||||
private int[] upsertCombo(String comboName, List<CanteenSpuImportExcel> items, Long merchantId, Long deptId,
|
||||
Long defaultCategoryId, Map<String, Long> categoryByName, boolean cover, List<String> errors,
|
||||
Long defaultCategoryId, Map<String, Long> categoryByName, String mode, List<String> errors,
|
||||
ImportCache cache, List<CanteenSpuEntity> pendingUpdates, Set<Long> standaloneDishIds,
|
||||
Set<String> standaloneNames) {
|
||||
boolean cover = MODE_COVER.equals(mode);
|
||||
boolean force = MODE_FORCE.equals(mode);
|
||||
List<CanteenSpuEntity> children = new ArrayList<>();
|
||||
int created = 0;
|
||||
int updated = 0;
|
||||
@@ -541,7 +566,7 @@ public class CanteenSpuImportHelper {
|
||||
try {
|
||||
Long categoryId = requireOrCreateCategory(item, defaultCategoryId, categoryByName, merchantId,
|
||||
deptId);
|
||||
List<CanteenSpuEntity> exists = resolveDishes(merchantId, item, cache);
|
||||
List<CanteenSpuEntity> exists = force ? List.of() : resolveDishes(merchantId, item, cache);
|
||||
if (CollUtil.isNotEmpty(exists)) {
|
||||
CanteenSpuEntity exist = exists.get(0);
|
||||
boolean dishOwnedBySingleRow = standaloneDishIds.contains(exist.getId())
|
||||
@@ -570,7 +595,9 @@ public class CanteenSpuImportHelper {
|
||||
CanteenSpuEntity spu = newDish(merchantId, deptId, categoryId, item);
|
||||
canteenSpuService.save(spu);
|
||||
createStock(spu);
|
||||
cache.put(spu);
|
||||
if (!force) {
|
||||
cache.put(spu);
|
||||
}
|
||||
children.add(spu);
|
||||
created++;
|
||||
if (resolveDishPriceFen(item) != null) {
|
||||
@@ -604,7 +631,7 @@ public class CanteenSpuImportHelper {
|
||||
comboItems.add(line);
|
||||
}
|
||||
|
||||
CanteenSpuEntity existCombo = resolveCombo(merchantId, comboName, first.getComboId(), cache);
|
||||
CanteenSpuEntity existCombo = force ? null : resolveCombo(merchantId, comboName, first.getComboId(), cache);
|
||||
if (existCombo != null) {
|
||||
if (!cover) {
|
||||
skipped++;
|
||||
@@ -654,7 +681,9 @@ public class CanteenSpuImportHelper {
|
||||
combo.setComboItems(comboItems);
|
||||
canteenSpuService.saveDeep(combo);
|
||||
createStock(combo);
|
||||
cache.put(combo);
|
||||
if (!force) {
|
||||
cache.put(combo);
|
||||
}
|
||||
created++;
|
||||
if (comboPriceFen != null) {
|
||||
priceChanged++;
|
||||
@@ -663,6 +692,20 @@ public class CanteenSpuImportHelper {
|
||||
return new int[] { created, updated, skipped, priceChanged };
|
||||
}
|
||||
|
||||
private static String normalizeImportMode(String importMode) {
|
||||
if (StrUtil.isBlank(importMode)) {
|
||||
return MODE_SKIP;
|
||||
}
|
||||
String m = importMode.trim().toLowerCase();
|
||||
if (MODE_COVER.equals(m) || "true".equals(m) || "1".equals(m)) {
|
||||
return MODE_COVER;
|
||||
}
|
||||
if (MODE_FORCE.equals(m) || "always".equals(m) || "duplicate".equals(m)) {
|
||||
return MODE_FORCE;
|
||||
}
|
||||
return MODE_SKIP;
|
||||
}
|
||||
|
||||
/** 单品单价:菜品单价优先;为空时用市场价 */
|
||||
private static Integer resolveDishPriceFen(CanteenSpuImportExcel item) {
|
||||
Integer dish = toFen(item.getPriceYuan());
|
||||
|
||||
Reference in new issue
Block a user