|
|
@@ -66,6 +66,13 @@ public class PosFoodController extends BaseController {
|
|
|
@Autowired
|
|
|
private PosStoreEnrichService posStoreEnrichService;
|
|
|
|
|
|
+ @Autowired //规格组
|
|
|
+ private IFoodSpecsService foodSpecsService;
|
|
|
+ @Autowired //规格值
|
|
|
+ private IFoodSpecsValueService foodSpecsValueService;
|
|
|
+ @Autowired //商品-规格关联
|
|
|
+ private IFoodSpecRelationService foodSpecRelationService;
|
|
|
+
|
|
|
//删除商品
|
|
|
@Anonymous
|
|
|
@Auth
|
|
|
@@ -87,14 +94,12 @@ public class PosFoodController extends BaseController {
|
|
|
@Anonymous
|
|
|
@PostMapping("/setposfood")
|
|
|
public AjaxResult setposfood(@RequestBody PosFood posFood) {
|
|
|
- JSONArray jsonArray = posFood.getSku();
|
|
|
- posFood.setFoodSku(jsonArray.toString());
|
|
|
Boolean org = posFoodService.saveOrUpdate(posFood);
|
|
|
- if (org) {
|
|
|
- return success();
|
|
|
- } else {
|
|
|
+ if (!org) {
|
|
|
return error();
|
|
|
}
|
|
|
+ handleFoodSpec(posFood);
|
|
|
+ return success();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -120,6 +125,8 @@ public class PosFoodController extends BaseController {
|
|
|
}
|
|
|
queryWrapper.eq("language", lang);
|
|
|
List<PosFood> list = posFoodService.list(queryWrapper);
|
|
|
+ List<Long> __foodIds = list.stream().map(PosFood::getId).collect(Collectors.toList());
|
|
|
+ Map<Long, List<FoodSpecs>> __specMap = loadFoodSpecsMap(__foodIds);
|
|
|
JSONArray all = new JSONArray();
|
|
|
for (int i = 0; i < list.size(); i++) {
|
|
|
JSONObject org = new JSONObject();
|
|
|
@@ -131,7 +138,9 @@ public class PosFoodController extends BaseController {
|
|
|
org.put("price", list.get(i).getPrice());
|
|
|
org.put("introduce", list.get(i).getIntroduce());
|
|
|
org.put("recommend", list.get(i).getRecommend());
|
|
|
- org.put("foodSku", JSONArray.parseArray(list.get(i).getFoodSku()));
|
|
|
+ List<FoodSpecs> __fs = __specMap.getOrDefault(list.get(i).getId(), new ArrayList<>());
|
|
|
+ org.put("foodSpecs", __fs);
|
|
|
+ org.put("foodSku", __fs.isEmpty() ? JSONArray.parseArray(list.get(i).getFoodSku()) : buildFoodSkuArray(__fs));
|
|
|
org.put("stackingUp", list.get(i).getStackingUp());
|
|
|
org.put("toExamine", list.get(i).getToExamine());
|
|
|
all.add(org);
|
|
|
@@ -166,6 +175,8 @@ public class PosFoodController extends BaseController {
|
|
|
queryWrapper.apply(" BINARY name LIKE CONCAT('%', {0}, '%')", name);
|
|
|
}
|
|
|
List<PosFood> list = posFoodService.list(queryWrapper);
|
|
|
+ List<Long> __foodIds = list.stream().map(PosFood::getId).collect(Collectors.toList());
|
|
|
+ Map<Long, List<FoodSpecs>> __specMap = loadFoodSpecsMap(__foodIds);
|
|
|
JSONArray all = new JSONArray();
|
|
|
for (int i = 0; i < list.size(); i++) {
|
|
|
JSONObject org = new JSONObject();
|
|
|
@@ -179,7 +190,9 @@ public class PosFoodController extends BaseController {
|
|
|
org.put("price", list.get(i).getPrice());
|
|
|
org.put("introduce", list.get(i).getIntroduce());
|
|
|
org.put("recommend", list.get(i).getRecommend());
|
|
|
- org.put("foodSku", JSONArray.parseArray(list.get(i).getFoodSku()));
|
|
|
+ List<FoodSpecs> __fs = __specMap.getOrDefault(list.get(i).getId(), new ArrayList<>());
|
|
|
+ org.put("foodSpecs", __fs);
|
|
|
+ org.put("foodSku", __fs.isEmpty() ? JSONArray.parseArray(list.get(i).getFoodSku()) : buildFoodSkuArray(__fs));
|
|
|
org.put("stackingUp", list.get(i).getStackingUp());
|
|
|
org.put("toExamine", list.get(i).getToExamine());
|
|
|
all.add(org);
|
|
|
@@ -195,6 +208,10 @@ public class PosFoodController extends BaseController {
|
|
|
public AjaxResult getfood(@RequestParam Integer id) {
|
|
|
JSONObject org = new JSONObject();
|
|
|
PosFood posFood = posFoodService.getById(id);
|
|
|
+ List<Long> __foodIds = new ArrayList<>();
|
|
|
+ __foodIds.add(posFood.getId());
|
|
|
+ Map<Long, List<FoodSpecs>> __specMap = loadFoodSpecsMap(__foodIds);
|
|
|
+ List<FoodSpecs> __fs = __specMap.getOrDefault(posFood.getId(), new ArrayList<>());
|
|
|
org.put("id", posFood.getId());
|
|
|
org.put("fenlei", posFenleiService.getById(posFood.getFlId()));
|
|
|
PosStore store = posStoreService.getById(posFood.getMdid());
|
|
|
@@ -206,7 +223,8 @@ public class PosFoodController extends BaseController {
|
|
|
org.put("introduce", posFood.getIntroduce());
|
|
|
org.put("recommend", posFood.getRecommend());
|
|
|
org.put("stackingUp", posFood.getStackingUp());
|
|
|
- org.put("foodSku", JSONArray.parseArray(posFood.getFoodSku()));
|
|
|
+ org.put("foodSpecs", __fs);
|
|
|
+ org.put("foodSku", __fs.isEmpty() ? JSONArray.parseArray(posFood.getFoodSku()) : buildFoodSkuArray(__fs));
|
|
|
return success(org);
|
|
|
}
|
|
|
|
|
|
@@ -314,6 +332,13 @@ public class PosFoodController extends BaseController {
|
|
|
.apply(" CONCAT(name, ' ') LIKE CONCAT('%', {0}, '%') COLLATE utf8mb4_unicode_ci", keyword);
|
|
|
|
|
|
List<PosFood> allFoods = posFoodService.list(foodQuery);
|
|
|
+ {
|
|
|
+ List<Long> __foodIds = allFoods.stream().map(PosFood::getId).collect(Collectors.toList());
|
|
|
+ Map<Long, List<FoodSpecs>> __specMap = loadFoodSpecsMap(__foodIds);
|
|
|
+ for (PosFood __f : allFoods) {
|
|
|
+ __f.setFoodSpecs(__specMap.getOrDefault(__f.getId(), new ArrayList<>()));
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
// 按店铺ID分组商品
|
|
|
Map<Long, List<PosFood>> foodsByStore = allFoods.stream()
|
|
|
@@ -441,6 +466,11 @@ public class PosFoodController extends BaseController {
|
|
|
queryWrapper.eq("fl_id", flId);
|
|
|
}
|
|
|
IPage<PosFood> result = posFoodService.page(foodPage, queryWrapper);
|
|
|
+ List<Long> __foodIds = result.getRecords().stream().map(PosFood::getId).collect(Collectors.toList());
|
|
|
+ Map<Long, List<FoodSpecs>> __specMap = loadFoodSpecsMap(__foodIds);
|
|
|
+ for (PosFood __f : result.getRecords()) {
|
|
|
+ __f.setFoodSpecs(__specMap.getOrDefault(__f.getId(), new ArrayList<>()));
|
|
|
+ }
|
|
|
return success(result);
|
|
|
}
|
|
|
|
|
|
@@ -527,7 +557,11 @@ public class PosFoodController extends BaseController {
|
|
|
@Log(title = "food", businessType = BusinessType.INSERT)
|
|
|
@PostMapping
|
|
|
public AjaxResult add(@RequestBody PosFood posFood) {
|
|
|
- return toAjax(posFoodService.insertPosFood(posFood));
|
|
|
+ int rows = posFoodService.insertPosFood(posFood);
|
|
|
+ if (rows > 0) {
|
|
|
+ handleFoodSpec(posFood);
|
|
|
+ }
|
|
|
+ return toAjax(rows);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -537,7 +571,11 @@ public class PosFoodController extends BaseController {
|
|
|
@Log(title = "food", businessType = BusinessType.UPDATE)
|
|
|
@PutMapping
|
|
|
public AjaxResult edit(@RequestBody PosFood posFood) {
|
|
|
- return toAjax(posFoodService.updatePosFood(posFood));
|
|
|
+ int rows = posFoodService.updatePosFood(posFood);
|
|
|
+ if (rows > 0) {
|
|
|
+ handleFoodSpec(posFood);
|
|
|
+ }
|
|
|
+ return toAjax(rows);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -611,6 +649,112 @@ public class PosFoodController extends BaseController {
|
|
|
/**
|
|
|
* 当门店是摊位时,用夜市的经纬度覆盖摊位的经纬度
|
|
|
*/
|
|
|
+ /**
|
|
|
+ * 保存商品规格:sku JSON 写 food_sku(落库) -> 删除旧关联 -> 按 foodSpecs 建立新关联
|
|
|
+ */
|
|
|
+ private void handleFoodSpec(PosFood posFood) {
|
|
|
+ if (posFood == null || posFood.getId() == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ JSONArray sku = posFood.getSku();
|
|
|
+ if (sku != null) {
|
|
|
+ PosFood upd = new PosFood();
|
|
|
+ upd.setId(posFood.getId());
|
|
|
+ upd.setFoodSku(sku.toString());
|
|
|
+ posFoodService.updateById(upd);
|
|
|
+ posFood.setFoodSku(sku.toString());
|
|
|
+ }
|
|
|
+ foodSpecRelationService.remove(new LambdaQueryWrapper<FoodSpecRelation>()
|
|
|
+ .eq(FoodSpecRelation::getFoodId, posFood.getId()));
|
|
|
+ List<FoodSpecs> foodSpecs = posFood.getFoodSpecs();
|
|
|
+ if (foodSpecs != null && !foodSpecs.isEmpty()) {
|
|
|
+ List<FoodSpecRelation> rels = foodSpecs.stream()
|
|
|
+ .filter(sp -> sp.getId() != null && sp.getId() > 0)
|
|
|
+ .map(sp -> {
|
|
|
+ FoodSpecRelation r = new FoodSpecRelation();
|
|
|
+ r.setFoodId(posFood.getId());
|
|
|
+ r.setSpecsId(sp.getId());
|
|
|
+ return r;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ if (!rels.isEmpty()) {
|
|
|
+ foodSpecRelationService.saveBatch(rels);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量查询商品规格(避免 N+1):关联 -> 启用规格组 -> 启用规格值 -> 内存分组
|
|
|
+ * @return foodId -> 规格组列表(含启用规格值)
|
|
|
+ */
|
|
|
+ private Map<Long, List<FoodSpecs>> loadFoodSpecsMap(List<Long> foodIds) {
|
|
|
+ Map<Long, List<FoodSpecs>> result = new HashMap<>();
|
|
|
+ if (foodIds == null || foodIds.isEmpty()) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ List<FoodSpecRelation> rels = foodSpecRelationService.list(new LambdaQueryWrapper<FoodSpecRelation>()
|
|
|
+ .in(FoodSpecRelation::getFoodId, foodIds));
|
|
|
+ if (rels.isEmpty()) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ Map<Long, List<Long>> foodToSpecIds = rels.stream()
|
|
|
+ .collect(Collectors.groupingBy(FoodSpecRelation::getFoodId,
|
|
|
+ Collectors.mapping(FoodSpecRelation::getSpecsId, Collectors.toList())));
|
|
|
+ List<Long> specsIds = rels.stream().map(FoodSpecRelation::getSpecsId).distinct().collect(Collectors.toList());
|
|
|
+ List<FoodSpecs> specsList = foodSpecsService.list(new LambdaQueryWrapper<FoodSpecs>()
|
|
|
+ .in(FoodSpecs::getId, specsIds)
|
|
|
+ .eq(FoodSpecs::getIsOpen, true)
|
|
|
+ .eq(FoodSpecs::getIsDelete, false)
|
|
|
+ .orderByAsc(FoodSpecs::getSort));
|
|
|
+ if (specsList.isEmpty()) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ List<Long> enabledSpecIds = specsList.stream().map(FoodSpecs::getId).collect(Collectors.toList());
|
|
|
+ List<FoodSpecsValue> values = foodSpecsValueService.list(new LambdaQueryWrapper<FoodSpecsValue>()
|
|
|
+ .in(FoodSpecsValue::getParentId, enabledSpecIds)
|
|
|
+ .eq(FoodSpecsValue::getIsOpen, true)
|
|
|
+ .orderByAsc(FoodSpecsValue::getId));
|
|
|
+ Map<Long, List<FoodSpecsValue>> valueMap = values.stream()
|
|
|
+ .collect(Collectors.groupingBy(FoodSpecsValue::getParentId));
|
|
|
+ Map<Long, FoodSpecs> specsMap = specsList.stream().collect(Collectors.toMap(FoodSpecs::getId, sp -> sp));
|
|
|
+ for (Map.Entry<Long, List<Long>> entry : foodToSpecIds.entrySet()) {
|
|
|
+ List<FoodSpecs> fsList = new ArrayList<>();
|
|
|
+ for (Long sid : entry.getValue()) {
|
|
|
+ FoodSpecs src = specsMap.get(sid);
|
|
|
+ if (src != null) {
|
|
|
+ FoodSpecs copy = new FoodSpecs();
|
|
|
+ copy.setId(src.getId());
|
|
|
+ copy.setTitle(src.getTitle());
|
|
|
+ copy.setType(src.getType());
|
|
|
+ copy.setState(src.getState());
|
|
|
+ copy.setLanguage(src.getLanguage());
|
|
|
+ copy.setRemark(src.getRemark());
|
|
|
+ copy.setMdId(src.getMdId());
|
|
|
+ copy.setSort(src.getSort());
|
|
|
+ copy.setIsOpen(src.getIsOpen());
|
|
|
+ copy.setIsDelete(src.getIsDelete());
|
|
|
+ copy.setFoodSpecsItems(valueMap.getOrDefault(src.getId(), new ArrayList<>()));
|
|
|
+ fsList.add(copy);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ result.put(entry.getKey(), fsList);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 由结构化规格构建兼容的 food_sku JSON 数组(明细字段名 foodSpecsItems)
|
|
|
+ */
|
|
|
+ private JSONArray buildFoodSkuArray(List<FoodSpecs> fsList) {
|
|
|
+ JSONArray skuArr = new JSONArray();
|
|
|
+ if (fsList == null || fsList.isEmpty()) {
|
|
|
+ return skuArr;
|
|
|
+ }
|
|
|
+ for (FoodSpecs s : fsList) {
|
|
|
+ skuArr.add(JSONObject.toJSON(s));
|
|
|
+ }
|
|
|
+ return skuArr;
|
|
|
+ }
|
|
|
+
|
|
|
private void fillStallLocation(PosStore store) {
|
|
|
if (store != null && store.getIsStall() != null && store.getIsStall() == 1
|
|
|
&& store.getNightMarketId() != null) {
|