|
@@ -2,33 +2,51 @@ package cn.iocoder.yudao.module.system.service.restaurant;
|
|
|
|
|
|
|
|
import cn.hutool.core.collection.CollectionUtil;
|
|
import cn.hutool.core.collection.CollectionUtil;
|
|
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
|
|
|
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
|
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
|
|
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
|
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
|
|
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
|
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
|
|
|
|
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
|
|
|
import cn.iocoder.yudao.module.system.controller.admin.restaurant.vo.CateringPlanPageReqVO;
|
|
import cn.iocoder.yudao.module.system.controller.admin.restaurant.vo.CateringPlanPageReqVO;
|
|
|
import cn.iocoder.yudao.module.system.controller.admin.restaurant.vo.CateringPlanRespVO;
|
|
import cn.iocoder.yudao.module.system.controller.admin.restaurant.vo.CateringPlanRespVO;
|
|
|
import cn.iocoder.yudao.module.system.controller.admin.restaurant.vo.CateringPlanSaveReqVO;
|
|
import cn.iocoder.yudao.module.system.controller.admin.restaurant.vo.CateringPlanSaveReqVO;
|
|
|
import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.CateringPlanDO;
|
|
import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.CateringPlanDO;
|
|
|
import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.CateringPlanItemDO;
|
|
import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.CateringPlanItemDO;
|
|
|
import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.DishesDO;
|
|
import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.DishesDO;
|
|
|
|
|
+import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.RestaurantManagementDO;
|
|
|
import cn.iocoder.yudao.module.system.dal.mysql.restaurant.CateringPlanItemMapper;
|
|
import cn.iocoder.yudao.module.system.dal.mysql.restaurant.CateringPlanItemMapper;
|
|
|
import cn.iocoder.yudao.module.system.dal.mysql.restaurant.CateringPlanMapper;
|
|
import cn.iocoder.yudao.module.system.dal.mysql.restaurant.CateringPlanMapper;
|
|
|
import cn.iocoder.yudao.module.system.dal.mysql.restaurant.DishesMapper;
|
|
import cn.iocoder.yudao.module.system.dal.mysql.restaurant.DishesMapper;
|
|
|
|
|
+import cn.iocoder.yudao.module.system.dal.mysql.restaurant.RestaurantManagementMapper;
|
|
|
|
|
+import cn.iocoder.yudao.module.system.util.ImportUtil;
|
|
|
import cn.iocoder.yudao.module.system.util.http.HttpClientUtil;
|
|
import cn.iocoder.yudao.module.system.util.http.HttpClientUtil;
|
|
|
import cn.iocoder.yudao.module.system.util.http.HttpClientResult;
|
|
import cn.iocoder.yudao.module.system.util.http.HttpClientResult;
|
|
|
|
|
+import com.alibaba.excel.EasyExcel;
|
|
|
|
|
+import com.alibaba.excel.context.AnalysisContext;
|
|
|
|
|
+import com.alibaba.excel.event.AnalysisEventListener;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
+import com.google.gson.Gson;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
import javax.annotation.Resource;
|
|
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
|
|
|
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
|
|
-import java.util.Date;
|
|
|
|
|
-import java.util.List;
|
|
|
|
|
|
|
+import java.io.IOException;
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
|
+import java.time.LocalDate;
|
|
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
|
|
+import java.time.format.DateTimeParseException;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 餐谱计划 Service 实现类
|
|
* 餐谱计划 Service 实现类
|
|
@@ -46,6 +64,8 @@ public class CateringPlanServiceImpl implements CateringPlanService {
|
|
|
@Resource
|
|
@Resource
|
|
|
private CateringPlanItemMapper cateringPlanItemMapper;
|
|
private CateringPlanItemMapper cateringPlanItemMapper;
|
|
|
|
|
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private RestaurantManagementMapper restaurantManagementMapper;
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public Long createCateringPlan(CateringPlanSaveReqVO createReqVO) {
|
|
public Long createCateringPlan(CateringPlanSaveReqVO createReqVO) {
|
|
@@ -195,6 +215,162 @@ public class CateringPlanServiceImpl implements CateringPlanService {
|
|
|
return respVO;
|
|
return respVO;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void exportImportTemplate(HttpServletResponse response) throws IOException {
|
|
|
|
|
+ List<List<String>> data = buildImportTemplateSampleData();
|
|
|
|
|
+ ExcelUtils.setResponseProperties(response, "餐饮计划导入模板.xlsx");
|
|
|
|
|
+ try (java.io.OutputStream outputStream = response.getOutputStream()) {
|
|
|
|
|
+ EasyExcel.write(outputStream)
|
|
|
|
|
+ .sheet("模板")
|
|
|
|
|
+ .doWrite(data);
|
|
|
|
|
+ outputStream.flush();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ @Transactional
|
|
|
|
|
+ public ImportResultVO importCateringPlan(MultipartFile file, Long restaurantId) throws Exception {
|
|
|
|
|
+ List<Map<Integer, String>> rawRows = new ArrayList<>();
|
|
|
|
|
+ EasyExcel.read(file.getInputStream(), new AnalysisEventListener<Map<Integer, String>>() {
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void invoke(Map<Integer, String> data, AnalysisContext context) {
|
|
|
|
|
+ rawRows.add(data);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void doAfterAllAnalysed(AnalysisContext context) {
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .autoCloseStream(true)
|
|
|
|
|
+ .sheet(0)
|
|
|
|
|
+ .headRowNumber(0)
|
|
|
|
|
+ .doRead();
|
|
|
|
|
+
|
|
|
|
|
+ int success = 0;
|
|
|
|
|
+ List<ImportResultVO.RowError> failures = new ArrayList<>();
|
|
|
|
|
+
|
|
|
|
|
+ if (rawRows.isEmpty()) {
|
|
|
|
|
+ return ImportUtil.buildResult(success, failures);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, String> meta = new HashMap<>();
|
|
|
|
|
+ List<CateringPlanItemDO> items = new ArrayList<>();
|
|
|
|
|
+ for (int i = 0; i < rawRows.size(); i++) {
|
|
|
|
|
+ Map<Integer, String> row = rawRows.get(i);
|
|
|
|
|
+ String col0 = getCell(row, 0);
|
|
|
|
|
+ String col1 = getCell(row, 1);
|
|
|
|
|
+ String nextCol0 = i+1 >= rawRows.size() ? "" :getCell(rawRows.get(i+1), 0);
|
|
|
|
|
+ if (i < 4) {
|
|
|
|
|
+ if (col0 != null) {
|
|
|
|
|
+ meta.put(col0.trim(), col1);
|
|
|
|
|
+ }
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(i == 4){
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (col0 == null && col1 == null) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ CateringPlanItemDO item = new CateringPlanItemDO();
|
|
|
|
|
+ item.setTenantId(TenantContextHolder.getTenantId());
|
|
|
|
|
+ item.setMealTimes(col0);
|
|
|
|
|
+ item.setMonday(parseDishes(col1));
|
|
|
|
|
+ item.setTuesday(parseDishes(getCell(row, 2)));
|
|
|
|
|
+ item.setWednesday(parseDishes(getCell(row, 3)));
|
|
|
|
|
+ item.setThursday(parseDishes(getCell(row, 4)));
|
|
|
|
|
+ item.setFriday(parseDishes(getCell(row, 5)));
|
|
|
|
|
+ item.setSaturday(parseDishes(getCell(row, 6)));
|
|
|
|
|
+ item.setSunday(parseDishes(getCell(row, 7)));
|
|
|
|
|
+ items.add(item);
|
|
|
|
|
+ if (isOptionalMeal(nextCol0)) {
|
|
|
|
|
+ Map<Integer, String> nextRow = rawRows.get(i + 1);
|
|
|
|
|
+ item.setMondayExtra(parseDishes(getCell(nextRow, 1)));
|
|
|
|
|
+ item.setTuesdayExtra(parseDishes(getCell(nextRow, 2)));
|
|
|
|
|
+ item.setWednesdayExtra(parseDishes(getCell(nextRow, 3)));
|
|
|
|
|
+ item.setThursdayExtra(parseDishes(getCell(nextRow, 4)));
|
|
|
|
|
+ item.setFridayExtra(parseDishes(getCell(nextRow, 5)));
|
|
|
|
|
+ item.setSaturdayExtra(parseDishes(getCell(nextRow, 6)));
|
|
|
|
|
+ item.setSundayExtra(parseDishes(getCell(nextRow, 7)));
|
|
|
|
|
+ i++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (items.isEmpty()) {
|
|
|
|
|
+ ImportUtil.addFailure(failures, 7, null, null, "未读取到餐次明细");
|
|
|
|
|
+ return ImportUtil.buildResult(success, failures);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ CateringPlanDO cateringPlan = buildCateringPlan(meta, restaurantId, failures);
|
|
|
|
|
+ if (!failures.isEmpty()) {
|
|
|
|
|
+ return ImportUtil.buildResult(success, failures);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ensureDishesExists(items, cateringPlan, failures);
|
|
|
|
|
+ if (!failures.isEmpty()) {
|
|
|
|
|
+ return ImportUtil.buildResult(success, failures);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ cateringPlanMapper.insert(cateringPlan);
|
|
|
|
|
+ for (CateringPlanItemDO item : items) {
|
|
|
|
|
+ item.setCateringPlanId(cateringPlan.getId());
|
|
|
|
|
+ cateringPlanItemMapper.insert(item);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ invokeWechatInterface(cateringPlan.getRestaurantId(), cateringPlan.getRestaurantName());
|
|
|
|
|
+ success = 1;
|
|
|
|
|
+ return ImportUtil.buildResult(success, failures);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private LocalDate parseDate(String value, List<ImportResultVO.RowError> failures) {
|
|
|
|
|
+ List<DateTimeFormatter> patterns = Arrays.asList(
|
|
|
|
|
+ DateTimeFormatter.ofPattern("yyyy/M/d"),
|
|
|
|
|
+ DateTimeFormatter.ofPattern("yyyy-MM-dd"),
|
|
|
|
|
+ DateTimeFormatter.ofPattern("yyyy/MM/dd"),
|
|
|
|
|
+ DateTimeFormatter.ofPattern("yyyy.M.d")
|
|
|
|
|
+ );
|
|
|
|
|
+ for (DateTimeFormatter formatter : patterns) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ return LocalDate.parse(value, formatter);
|
|
|
|
|
+ } catch (DateTimeParseException ignored) {
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ImportUtil.addFailure(failures, 1, null, null, "计划开始日期格式不正确");
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private String getCell(Map<Integer, String> row, int index) {
|
|
|
|
|
+ String value = row.get(index);
|
|
|
|
|
+ return value != null ? value.trim() : null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 格式化菜品字符串
|
|
|
|
|
+ * @param dishes
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ private String parseDishes(String dishes){
|
|
|
|
|
+ if(StringUtils.isBlank(dishes)){
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+ return new Gson().toJson(dishes.split("、"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private List<List<String>> buildImportTemplateSampleData() {
|
|
|
|
|
+ List<List<String>> data = new ArrayList<>();
|
|
|
|
|
+ data.add(Arrays.asList("计划开始日期", ""));
|
|
|
|
|
+ data.add(Arrays.asList("计划名称", ""));
|
|
|
|
|
+ data.add(Arrays.asList("餐谱说明", ""));
|
|
|
|
|
+ data.add(Arrays.asList("上墙备注", ""));
|
|
|
|
|
+ data.add(Arrays.asList("餐次", "周一", "周二", "周三", "周四", "周五", "周六", "周日"));
|
|
|
|
|
+ data.add(Arrays.asList("早餐", "", "", "", "", "", "", ""));
|
|
|
|
|
+ data.add(Arrays.asList("中餐", "", "", "", "", "", "", ""));
|
|
|
|
|
+ data.add(Arrays.asList("中餐(可选)", "", "", "", "", "", "", ""));
|
|
|
|
|
+ data.add(Arrays.asList("晚餐", "", "", "", "", "", "", ""));
|
|
|
|
|
+ return data;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
private void invokeWechatInterface(Long restaurantId,String restaurantName){
|
|
private void invokeWechatInterface(Long restaurantId,String restaurantName){
|
|
|
// 调用外部接口更新餐厅周菜单
|
|
// 调用外部接口更新餐厅周菜单
|
|
|
try {
|
|
try {
|
|
@@ -220,4 +396,109 @@ public class CateringPlanServiceImpl implements CateringPlanService {
|
|
|
log.error("调用更新餐厅周菜单接口异常:{}", e.getMessage(), e);
|
|
log.error("调用更新餐厅周菜单接口异常:{}", e.getMessage(), e);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
+
|
|
|
|
|
+ private CateringPlanDO buildCateringPlan(Map<String, String> meta, Long restaurantId, List<ImportResultVO.RowError> failures) {
|
|
|
|
|
+ String startDateStr = meta.get("计划开始日期");
|
|
|
|
|
+ String planName = meta.get("计划名称");
|
|
|
|
|
+ String description = meta.get("餐谱说明");
|
|
|
|
|
+ String remarks = meta.get("上墙备注");
|
|
|
|
|
+
|
|
|
|
|
+ if (startDateStr == null) {
|
|
|
|
|
+ ImportUtil.addFailure(failures, 1, null, null, "计划开始日期不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (planName == null) {
|
|
|
|
|
+ ImportUtil.addFailure(failures, 2, null, null, "计划名称不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!failures.isEmpty()) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ LocalDate startDate = parseDate(startDateStr.trim(), failures);
|
|
|
|
|
+ if (startDate == null) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ CateringPlanDO cateringPlan = new CateringPlanDO();
|
|
|
|
|
+ cateringPlan.setRestaurantId(restaurantId);
|
|
|
|
|
+ RestaurantManagementDO restaurant = restaurantManagementMapper.selectById(restaurantId);
|
|
|
|
|
+ if (restaurant != null) {
|
|
|
|
|
+ cateringPlan.setRestaurantName(restaurant.getRestaurantName());
|
|
|
|
|
+ }
|
|
|
|
|
+ cateringPlan.setScheduledStartDate(startDate);
|
|
|
|
|
+ cateringPlan.setScheduledEndDate(startDate.plusDays(6));
|
|
|
|
|
+ cateringPlan.setPlanName(planName);
|
|
|
|
|
+ cateringPlan.setDescription(description);
|
|
|
|
|
+ cateringPlan.setRemarks(remarks);
|
|
|
|
|
+ cateringPlan.setCreatedTime(new Date());
|
|
|
|
|
+ cateringPlan.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
|
|
|
|
|
+ cateringPlan.setTenantId(TenantContextHolder.getTenantId());
|
|
|
|
|
+ return cateringPlan;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void ensureDishesExists(List<CateringPlanItemDO> items, CateringPlanDO cateringPlan, List<ImportResultVO.RowError> failures) {
|
|
|
|
|
+ Map<String, DishesDO> existing = dishesMapper.selectList(new LambdaQueryWrapperX<DishesDO>()
|
|
|
|
|
+ .eq(DishesDO::getTenantId, TenantContextHolder.getTenantId())
|
|
|
|
|
+ .eq(DishesDO::getRestaurantId, cateringPlan.getRestaurantId()))
|
|
|
|
|
+ .stream()
|
|
|
|
|
+ .collect(java.util.stream.Collectors.toMap(DishesDO::getFoodName, item -> item, (a, b) -> a));
|
|
|
|
|
+
|
|
|
|
|
+ Set<String> toCreate = new LinkedHashSet<>();
|
|
|
|
|
+ for (CateringPlanItemDO item : items) {
|
|
|
|
|
+ collectDishes(item.getMonday(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getTuesday(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getWednesday(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getThursday(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getFriday(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getSaturday(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getSunday(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getMondayExtra(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getTuesdayExtra(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getWednesdayExtra(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getThursdayExtra(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getFridayExtra(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getSaturdayExtra(), toCreate, existing);
|
|
|
|
|
+ collectDishes(item.getSundayExtra(), toCreate, existing);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (String foodName : toCreate) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ DishesDO dishes = new DishesDO();
|
|
|
|
|
+ dishes.setFoodName(foodName);
|
|
|
|
|
+ dishes.setRestaurantId(cateringPlan.getRestaurantId());
|
|
|
|
|
+ dishes.setRestaurantName(cateringPlan.getRestaurantName());
|
|
|
|
|
+ dishes.setTenantId(TenantContextHolder.getTenantId());
|
|
|
|
|
+ dishes.setPrice(BigDecimal.ZERO);
|
|
|
|
|
+ dishes.setStatus(1);
|
|
|
|
|
+ dishes.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
|
|
|
|
|
+ dishes.setCreatedTime(new Date());
|
|
|
|
|
+ dishesMapper.insert(dishes);
|
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
|
+ ImportUtil.addFailure(failures, 1, null, null, "自动创建菜品失败:" + foodName, ex);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void collectDishes(String value, Set<String> toCreate, Map<String, DishesDO> existing) {
|
|
|
|
|
+ if (value == null || value.isEmpty()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ String normalized = value.replace(",", ",");
|
|
|
|
|
+ for (String name : normalized.split(",")) {
|
|
|
|
|
+ String trimmed = name.trim();
|
|
|
|
|
+ if (trimmed.isEmpty()) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!existing.containsKey(trimmed)) {
|
|
|
|
|
+ toCreate.add(trimmed);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean isOptionalMeal(String mealTimes) {
|
|
|
|
|
+ if (mealTimes == null) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ String normalized = mealTimes.replace("(", "(").replace(")", ")");
|
|
|
|
|
+ return normalized.contains("(可选)") || normalized.contains("可选");
|
|
|
|
|
+ }
|
|
|
|
|
+}
|