Parcourir la source

添加pos的预约和联台等功能。添加pos点单套餐功能。修改点套餐的销售报表功能

许智捷 il y a 2 ans
Parent
commit
47c598ade8
27 fichiers modifiés avec 1237 ajouts et 279 suppressions
  1. 13 5
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/kc/entity/KcDepositoryInGoods.java
  2. 32 2
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/kc/mapper/xml/KcDepositoryInGoodsMapper.xml
  3. 3 4
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/kc/service/impl/KcDepositoryInGoodsServiceImpl.java
  4. 13 34
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/mall/controller/MallPosTableOrderGoodsController.java
  5. 55 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/PosBookingStateEnum.java
  6. 55 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/TableStateEnum.java
  7. 175 99
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/controller/PosOrderGoodsController.java
  8. 37 6
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/controller/PosOrderGoodsDetailController.java
  9. 10 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/controller/PosSellClearGoodsController.java
  10. 83 11
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/controller/PosTableController.java
  11. 17 31
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/controller/PosThaliController.java
  12. 101 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/entity/PosBookingOrder.java
  13. 30 13
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/entity/PosOrderGoods.java
  14. 14 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/entity/PosOrderGoodsDetail.java
  15. 5 2
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/entity/PosTable.java
  16. 6 1
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/entity/PosThali.java
  17. 7 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/mapper/PosBookingOrderMapper.java
  18. 7 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/mapper/PosOrderTeamMapper.java
  19. 9 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/mapper/PosThaliInGoodsMapper.java
  20. 14 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/IPosBookingService.java
  21. 25 1
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/IPosOrderGoodsService.java
  22. 8 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/IPosOrderTeamService.java
  23. 4 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/IPosThaliInGoodsService.java
  24. 50 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/impl/PosBookingOrderImpl.java
  25. 423 70
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/impl/PosOrderGoodsServiceImpl.java
  26. 34 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/impl/PosOrderTeamImpl.java
  27. 7 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/impl/PosThaliInGoodsServiceImpl.java

+ 13 - 5
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/kc/entity/KcDepositoryInGoods.java

@@ -27,7 +27,7 @@ import lombok.experimental.Accessors;
 @TableName("kc_depository_in_goods")
 @Accessors(chain = true)
 @EqualsAndHashCode(callSuper = false)
-@ApiModel(value="kc_depository_in_goods对象", description="kc_depository_in_goods")
+@ApiModel(value="kc_depository_in_goods对象", description="出入库商品")
 public class KcDepositoryInGoods implements Serializable {
     private static final long serialVersionUID = 1L;
 
@@ -51,6 +51,14 @@ public class KcDepositoryInGoods implements Serializable {
 	@Excel(name = "商品id", width = 15)
     @ApiModelProperty(value = "商品id")
     private String goodsId;
+	/**商品id*/
+	@Excel(name = "商品套餐id", width = 15)
+	@ApiModelProperty(value = "商品套餐id")
+	private String thaliId;
+	/**套餐出入库对象id*/
+	@Excel(name = "套餐出入库对象id", width = 15)
+	@ApiModelProperty(value = "套餐出入库对象id")
+	private String parentId;
 	/**总数*/
 	@Excel(name = "总数", width = 15)
     @ApiModelProperty(value = "总数")
@@ -61,13 +69,13 @@ public class KcDepositoryInGoods implements Serializable {
     private String stockDetailId;
 
 	/**费用单id*/
-	@Excel(name = "创建时间", width = 15)
-	@ApiModelProperty(value = "创建时间")
+	@Excel(name = "费用单id", width = 15)
+	@ApiModelProperty(value = "费用单id")
 	private String feeId;
 
 	/**费用单id*/
-	@Excel(name = "创建时间", width = 15)
-	@ApiModelProperty(value = "创建时间")
+	@Excel(name = "费用单id", width = 15)
+	@ApiModelProperty(value = "费用单id")
 	private String feeGoodId;
 
 	/**创建时间*/

+ 32 - 2
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/kc/mapper/xml/KcDepositoryInGoodsMapper.xml

@@ -48,6 +48,7 @@
 
     <select id="goodsSellDetailPage" resultType="org.jeecg.modules.kc.vo.GoodStorage">
         select * from (
+            /*客房商品销售*/
             SELECT cg.id as good_id, cg.name as good_name,kdig.num,kdig.create_time,kdig.fee_id,kdig.fee_good_id,
                    bof.money,concat(cr.prefix,cr.name) as room_sign,
                    cst.name AS good_type_name,'客房' as place_name, '1' as place_id
@@ -59,6 +60,7 @@
             inner JOIN ces_stock_type cst ON cst.id = cg.good_type
             where kdig.stock_detail_id is null
             UNION ALL
+            /*pos商品销售*/
             SELECT cg.id as good_id,cg.name as good_name,kdig.num,kdig.create_time,kdig.fee_id,kdig.fee_good_id,
                    pogd.money*pogd.num as money, pog.table_no as room_sign,
                    cst.name AS good_type_name,pt.name as place_name, pt.id as place_id
@@ -66,10 +68,24 @@
             inner join pos_order_goods_detail pogd on pogd.id  = kdig.fee_good_id
             inner join pos_order_goods pog on pog.code = pogd.order_id
             inner join pos_type pt on pt.id = pog.pos_type
-            inner JOIN ces_goods cg ON cg.id = kdig.goods_id
+            left JOIN ces_goods cg ON cg.id = kdig.goods_id
             inner JOIN ces_goods_unit cgu ON cgu.id = cg.good_unit
             inner JOIN ces_stock_type cst ON cst.id = cg.good_type
-            where kdig.stock_detail_id is null) t
+            where kdig.stock_detail_id is null and kdig.parent_id is null
+            UNION ALL
+            /*pos套餐销售*/
+            SELECT thali.id as good_id,thali.name as good_name,kdig.num,kdig.create_time,kdig.fee_id,kdig.fee_good_id,
+                pogd.money*pogd.num as money, pog.table_no as room_sign,
+                cst.name AS good_type_name,pt.name as place_name, pt.id as place_id
+            from kc_depository_in_goods kdig
+            inner join pos_order_goods_detail pogd on pogd.id  = kdig.fee_good_id
+            inner join pos_order_goods pog on pog.code = pogd.order_id
+            inner join pos_type pt on pt.id = pog.pos_type
+            inner join pos_thali thali on thali.id = kdig.thali_id
+            --             inner JOIN ces_goods_unit cgu ON cgu.id = cg.good_unit
+            inner JOIN ces_stock_type cst ON cst.id = thali.thail_type
+            where kdig.stock_detail_id is null and kdig.parent_id is null
+            ) t
         where 1=1
         <if test='goodStorage.startTime != null'> and create_time &gt;= #{goodStorage.startTime} </if>
         <if test='goodStorage.endTime != null'> and create_time &lt; #{goodStorage.endTime} </if>
@@ -108,6 +124,20 @@
                 where kdig.stock_detail_id is null
                 <if test='goodStorage.startTime != null'> and kdig.create_time &gt;= #{goodStorage.startTime} </if>
                 <if test='goodStorage.endTime != null'> and kdig.create_time &lt; #{goodStorage.endTime} </if>
+            UNION ALL
+            SELECT thali.id as good_id, thali.name as good_name,
+                kdig.num as num,pogd.money*pogd.num as money,pog.table_no as room_sign,
+                cst.name AS good_type_name,pt.name as place_name,pt.id as place_id
+                from kc_depository_in_goods kdig
+                inner join pos_order_goods_detail pogd on pogd.id  = kdig.fee_good_id
+                inner join pos_order_goods pog on pog.code = pogd.order_id
+                inner join pos_type pt on pt.id = pog.pos_type
+                inner join pos_thali thali on thali.id = kdig.thali_id
+                --  inner JOIN ces_goods_unit cgu ON cgu.id = cg.good_unit
+                inner JOIN ces_stock_type cst ON cst.id = thali.thail_type
+                where kdig.stock_detail_id is null and kdig.parent_id is null
+                <if test='goodStorage.startTime != null'> and kdig.create_time &gt;= #{goodStorage.startTime} </if>
+                <if test='goodStorage.endTime != null'> and kdig.create_time &lt; #{goodStorage.endTime} </if>
         ) t
         where 1=1
         <if test="goodStorage.roomSign != null and goodStorage.roomSign != ''">and room_sign like concat('%',#{goodStorage.roomSign},'%') </if>

+ 3 - 4
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/kc/service/impl/KcDepositoryInGoodsServiceImpl.java

@@ -37,9 +37,6 @@ public class KcDepositoryInGoodsServiceImpl extends ServiceImpl<KcDepositoryInGo
 
     /**
      * 仓库库存商品列表
-     * @param page
-     * @param kcDepositoryInGoods
-     * @return
      */
     public Page<KcDepositoryInGoods> depositoryInGoodsList(Page<KcDepositoryInGoods> page, KcDepositoryInGoods kcDepositoryInGoods){
         return page.setRecords(baseMapper.depositoryInGoodsList(page,kcDepositoryInGoods.getHotelId(),
@@ -70,6 +67,7 @@ public class KcDepositoryInGoodsServiceImpl extends ServiceImpl<KcDepositoryInGo
         return storagePage;
     }
 
+    /**添加销售出库*/
     @Override
     public void addSell(KcDepositoryInGoods depositoryInGoods) {
         LoginUser user = TokenUtils.getAuthUser();
@@ -94,13 +92,14 @@ public class KcDepositoryInGoodsServiceImpl extends ServiceImpl<KcDepositoryInGo
         save(depositoryInGoods);
     }
 
-
+    /**分页查询销售详情表*/
     @Override
     public IPage<GoodStorage> goodsSellDetailPage(Page<GoodStorage> page, GoodStorage goodStorage) {
         IPage<GoodStorage> storagePage = baseMapper.goodsSellDetailPage(page, goodStorage);
         return storagePage;
     }
 
+    /**分页查询销售汇总表*/
     @Override
     public IPage<GoodStorage> goodsSellCollect(Page<GoodStorage> page, GoodStorage goodStorage) {
         IPage<GoodStorage> storagePage = baseMapper.goodsSellCollect(page, goodStorage);

+ 13 - 34
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/mall/controller/MallPosTableOrderGoodsController.java

@@ -1,56 +1,35 @@
 package org.jeecg.modules.mall.controller;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
 import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
 import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
+import org.jeecg.common.system.base.controller.JeecgController;
 import org.jeecg.common.system.query.QueryGenerator;
-import org.jeecg.common.util.oConvertUtils;
-import org.jeecg.modules.business.entity.BusHotel;
-import org.jeecg.modules.mall.entity.MallOrderGoods;
-import org.jeecg.modules.mall.entity.MallOrderGoodsDetail;
 import org.jeecg.modules.mall.entity.MallPosTableOrderGoods;
 import org.jeecg.modules.mall.entity.MallPosTableOrderGoodsDetail;
 import org.jeecg.modules.mall.service.IMallPosTableOrderGoodsDetailService;
 import org.jeecg.modules.mall.service.IMallPosTableOrderGoodsService;
-
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import lombok.extern.slf4j.Slf4j;
-
 import org.jeecg.modules.pos.entity.PosRegion;
 import org.jeecg.modules.pos.entity.PosTable;
 import org.jeecg.modules.pos.service.IPosRegionService;
 import org.jeecg.modules.pos.service.IPosTableService;
 import org.jeecg.modules.rooms.service.CesGoodsServiceImpl;
-import org.jeecgframework.poi.excel.ExcelImportUtil;
-import org.jeecgframework.poi.excel.def.NormalExcelConstants;
-import org.jeecgframework.poi.excel.entity.ExportParams;
-import org.jeecgframework.poi.excel.entity.ImportParams;
-import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
-import org.jeecg.common.system.base.controller.JeecgController;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-import org.springframework.web.multipart.MultipartHttpServletRequest;
 import org.springframework.web.servlet.ModelAndView;
-import com.alibaba.fastjson.JSON;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.jeecg.common.aspect.annotation.AutoLog;
-import org.apache.shiro.authz.annotation.RequiresPermissions;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Arrays;
+import java.util.List;
 
  /**
  * @Description: mall_pos_table_order_goods

+ 55 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/PosBookingStateEnum.java

@@ -0,0 +1,55 @@
+package org.jeecg.modules.pos;
+
+import org.jeecg.common.system.vo.DictModel;
+import org.jeecg.modules.business.enums.CouponsEventEnum;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public enum PosBookingStateEnum {
+    NO_ARRIVE(1, "未到店"),
+    ARRIVE(2, "已到店"),
+    RETRUN_MONEY(3, "已退款"),
+    OVER_TIME(4, "已逾期");
+
+    Integer key;
+
+    String title;
+
+    PosBookingStateEnum(Integer key, String title){
+        this.key = key;
+        this.title = title;
+    }
+    public Integer getKey() {
+        return key;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    /**
+     * 获取字典数据
+     * @return
+     */
+    public static List<DictModel> getDictList(){
+        List<DictModel> list = new ArrayList<>();
+        DictModel dictModel = null;
+        for(PosBookingStateEnum e: PosBookingStateEnum.values()){
+            dictModel = new DictModel();
+            dictModel.setValue(e.key.toString());
+            dictModel.setText(e.title);
+            list.add(dictModel);
+        }
+        return list;
+    }
+
+    public static PosBookingStateEnum val(Integer key){
+        for(PosBookingStateEnum bld: values()){
+            if(bld.key.equals(key)){
+                return bld;
+            }
+        }
+        return null;
+    }
+}

+ 55 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/TableStateEnum.java

@@ -0,0 +1,55 @@
+package org.jeecg.modules.pos;
+
+import org.jeecg.common.system.vo.DictModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public enum TableStateEnum {
+    EMPTY(0, "空桌台"),
+    WILL_ORDER(1, "待下单"),
+    WILL_PAYMENT(2, "待结账"),
+    READY_MONEY(3, "已预结"),
+    WILL_CLEAN(4, "待清台");
+
+    Integer key;
+
+    String title;
+
+    TableStateEnum(Integer key, String title){
+        this.key = key;
+        this.title = title;
+    }
+    public Integer getKey() {
+        return key;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    /**
+     * 获取字典数据
+     * @return
+     */
+    public static List<DictModel> getDictList(){
+        List<DictModel> list = new ArrayList<>();
+        DictModel dictModel = null;
+        for(TableStateEnum e: TableStateEnum.values()){
+            dictModel = new DictModel();
+            dictModel.setValue(e.key.toString());
+            dictModel.setText(e.title);
+            list.add(dictModel);
+        }
+        return list;
+    }
+
+    public static TableStateEnum val(Integer key){
+        for(TableStateEnum bld: values()){
+            if(bld.key.equals(key)){
+                return bld;
+            }
+        }
+        return null;
+    }
+}

+ 175 - 99
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/controller/PosOrderGoodsController.java

@@ -1,58 +1,32 @@
 package org.jeecg.modules.pos.controller;
 
-import java.math.BigDecimal;
-import java.text.SimpleDateFormat;
-import java.time.LocalDateTime;
-import java.util.*;
-import java.util.stream.Collectors;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.util.BooleanUtil;
+import cn.hutool.core.date.DateTime;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import org.apache.commons.lang3.ObjectUtils;
-import org.jeecg.common.api.vo.Result;
-import org.jeecg.common.exception.JeecgBootException;
-import org.jeecg.common.system.query.QueryGenerator;
-import org.jeecg.common.util.TokenUtils;
-import org.jeecg.common.util.oConvertUtils;
-import org.jeecg.modules.business.entity.BusOrderFee;
-import org.jeecg.modules.business.enums.FeeSubjectType;
-import org.jeecg.modules.business.service.IBusRoomBookingOrdersService;
-import org.jeecg.modules.pos.entity.*;
-import org.jeecg.modules.pos.service.*;
-
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
-
-import org.jeecg.modules.rooms.entity.CesGoods;
-import org.jeecg.modules.rooms.service.CesGoodsServiceImpl;
-import org.jeecgframework.poi.excel.ExcelImportUtil;
-import org.jeecgframework.poi.excel.def.NormalExcelConstants;
-import org.jeecgframework.poi.excel.entity.ExportParams;
-import org.jeecgframework.poi.excel.entity.ImportParams;
-import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
 import org.jeecg.common.system.base.controller.JeecgController;
+import org.jeecg.common.system.query.QueryGenerator;
+import org.jeecg.modules.pos.PosBookingStateEnum;
+import org.jeecg.modules.pos.entity.*;
+import org.jeecg.modules.pos.service.*;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-import org.springframework.web.multipart.MultipartHttpServletRequest;
 import org.springframework.web.servlet.ModelAndView;
-import com.alibaba.fastjson.JSON;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.jeecg.common.aspect.annotation.AutoLog;
-import org.apache.shiro.authz.annotation.RequiresPermissions;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Arrays;
+import java.util.List;
 
  /**
  * @Description: pos_order_goods
@@ -66,7 +40,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
 @Slf4j
 public class PosOrderGoodsController extends JeecgController<PosOrderGoods, IPosOrderGoodsService> {
 	@Autowired
-	private IPosOrderGoodsService posOrderGoodsService;
+	private IPosBookingService bookingService;
 	@Autowired
 	private IPosOrderGoodsDetailService posOrderGoodsDetailService;
 	@Autowired
@@ -75,12 +49,6 @@ public class PosOrderGoodsController extends JeecgController<PosOrderGoods, IPos
 	private IPosOrderGoodsPaymentService posOrderGoodsPaymentService;
 	/**
 	 * 分页列表查询
-	 *
-	 * @param posOrderGoods
-	 * @param pageNo
-	 * @param pageSize
-	 * @param req
-	 * @return
 	 */
 	//@AutoLog(value = "pos_order_goods-分页列表查询")
 	@ApiOperation(value="pos_order_goods-分页列表查询", notes="pos_order_goods-分页列表查询")
@@ -91,7 +59,7 @@ public class PosOrderGoodsController extends JeecgController<PosOrderGoods, IPos
 								   HttpServletRequest req) {
 		QueryWrapper<PosOrderGoods> queryWrapper = QueryGenerator.initQueryWrapper(posOrderGoods, req.getParameterMap());
 		Page<PosOrderGoods> page = new Page<PosOrderGoods>(pageNo, pageSize);
-		IPage<PosOrderGoods> pageList = posOrderGoodsService.page(page, queryWrapper);
+		IPage<PosOrderGoods> pageList = service.page(page, queryWrapper);
 		pageList.getRecords().forEach(item -> {
 			PosType posType = posTypeService.getById(item.getPosType());
 			if(posType!=null) {
@@ -101,25 +69,9 @@ public class PosOrderGoodsController extends JeecgController<PosOrderGoods, IPos
 		return Result.OK(pageList);
 	}
 
-	 /**
-	  * 生成16位数字+prefix
-	  * @param prefix
-	  * @return
-	  */
-	 private String randomNumber(String prefix) {
-		 int first = new Random(10).nextInt(8) + 1;
-		 int hashCode = UUID.randomUUID().toString().hashCode();
-		 if (hashCode < 0) {
-			 hashCode = -hashCode;
-		 }
-		 return prefix + first + String.format("%015d", hashCode);
-	 }
 
 	 /**
 	  *   添加
-	  *
-	  * @param posOrderGoods
-	  * @return
 	  */
 	 @AutoLog(value = "pos_order_goods-添加")
 	 @ApiOperation(value="pos_order_goods-添加", notes="pos_order_goods-添加")
@@ -135,15 +87,120 @@ public class PosOrderGoodsController extends JeecgController<PosOrderGoods, IPos
 	 }
 
 	 /**
+	  *   添加预约单
+	  */
+	 @AutoLog(value = "pos_booking_order-添加预约单")
+	 @ApiOperation(value="pos_booking_order-添加预约单", notes="pos_booking_order-添加预约单")
+	 //@RequiresPermissions("pos:pos_order_goods:add")
+	 @Transactional(rollbackFor = Exception.class)
+	 @PostMapping(value = "/addBooking")
+	 public Result<Boolean> addBooking(@RequestBody PosBookingOrder bookingOrder) {
+		 return Result.OK("添加成功", service.addBookingOrder(bookingOrder));
+	 }
+
+	 /**
+	  *   修改预约单
+	  */
+	 @AutoLog(value = "pos_booking_order-修改预约单")
+	 @ApiOperation(value="pos_booking_order-修改预约单", notes="pos_booking_order-修改预约单")
+	 //@RequiresPermissions("pos:pos_order_goods:add")
+	 @Transactional(rollbackFor = Exception.class)
+	 @PostMapping(value = "/editBooking")
+	 public Result<Boolean> editBooking(@RequestBody PosBookingOrder bookingOrder) {
+		 return Result.OK("修改成功", service.editBookingOrder(bookingOrder));
+	 }
+
+	 /**
+	  *   根据预约单id查询预约单详情
+	  */
+	 @AutoLog(value = "pos_booking_order-根据预约单id查询预约单详情")
+	 @ApiOperation(value="pos_booking_order-根据预约单id查询预约单详情", notes="pos_booking_order-根据预约单id查询预约单详情")
+	 //@RequiresPermissions("pos:pos_order_goods:add")
+	 @Transactional(rollbackFor = Exception.class)
+	 @GetMapping(value = "/getBookingOrderById")
+	 public Result<PosBookingOrder> getBookingOrderById(String bookingOrderId) {
+		 return Result.OK("修改成功", service.getBookingOrderById(bookingOrderId));
+	 }
+
+	 /**
+	  *   分页查询预约单
+	  */
+	 @AutoLog(value = "pos_booking_order-分页查询")
+	 @ApiOperation(value="pos_booking_order-分页查询", notes="pos_booking_order-分页查询")
+	 //@RequiresPermissions("pos:pos_order_goods:add")
+	 @GetMapping(value = "/getBookingPage")
+	 public Result<Page<PosBookingOrder>> getBookingPage(PosBookingOrder bookingOrder,
+								@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
+								@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
+							   @RequestParam(name="startTime" ,required=false) @JsonFormat(pattern = "yyyy-MM-dd")  @DateTimeFormat(pattern="yyyy-MM-dd") DateTime startTime,
+							   @RequestParam(name="endTime" ,required=false) @JsonFormat(pattern = "yyyy-MM-dd")  @DateTimeFormat(pattern="yyyy-MM-dd") DateTime endTime) {
+		 Page<PosBookingOrder> page = new Page<>(pageNo, pageSize);
+		 return Result.OK(bookingService.getBookingPage(bookingOrder,page,startTime,endTime));
+	 }
+
+
+	 /**
+	  *   根据桌号查询今日预约单
+	  */
+	 @AutoLog(value = "pos_booking_order-根据桌号查询今日预约单")
+	 @ApiOperation(value="pos_booking_order-根据桌号查询今日预约单", notes="pos_booking_order-根据桌号查询今日预约单")
+	 @GetMapping(value = "/getBookingByTableId")
+	 public Result<List<PosBookingOrder>> getBookingByTableId(String tableId) {
+		 if (tableId == null || tableId.isEmpty()){
+			 return Result.error("请选择桌台");
+		 }
+		 return Result.OK(service.getBookingByTableId(tableId));
+	 }
+
+	 /**
+	  *   预定开台
+	  */
+	 @AutoLog(value = "预定开台")
+	 @ApiOperation(value="预定开台", notes="预定开台")
+	 @Transactional(rollbackFor = Exception.class)
+	 @GetMapping(value = "/addOrderByBookingId")
+	 public Result<Boolean> addOrderByBookingId(String bookingId) {
+		 if (bookingId == null || bookingId.isEmpty()){
+			 return Result.error("请选择预约单");
+		 }
+		 return Result.OK(service.addOrderByBookingId(bookingId));
+	 }
+
+	 /**
+	  *   预约单退订
+	  */
+	 @AutoLog(value = "预约单退订")
+	 @ApiOperation(value="预约单退订", notes="预约单退订")
+	 @Transactional(rollbackFor = Exception.class)
+	 @GetMapping(value = "/removeBooking")
+	 public Result<Boolean> cancelBooking(PosBookingOrder bookingOrder) {
+		 return Result.OK(service.cancelBooking(bookingOrder));
+	 }
+
+	 /**
+	  *   预约单逾期
+	  */
+	 @AutoLog(value = "预约单逾期")
+	 @ApiOperation(value="预约单逾期", notes="预约单逾期")
+	 @Transactional(rollbackFor = Exception.class)
+	 @GetMapping(value = "/overTimeBooking")
+	 public Result<Boolean> overTimeBooking(String bookingOrderId) {
+		 PosBookingOrder bookingOrder = bookingService.getById(bookingOrderId);
+		 if (!PosBookingStateEnum.NO_ARRIVE.getKey().equals(bookingOrder.getState())){
+			 return Result.error("未到店订单时才能逾期");
+		 }
+		 bookingOrder.setState(PosBookingStateEnum.OVER_TIME.getKey());
+		 return Result.OK(bookingService.updateById(bookingOrder));
+	 }
+
+	 /**
 	  * 台桌时挂房账
-	  * @param
-	  * @return
 	  */
 	 @AutoLog(value = "pos_order_goods-挂房账")
 	 @ApiOperation(value="pos_order_goods-挂房账", notes="pos_order_goods-挂房账")
 	 @Transactional(rollbackFor = Exception.class)
 	 @PostMapping("/addRoomFee")
-	 public Result addRoomFee(@RequestBody PosOrderGoods posOrderGoods,String hotelId){
+	 public Result<Boolean> addRoomFee(@RequestBody PosOrderGoods posOrderGoods,String hotelId){
 		 return Result.ok(service.addRoomFee(posOrderGoods, hotelId));
 	 }
 
@@ -155,8 +212,6 @@ public class PosOrderGoodsController extends JeecgController<PosOrderGoods, IPos
 
 	 /**
 	  * 撤销结账
-	  * @param code
-	  * @return
 	  */
 	 @AutoLog(value = "cancelSettle")
 	 @ApiOperation(value="cancelSettle", notes="cancelSettle")
@@ -166,7 +221,7 @@ public class PosOrderGoodsController extends JeecgController<PosOrderGoods, IPos
 		 lambdaUpdateWrapper.eq(PosOrderGoods::getCode, code);
 		 lambdaUpdateWrapper.set(PosOrderGoods::getStatus, 0);
 		 lambdaUpdateWrapper.set(PosOrderGoods::getPayInfo, "");
-		 posOrderGoodsService.update(lambdaUpdateWrapper);
+		 service.update(lambdaUpdateWrapper);
 
 		 LambdaQueryWrapper<PosOrderGoodsPayment> LambdaQueryWrapper = new LambdaQueryWrapper<>();
 		 LambdaQueryWrapper.eq(PosOrderGoodsPayment::getOrderId, code);
@@ -177,8 +232,6 @@ public class PosOrderGoodsController extends JeecgController<PosOrderGoods, IPos
 	 /**
 	  *   通过code删除
 	  *
-	  * @param code
-	  * @return
 	  */
 	 @AutoLog(value = "pos_order_goods-通过id删除")
 	 @ApiOperation(value="pos_order_goods-通过id删除", notes="pos_order_goods-通过id删除")
@@ -187,7 +240,7 @@ public class PosOrderGoodsController extends JeecgController<PosOrderGoods, IPos
 	 public Result<String> deleteOrder(@RequestParam(name="code",required=true) String code) {
 		 LambdaQueryWrapper<PosOrderGoods> LambdaQueryWrapper = new LambdaQueryWrapper<>();
 		 LambdaQueryWrapper.eq(PosOrderGoods::getCode, code);
-		 posOrderGoodsService.remove(LambdaQueryWrapper);
+		 service.remove(LambdaQueryWrapper);
 
 		 LambdaQueryWrapper<PosOrderGoodsDetail> LambdaQueryWrapper2 = new LambdaQueryWrapper<>();
 		 LambdaQueryWrapper2.eq(PosOrderGoodsDetail::getOrderId, code);
@@ -199,71 +252,98 @@ public class PosOrderGoodsController extends JeecgController<PosOrderGoods, IPos
 
 	/**
 	 *  编辑
-	 *
-	 * @param posOrderGoods
-	 * @return
 	 */
 	@AutoLog(value = "pos_order_goods-编辑")
 	@ApiOperation(value="pos_order_goods-编辑", notes="pos_order_goods-编辑")
 	//@RequiresPermissions("pos:pos_order_goods:edit")
 	@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
 	public Result<String> edit(@RequestBody PosOrderGoods posOrderGoods) {
-		posOrderGoodsService.updateById(posOrderGoods);
+		service.updateById(posOrderGoods);
 		return Result.OK("编辑成功!");
 	}
 
 	/**
 	 *   通过id删除
-	 *
-	 * @param id
-	 * @return
 	 */
 	@AutoLog(value = "pos_order_goods-通过id删除")
 	@ApiOperation(value="pos_order_goods-通过id删除", notes="pos_order_goods-通过id删除")
 	//@RequiresPermissions("pos:pos_order_goods:delete")
 	@DeleteMapping(value = "/delete")
 	public Result<String> delete(@RequestParam(name="id",required=true) String id) {
-		posOrderGoodsService.removeById(id);
+		service.removeById(id);
 		return Result.OK("删除成功!");
 	}
 
 	/**
 	 *  批量删除
-	 *
-	 * @param ids
-	 * @return
 	 */
 	@AutoLog(value = "pos_order_goods-批量删除")
 	@ApiOperation(value="pos_order_goods-批量删除", notes="pos_order_goods-批量删除")
 	//@RequiresPermissions("pos:pos_order_goods:deleteBatch")
 	@DeleteMapping(value = "/deleteBatch")
 	public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
-		this.posOrderGoodsService.removeByIds(Arrays.asList(ids.split(",")));
+		service.removeByIds(Arrays.asList(ids.split(",")));
 		return Result.OK("批量删除成功!");
 	}
 
 	/**
 	 * 通过id查询
-	 *
-	 * @param id
-	 * @return
 	 */
 	//@AutoLog(value = "pos_order_goods-通过id查询")
 	@ApiOperation(value="pos_order_goods-通过id查询", notes="pos_order_goods-通过id查询")
 	@GetMapping(value = "/queryById")
 	public Result<PosOrderGoods> queryById(@RequestParam(name="id",required=true) String id) {
-		PosOrderGoods posOrderGoods = posOrderGoodsService.getById(id);
+		PosOrderGoods posOrderGoods = service.getById(id);
 		if(posOrderGoods==null) {
 			return Result.error("未找到对应数据");
 		}
 		return Result.OK(posOrderGoods);
 	}
 
+	 /**
+	  * 联台
+	  */
+	 @ApiOperation(value="联台", notes="联台")
+	 @Transactional(rollbackFor = Exception.class)
+	 @RequestMapping(value = "/merge-order",method = RequestMethod.POST)
+	 public Result<Boolean> mergePosOrder(String hotelId, String mainPosOrderId,@RequestBody List<String> posOrderIds){
+		 return  Result.OK(service.mergePosOrder(hotelId,mainPosOrderId,posOrderIds));
+	 }
+
+	 /**
+	  * 取消联台
+	  */
+	 @ApiOperation(value="取消联台", notes="取消联台")
+	 @Transactional(rollbackFor = Exception.class)
+	 @RequestMapping(value = "/return-merge-order",method = RequestMethod.GET)
+	 public Result<Boolean> returnMergePosOrder(String posOrderId){
+		 return  Result.OK(service.returnMergePosOrder(posOrderId));
+	 }
+
+	 /**
+	  * 换桌
+	  */
+	 @ApiOperation(value="换桌", notes="换桌")
+	 @Transactional(rollbackFor = Exception.class)
+	 @RequestMapping(value = "/change-table",method = RequestMethod.GET)
+	 public Result<Boolean> changeTable(String posOrderId,String tableId ){
+		 return  Result.OK(service.changeTable(posOrderId,tableId));
+	 }
+
+
+
+	 /**
+	  * 转菜
+	  */
+	 @ApiOperation(value="转菜", notes="转菜")
+	 @Transactional(rollbackFor = Exception.class)
+	 @RequestMapping(value = "/transfer-dishes",method = RequestMethod.POST)
+	 public Result<Boolean> transferDishes(String posOrderId,@RequestBody List<String> orderGoodsDetailIds ){
+		 return  Result.OK(service.transferDishes(posOrderId,orderGoodsDetailIds));
+	 }
+
     /**
     * 导出excel
-    *
-    * @param request
-    * @param posOrderGoods
     */
     //@RequiresPermissions("pos:pos_order_goods:exportXls")
     @RequestMapping(value = "/exportXls")
@@ -273,10 +353,6 @@ public class PosOrderGoodsController extends JeecgController<PosOrderGoods, IPos
 
     /**
       * 通过excel导入数据
-    *
-    * @param request
-    * @param response
-    * @return
     */
     //@RequiresPermissions("pos:pos_order_goods:importExcel")
     @RequestMapping(value = "/importExcel", method = RequestMethod.POST)

+ 37 - 6
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/controller/PosOrderGoodsDetailController.java

@@ -1,5 +1,6 @@
 package org.jeecg.modules.pos.controller;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -11,8 +12,10 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.exception.JeecgBootException;
 import org.jeecg.common.system.query.QueryGenerator;
 import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.modules.pos.entity.PosOrderGoodsDetail;
@@ -64,12 +67,6 @@ private CesGoodsServiceImpl cesGoodsService;
 private IPosThaliService posThaliService;
 	/**
 	 * 分页列表查询
-	 *
-	 * @param posOrderGoodsDetail
-	 * @param pageNo
-	 * @param pageSize
-	 * @param req
-	 * @return
 	 */
 	//@AutoLog(value = "pos_order_goods_detail-分页列表查询")
 	@ApiOperation(value="pos_order_goods_detail-分页列表查询", notes="pos_order_goods_detail-分页列表查询")
@@ -95,6 +92,40 @@ private IPosThaliService posThaliService;
 		return Result.OK(pageList);
 	}
 
+	 /**
+	  * 通过订单id查询订单详情
+	  */
+	 //@AutoLog(value = "pos_order_goods_detail-分页列表查询")
+	 @ApiOperation(value="pos_order_goods_detail-通过订单id查询订单详情", notes="pos_order_goods_detail-通过订单id查询订单详情")
+	 @GetMapping(value = "/getDetailByOrderId")
+	 public Result<List<PosOrderGoodsDetail>> getDetailByOrderId(PosOrderGoodsDetail posOrderGoodsDetail,HttpServletRequest req) {
+		 QueryWrapper<PosOrderGoodsDetail> queryWrapper = QueryGenerator.initQueryWrapper(posOrderGoodsDetail, req.getParameterMap());
+		 List<PosOrderGoodsDetail> orderGoodsDetailList = posOrderGoodsDetailService.list(queryWrapper);
+		 List<PosOrderGoodsDetail> result = new ArrayList<>();
+		 orderGoodsDetailList.forEach(item -> {
+			 CesGoods cesGoods = cesGoodsService.getById(item.getGoodsId());
+			 if (cesGoods != null) {
+				 item.setGoodsName(cesGoods.getName());
+			 }
+			 if (StrUtil.isNotEmpty(item.getThaliId()) && StrUtil.isEmpty(item.getParentId())) {
+				 PosThali posThali = posThaliService.getById(item.getThaliId());
+				 if (posThali == null){
+					 throw new JeecgBootException("未找到商品");
+				 }
+				 item.setGoodsName(posThali.getName());
+			 }
+			 if (StrUtil.isEmpty(item.getParentId())){
+				 result.add(item);
+			 }
+		 });
+		 result.forEach(e -> {
+			 List<PosOrderGoodsDetail> child = orderGoodsDetailList.stream().filter(ele -> e.getId()
+					 .equals(ele.getParentId())).collect(Collectors.toList());
+			 e.setChildDetails(child);
+		 });
+		 return Result.OK(result);
+	 }
+
 	/**
 	 *   添加
 	 *

+ 10 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/controller/PosSellClearGoodsController.java

@@ -18,7 +18,10 @@ import org.jeecg.common.util.TokenUtils;
 import org.jeecg.modules.pos.entity.PosSellClearGoods;
 import org.jeecg.modules.pos.entity.PosThali;
 import org.jeecg.modules.pos.service.IPosSellClearGoodsService;
+import org.jeecg.modules.pos.service.IPosThaliInGoodsService;
 import org.jeecg.modules.pos.service.IPosThaliService;
+import org.jeecg.modules.pos.service.impl.PosThaliInGoodsServiceImpl;
+import org.jeecg.modules.rooms.Vo.CesGoodsVo;
 import org.jeecg.modules.rooms.entity.CesGoods;
 import org.jeecg.modules.rooms.entity.CesStockType;
 import org.jeecg.modules.rooms.service.CesGoodsServiceImpl;
@@ -53,6 +56,8 @@ public class PosSellClearGoodsController extends JeecgController<PosSellClearGoo
 	private CesStockTypeServiceImpl cesStockTypeService;
 	@Resource
 	private IPosThaliService posThaliService;
+	@Resource
+	private IPosThaliInGoodsService posThaliInGoodsService;
 
 	 /**
 	  * 商品沽清列表
@@ -187,6 +192,11 @@ public class PosSellClearGoodsController extends JeecgController<PosSellClearGoo
 		 }
 		 Page<PosThali> page = new Page<PosThali>(pageNo, pageSize);
 		 IPage<PosThali> pageList = posThaliService.page(page, queryWrapper);
+		 List<String> thaliIds = pageList.getRecords().stream().map(PosThali::getId).collect(Collectors.toList());
+		 pageList.getRecords().forEach(c -> {
+			 List<CesGoodsVo> goodsVos = posThaliInGoodsService.getThaliInGoodsDetail(thaliIds);
+			 c.setCesGoodsList(goodsVos);
+		 });
 		 return Result.OK(pageList);
 	 }
 

+ 83 - 11
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/controller/PosTableController.java

@@ -15,13 +15,16 @@ import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
 import cn.hutool.core.io.FastByteArrayOutputStream;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.URLUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import me.chanjar.weixin.common.error.WxErrorException;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.aspectj.weaver.ast.Var;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.constant.CommonConstant;
 import org.jeecg.common.exception.JeecgBootException;
@@ -35,6 +38,7 @@ import org.jeecg.modules.mall.entity.MallUserInfo;
 import org.jeecg.modules.mall.entity.WxAppConfig;
 import org.jeecg.modules.mall.ma.WxMaInRedisConfigStorage;
 import org.jeecg.modules.mall.service.IWxAppConfigService;
+import org.jeecg.modules.pos.PosBookingStateEnum;
 import org.jeecg.modules.pos.entity.*;
 import org.jeecg.modules.pos.service.*;
 
@@ -85,6 +89,8 @@ public class PosTableController extends JeecgController<PosTable, IPosTableServi
 	 @Autowired
 	 private IPosOrderGoodsService posOrderGoodsService;
 	 @Resource
+	 IPosBookingService bookingService;
+	 @Resource
 	 private IWxAppConfigService wxAppConfigService;
 	 @Resource
 	 private RedisTemplate redisTemplate;
@@ -127,7 +133,6 @@ public class PosTableController extends JeecgController<PosTable, IPosTableServi
 
 	 /**
 	  * 查询桌台用餐列表
-	  *
 	  * @param posTable
 	  * @param pageNo
 	  * @param pageSize
@@ -143,22 +148,57 @@ public class PosTableController extends JeecgController<PosTable, IPosTableServi
 		 QueryWrapper<PosTable> queryWrapper = QueryGenerator.initQueryWrapper(posTable, req.getParameterMap());
 		 Page<PosTable> page = new Page<PosTable>(pageNo, pageSize);
 		 IPage<PosTable> pageList = posTableService.page(page, queryWrapper);
+		 // 找出今日所有预约的桌台id集合
+		 List<String> bookingTableIds = getBookingTableIds();
 		 pageList.getRecords().forEach(item -> {
-			 if (item.getState().equals(2) || item.getState().equals(3) || item.getState().equals(4)) {
-				 LambdaQueryWrapper<PosOrderGoods> lambdaQueryWrapper = new LambdaQueryWrapper<>();
-				 lambdaQueryWrapper.eq(PosOrderGoods::getPosTableId, item.getId());
-				 lambdaQueryWrapper.orderByDesc(PosOrderGoods::getCreateTime);
-				 Page<PosOrderGoods> page2 = new Page<PosOrderGoods>(1, 1);
-				 lambdaQueryWrapper.orderByDesc(PosOrderGoods::getCreateTime);
-				 IPage<PosOrderGoods> posOrderGoodsList = posOrderGoodsService.page(page2, lambdaQueryWrapper);
-				 if (ObjectUtils.isNotEmpty(posOrderGoodsList.getRecords())) {
-					 item.setPosOrderGoods(posOrderGoodsList.getRecords().get(0));
-				 }
+			 // 是否是预约单
+			 item.setIsBooking(bookingTableIds.contains(item.getId()));
+			 // 如果桌台状态是 待下单、待结算、已经预结 就查询订单
+			 if (!item.getState().equals(0)) {
+				 PosOrderGoods orderGoods = posOrderGoodsService.getOrderTeamByTableId(item.getId());
+				 item.setPosOrderGoods(orderGoods);
 			 }
 		 });
 		 return Result.OK(pageList);
 	 }
 
+
+	 /**
+	  * 查询可以联台的桌台列表
+	  * @param posTable
+	  * @param pageNo
+	  * @param pageSize
+	  * @return
+	  */
+	 @ApiOperation(value = "pos_table-分页列表查询", notes = "pos_table-分页列表查询")
+	 @GetMapping(value = "/getCanMerge")
+	 public Result<IPage<PosTable>> getCanUseTable(PosTable posTable,
+											  @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
+											  @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
+		 LambdaQueryWrapper<PosTable> wrapper = new LambdaQueryWrapper<>();
+		 wrapper.eq(PosTable::getPosTypeId, posTable.getPosTypeId());
+		 wrapper.eq(StrUtil.isNotEmpty(posTable.getPosRegionId()),PosTable::getPosRegionId, posTable.getPosRegionId());
+		 wrapper.eq(PosTable::getHotelId, posTable.getHotelId());
+		 // 换台:0空桌。 转菜:2待结账的。 联台:1待下单、2待结账、3、已预结。
+		 if (posTable.getState() == 5){
+			 // 查询可联台的桌台,前端传入state = 5
+			 wrapper.and(i -> i.eq(PosTable::getState,1).or().eq(PosTable::getState,2).eq(PosTable::getState,3));
+		 } else {
+			 wrapper.eq(ObjectUtil.isNotEmpty(posTable.getState()),PosTable::getState,posTable.getState());
+		 }
+		 Page<PosTable> page = new Page<PosTable>(pageNo, pageSize);
+		 IPage<PosTable> pageList = posTableService.page(page, wrapper);
+		 // 找出今日所有预约的桌台id集合
+		 List<String> bookingTableIds = getBookingTableIds();
+		 pageList.getRecords().forEach(item -> {
+			 // 是否是今日有预约单
+			 item.setIsBooking(bookingTableIds.contains(item.getId()));
+			 PosOrderGoods orderGoods = posOrderGoodsService.getOrderTeamByTableId(item.getId());
+			 item.setPosOrderGoods(orderGoods);
+		 });
+		 return Result.OK(pageList);
+	 }
+
 	 /**
 	  * 添加
 	  *
@@ -279,13 +319,31 @@ public class PosTableController extends JeecgController<PosTable, IPosTableServi
 		 if (!table.getState().equals(0)) {
 			 return Result.error("不是空桌状态,不能下单!");
 		 }
+		 PosOrderGoods orderGoods = new PosOrderGoods();
+		 orderGoods.setCode(randomNumber("P"));
+		 orderGoods.setPosTableId(posTable.getId());
 		 posTable.setState(1);
 		 posTable.setOrderTime(new Date());
+		 posOrderGoodsService.save(orderGoods);
 		 posTableService.updateById(posTable);
 		 return Result.OK("下单成功!");
 	 }
 
 	 /**
+	  * 生成16位数字+prefix
+	  * @param prefix
+	  * @return
+	  */
+	 private String randomNumber(String prefix) {
+		 int first = new Random(10).nextInt(8) + 1;
+		 int hashCode = UUID.randomUUID().toString().hashCode();
+		 if (hashCode < 0) {
+			 hashCode = -hashCode;
+		 }
+		 return prefix + first + String.format("%015d", hashCode);
+	 }
+
+	 /**
 	  * 编辑
 	  *
 	  * @param posTable
@@ -360,6 +418,20 @@ public class PosTableController extends JeecgController<PosTable, IPosTableServi
 
 
 	 /**
+	  * 获取今日预定单预定桌id
+	  */
+	 private List<String> getBookingTableIds() {
+		 List<PosBookingOrder> bookingOrders = bookingService.getTodayBooking();
+		 List<String> ids = bookingOrders.stream().map(PosBookingOrder::getId).collect(Collectors.toList());
+		 if (ids.isEmpty()){
+			 return new ArrayList<>();
+		 }
+		 List<PosOrderGoods> orderGoods = posOrderGoodsService.listByIds(ids);
+		 return orderGoods.stream().map(PosOrderGoods::getPosTableId).collect(Collectors.toList());
+	 }
+
+
+	 /**
 	  * 生成二维码
 	  *
 	  * @param id

+ 17 - 31
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/controller/PosThaliController.java

@@ -1,51 +1,35 @@
 package org.jeecg.modules.pos.controller;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
+import cn.hutool.core.bean.BeanUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
 import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
 import org.jeecg.common.exception.JeecgBootException;
+import org.jeecg.common.system.base.controller.JeecgController;
 import org.jeecg.common.system.query.QueryGenerator;
 import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.common.util.TokenUtils;
 import org.jeecg.common.util.UUIDGenerator;
-import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.modules.pos.entity.PosThali;
 import org.jeecg.modules.pos.entity.PosThaliInGoods;
 import org.jeecg.modules.pos.service.IPosThaliInGoodsService;
 import org.jeecg.modules.pos.service.IPosThaliService;
-
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import lombok.extern.slf4j.Slf4j;
-
-import org.jeecgframework.poi.excel.ExcelImportUtil;
-import org.jeecgframework.poi.excel.def.NormalExcelConstants;
-import org.jeecgframework.poi.excel.entity.ExportParams;
-import org.jeecgframework.poi.excel.entity.ImportParams;
-import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
-import org.jeecg.common.system.base.controller.JeecgController;
+import org.jeecg.modules.rooms.entity.CesGoods;
+import org.jeecg.modules.rooms.service.CesGoodsServiceImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-import org.springframework.web.multipart.MultipartHttpServletRequest;
 import org.springframework.web.servlet.ModelAndView;
-import com.alibaba.fastjson.JSON;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.jeecg.common.aspect.annotation.AutoLog;
-import org.apache.shiro.authz.annotation.RequiresPermissions;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Arrays;
 
  /**
  * @Description: pos_thali
@@ -104,6 +88,8 @@ public class PosThaliController extends JeecgController<PosThali, IPosThaliServi
 			}
 		}
 		posThali.setId(UUIDGenerator.generate());
+		CesGoods cesGoods = BeanUtil.copyProperties(posThali, CesGoods.class);
+		cesGoods.setId(null);
 		boolean res = posThaliService.save(posThali);
 		if (res) {
 			if (ObjectUtils.isNotEmpty(posThali.getPosThaliInGoodsList())) {

+ 101 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/entity/PosBookingOrder.java

@@ -0,0 +1,101 @@
+package org.jeecg.modules.pos.entity;
+
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+import java.math.BigDecimal;
+import java.util.List;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.jeecg.modules.rooms.entity.CesGoods;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.jeecg.common.aspect.annotation.Dict;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * @Description: pos_order_goods
+ * @Author: jeecg-boot
+ * @Date:   2023-04-13
+ * @Version: V1.0
+ */
+@Data
+@TableName("pos_booking_order")
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value="pos_booking_order对象", description="pos_booking_order")
+public class PosBookingOrder implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**主键*/
+    @TableId(type = IdType.ASSIGN_ID)
+    @ApiModelProperty(value = "主键")
+    private String id;
+    /**关联租户*/
+    /**关联酒店*/
+    @Excel(name = "关联酒店", width = 15)
+    @ApiModelProperty(value = "关联酒店")
+    private String hotelId;
+    /**单据号*/
+    @Excel(name = "单据号", width = 15)
+    @ApiModelProperty(value = "单据号")
+    private String code;
+    /**押金*/
+    @Excel(name = "押金", width = 15)
+    @ApiModelProperty(value = "押金")
+    private String deposit;
+    /**每桌人数*/
+    @Excel(name = "每桌人数", width = 15)
+    @ApiModelProperty(value = "每桌人数")
+    private Integer peopleNum;
+    /**押金*/
+    @Excel(name = "性别", width = 15)
+    @ApiModelProperty(value = "性别")
+    private Integer sex;
+    /**客人姓名*/
+    @Excel(name = "客人姓名", width = 15)
+    @ApiModelProperty(value = "客人姓名")
+    private String customerName;
+    /**电话*/
+    @Excel(name = "电话", width = 15)
+    @ApiModelProperty(value = "电话")
+    private String phone;
+    /**备注*/
+    @Excel(name = "备注", width = 15)
+    @ApiModelProperty(value = "备注")
+    private String remark;
+    /**会员id*/
+    @Excel(name = "会员id", width = 15)
+    @ApiModelProperty(value = "会员id")
+    private String vipId;
+    /**状态*/
+    @Excel(name = "状态", width = 15)
+    @ApiModelProperty(value = "预约状态。1未到店,2已到店,3已退款,4已逾期")
+    private Integer state;
+    /**预约时间*/
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "预约时间")
+    private Date arriveTime;
+    /**创建时间*/
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+
+    @TableField(exist = false)
+    private List<PosOrderGoods> posOrderGoodList;
+    @TableField(exist = false)
+    private List<PosOrderGoodsDetail> posOrderGoodsDetailList;
+    @TableField(exist = false)
+    private List<String> tableIds;
+    @TableField(exist = false)
+    private List<PosTable> tableList;
+
+
+}

+ 30 - 13
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/entity/PosOrderGoods.java

@@ -1,21 +1,22 @@
 package org.jeecg.modules.pos.entity;
 
-import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
-import java.util.Date;
-import java.math.BigDecimal;
-import java.util.List;
-
-import com.baomidou.mybatisplus.annotation.*;
-import lombok.Data;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import org.springframework.format.annotation.DateTimeFormat;
-import org.jeecgframework.poi.excel.annotation.Excel;
-import org.jeecg.common.aspect.annotation.Dict;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
 
 /**
  * @Description: pos_order_goods
@@ -51,6 +52,14 @@ public class PosOrderGoods implements Serializable {
 	@Excel(name = "单据号", width = 15)
     @ApiModelProperty(value = "单据号")
     private String code;
+    /**单据号*/
+    @Excel(name = "是否为预约单", width = 15)
+    @ApiModelProperty(value = "是否还是预约单,预约开台后改为false")
+    private Boolean isBooking;
+    /**单据号*/
+    @Excel(name = "预约单Code", width = 15)
+    @ApiModelProperty(value = "单据号")
+    private String bookingCode;
     /**桌台id*/
     @Excel(name = "桌台id", width = 15)
     @ApiModelProperty(value = "桌台id")
@@ -110,13 +119,21 @@ public class PosOrderGoods implements Serializable {
     @Excel(name = "支付信息", width = 15)
     @ApiModelProperty(value = "支付信息")
     private String payInfo;
+    /**团队id*/
+    @Excel(name = "联桌id", width = 15)
+    @ApiModelProperty(value = "联桌id")
+    private String teamId;
 
+    /**联桌序号*/
+    @TableField(exist = false)
+    private Integer teamIndex;
+    /**是主房*/
+    @TableField(exist = false)
+    private Boolean isMain;
 	@TableField(exist = false)
 	private List<PosOrderGoodsDetail> posOrderGoodsDetailList;
-
     @TableField(exist = false)
     private String posTypeName;
-
     /** 是挂单 */
     @TableField(exist = false)
     private Boolean isPending;

+ 14 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/entity/PosOrderGoodsDetail.java

@@ -4,6 +4,7 @@ import java.io.Serializable;
 import java.io.UnsupportedEncodingException;
 import java.util.Date;
 import java.math.BigDecimal;
+import java.util.List;
 
 import com.baomidou.mybatisplus.annotation.*;
 import lombok.Data;
@@ -50,6 +51,14 @@ public class PosOrderGoodsDetail implements Serializable {
 	@Excel(name = "商品id", width = 15)
     @ApiModelProperty(value = "商品id")
     private String goodsId;
+	/**套餐id*/
+	@Excel(name = "套餐id", width = 15)
+	@ApiModelProperty(value = "套餐id")
+	private String thaliId;
+	/**套餐下的PosOrderGoodsDetail.id*/
+	@Excel(name = "套餐id", width = 15)
+	@ApiModelProperty(value = "套餐id")
+	private String parentId;
 	/**数量*/
 	@Excel(name = "数量", width = 15)
     @ApiModelProperty(value = "数量")
@@ -69,4 +78,9 @@ public class PosOrderGoodsDetail implements Serializable {
 
 	@TableField(exist = false)
 	private  String goodsName;
+
+	@TableField(exist = false)
+	private List<PosOrderGoodsDetail> childDetails;
+
+
 }

+ 5 - 2
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/entity/PosTable.java

@@ -6,6 +6,7 @@ import java.util.Date;
 import java.math.BigDecimal;
 
 import com.baomidou.mybatisplus.annotation.*;
+import com.sun.org.apache.xpath.internal.operations.Bool;
 import lombok.Data;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -68,7 +69,7 @@ public class PosTable implements Serializable {
     private java.lang.String tableNo;
 	/**状态*/
 	@Excel(name = "状态", width = 15)
-    @ApiModelProperty(value = "状态")
+    @ApiModelProperty(value = "状态 1待下单,")
     private java.lang.Integer state;
     /**下单时间*/
     @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@@ -93,7 +94,9 @@ public class PosTable implements Serializable {
     @TableField(exist = false)
     private  String tableTypeName;
 
-
+    /**今日有预约*/
+    @TableField(exist = false)
+    private Boolean isBooking;
 
     @TableField(exist = false)
     private  PosOrderGoods posOrderGoods;

+ 6 - 1
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/entity/PosThali.java

@@ -9,6 +9,8 @@ import java.util.List;
 import com.baomidou.mybatisplus.annotation.*;
 import lombok.Data;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import org.jeecg.modules.rooms.Vo.CesGoodsVo;
+import org.jeecg.modules.rooms.entity.CesGoods;
 import org.springframework.format.annotation.DateTimeFormat;
 import org.jeecgframework.poi.excel.annotation.Excel;
 import org.jeecg.common.aspect.annotation.Dict;
@@ -58,7 +60,7 @@ public class PosThali implements Serializable {
 	/**售价*/
 	@Excel(name = "售价", width = 15)
     @ApiModelProperty(value = "售价")
-    private java.math.BigDecimal price;
+    private java.math.BigDecimal sellingPrice;
 	/**状态*/
 	@Excel(name = "状态", width = 15)
     @ApiModelProperty(value = "状态")
@@ -74,4 +76,7 @@ public class PosThali implements Serializable {
 
 	@TableField(exist = false)
 	private List<PosThaliInGoods> posThaliInGoodsList;
+
+	@TableField(exist = false)
+	private List<CesGoodsVo> cesGoodsList;
 }

+ 7 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/mapper/PosBookingOrderMapper.java

@@ -0,0 +1,7 @@
+package org.jeecg.modules.pos.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.pos.entity.PosBookingOrder;
+
+public interface PosBookingOrderMapper extends BaseMapper<PosBookingOrder> {
+}

+ 7 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/mapper/PosOrderTeamMapper.java

@@ -0,0 +1,7 @@
+package org.jeecg.modules.pos.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.pos.entity.PosOrderTeam;
+
+public interface PosOrderTeamMapper extends BaseMapper<PosOrderTeam> {
+}

+ 9 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/mapper/PosThaliInGoodsMapper.java

@@ -3,8 +3,10 @@ package org.jeecg.modules.pos.mapper;
 import java.util.List;
 
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 import org.jeecg.modules.pos.entity.PosThaliInGoods;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.rooms.Vo.CesGoodsVo;
 
 /**
  * @Description: pos_thali_in_goods
@@ -14,4 +16,11 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface PosThaliInGoodsMapper extends BaseMapper<PosThaliInGoods> {
 
+    @Select("<script>select cg.*, ptig.num as thali_num, ptig.required as thali_required from pos_thali_in_goods ptig " +
+            "inner join ces_goods cg on cg.id = ptig.goods_id " +
+            "where ptig.pos_thali_id in " +
+            "<foreach collection='thaliIds' item='id' open='(' separator=',' close=')'> " +
+            "#{id} </foreach>" +
+            "</script>")
+    List<CesGoodsVo> getThaliInGoodsDetail(List<String> thaliIds);
 }

+ 14 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/IPosBookingService.java

@@ -0,0 +1,14 @@
+package org.jeecg.modules.pos.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.pos.entity.PosBookingOrder;
+
+import java.util.Date;
+import java.util.List;
+
+public interface IPosBookingService  extends IService<PosBookingOrder> {
+    Page<PosBookingOrder> getBookingPage(PosBookingOrder bookingOrder, Page<PosBookingOrder> page, Date startTime, Date endTime);
+
+    List<PosBookingOrder> getTodayBooking();
+}

+ 25 - 1
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/IPosOrderGoodsService.java

@@ -1,7 +1,8 @@
 package org.jeecg.modules.pos.service;
 
-import org.jeecg.modules.pos.entity.PosOrderGoods;
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.pos.entity.PosBookingOrder;
+import org.jeecg.modules.pos.entity.PosOrderGoods;
 
 import java.util.List;
 
@@ -15,7 +16,30 @@ public interface IPosOrderGoodsService extends IService<PosOrderGoods> {
 
     PosOrderGoods getOrderByTableId(String tableId);
 
+    PosOrderGoods getOrderTeamByTableId(String tableId);
+
     Boolean addRoomFee(PosOrderGoods posOrderGoods,String hotelId);
 
     PosOrderGoods addOrder(PosOrderGoods posOrderGoods);
+
+    Boolean addBookingOrder(PosBookingOrder bookingOrder);
+
+    Boolean editBookingOrder(PosBookingOrder bookingOrder);
+
+    PosBookingOrder getBookingOrderById(String bookingOrderId);
+
+    List<PosBookingOrder> getBookingByTableId(String tableId);
+
+    Boolean addOrderByBookingId(String bookingCode);
+
+    Boolean cancelBooking(PosBookingOrder bookingOrder);
+
+    Boolean mergePosOrder(String hotelId, String mainPosOrderId, List<String> posOrderIds);
+
+    Boolean returnMergePosOrder(String posOrderId);
+
+    Boolean changeTable(String posOrderId, String tableId);
+
+    Boolean transferDishes(String posOrderId, List<String> orderGoodsDetailIds);
+
 }

+ 8 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/IPosOrderTeamService.java

@@ -0,0 +1,8 @@
+package org.jeecg.modules.pos.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.pos.entity.PosOrderTeam;
+
+public interface IPosOrderTeamService extends IService<PosOrderTeam> {
+    PosOrderTeam addBusTeams(String hotelId, String orderId);
+}

+ 4 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/IPosThaliInGoodsService.java

@@ -2,6 +2,9 @@ package org.jeecg.modules.pos.service;
 
 import org.jeecg.modules.pos.entity.PosThaliInGoods;
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.rooms.Vo.CesGoodsVo;
+
+import java.util.List;
 
 /**
  * @Description: pos_thali_in_goods
@@ -11,4 +14,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface IPosThaliInGoodsService extends IService<PosThaliInGoods> {
 
+    List<CesGoodsVo> getThaliInGoodsDetail(List<String> thaliIds);
 }

+ 50 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/impl/PosBookingOrderImpl.java

@@ -0,0 +1,50 @@
+package org.jeecg.modules.pos.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.jeecg.modules.pos.PosBookingStateEnum;
+import org.jeecg.modules.pos.entity.PosBookingOrder;
+import org.jeecg.modules.pos.mapper.PosBookingOrderMapper;
+import org.jeecg.modules.pos.service.IPosBookingService;
+import org.springframework.stereotype.Service;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+public class PosBookingOrderImpl  extends ServiceImpl<PosBookingOrderMapper, PosBookingOrder> implements IPosBookingService {
+
+
+    @Override
+    public Page<PosBookingOrder> getBookingPage(PosBookingOrder bookingOrder, Page<PosBookingOrder> page, Date startTime, Date endTime) {
+        LambdaQueryWrapper<PosBookingOrder> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(ObjectUtil.isNotEmpty(bookingOrder.getState()),PosBookingOrder::getState, bookingOrder.getState());
+        wrapper.eq(ObjectUtil.isNotEmpty(bookingOrder.getCode()),PosBookingOrder::getCode, bookingOrder.getCode());
+        wrapper.eq(ObjectUtil.isNotEmpty(bookingOrder.getCustomerName()),PosBookingOrder::getCustomerName, bookingOrder.getCustomerName());
+        wrapper.eq(ObjectUtil.isNotEmpty(bookingOrder.getPhone()),PosBookingOrder::getPhone, bookingOrder.getPhone());
+        wrapper.ge(ObjectUtil.isNotEmpty(startTime),PosBookingOrder::getArriveTime, startTime);
+        wrapper.le(ObjectUtil.isNotEmpty(endTime),PosBookingOrder::getArriveTime, endTime);
+        return page(page, wrapper);
+    }
+
+    @Override
+    public List<PosBookingOrder> getTodayBooking() {
+        Calendar nowCalendar = Calendar.getInstance();
+        nowCalendar.set(Calendar.HOUR,0);
+        nowCalendar.set(Calendar.MINUTE,0);
+        nowCalendar.set(Calendar.SECOND,0);
+        nowCalendar.set(Calendar.MILLISECOND,0);
+        Calendar tomorrowCalendar = Calendar.getInstance();
+        tomorrowCalendar.setTime(nowCalendar.getTime());
+        tomorrowCalendar.add(Calendar.DAY_OF_YEAR,1);
+        List<PosBookingOrder> bookingOrders = list(Wrappers.<PosBookingOrder>lambdaQuery()
+                .eq(PosBookingOrder::getState, PosBookingStateEnum.NO_ARRIVE.getKey())
+                .ge(PosBookingOrder::getArriveTime, nowCalendar.getTime()).le(PosBookingOrder::getArriveTime,tomorrowCalendar.getTime()));
+        return bookingOrders;
+    }
+}

+ 423 - 70
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/impl/PosOrderGoodsServiceImpl.java

@@ -2,29 +2,26 @@ package org.jeecg.modules.pos.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.lang.Snowflake;
-import cn.hutool.core.util.BooleanUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.commons.lang3.ObjectUtils;
 import org.jeecg.common.exception.JeecgBootException;
 import org.jeecg.common.util.TokenUtils;
-import org.jeecg.modules.business.entity.BusBookingRooms;
-import org.jeecg.modules.business.entity.BusOrderFee;
-import org.jeecg.modules.business.entity.BusOrderFeeGoods;
-import org.jeecg.modules.business.entity.BusRoomsLivingOrder;
+import org.jeecg.modules.business.entity.*;
 import org.jeecg.modules.business.enums.FeeSubjectType;
 import org.jeecg.modules.business.enums.FeeType;
 import org.jeecg.modules.business.service.*;
 import org.jeecg.modules.kc.entity.KcDepositoryInGoods;
 import org.jeecg.modules.kc.service.IKcDepositoryInGoodsService;
-import org.jeecg.modules.pos.entity.PosOrderGoods;
-import org.jeecg.modules.pos.entity.PosOrderGoodsDetail;
-import org.jeecg.modules.pos.entity.PosTable;
+import org.jeecg.modules.pos.PosBookingStateEnum;
+import org.jeecg.modules.pos.TableStateEnum;
+import org.jeecg.modules.pos.entity.*;
 import org.jeecg.modules.pos.mapper.PosOrderGoodsMapper;
 import org.jeecg.modules.pos.service.*;
 import org.jeecg.modules.rooms.entity.CesGoods;
@@ -37,6 +34,7 @@ import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @Description: pos_order_goods
@@ -64,11 +62,15 @@ public class PosOrderGoodsServiceImpl extends ServiceImpl<PosOrderGoodsMapper, P
     private CesGoodsServiceImpl cesGoodsService;
 
     @Resource
-    private  IBusRoomBookingOrdersService busRoomBookingOrdersService;
+    private  IPosBookingService posBookingService;
 
     @Resource
     private IKcDepositoryInGoodsService depositoryInGoodsService;
 
+    @Resource
+    private IPosOrderTeamService posOrderTeamService;
+
+    /**通过桌台id查询订单*/
     @Override
     public PosOrderGoods getOrderByTableId(String tableId) {
         LambdaQueryWrapper<PosOrderGoods> queryWrapper = new LambdaQueryWrapper<PosOrderGoods>()
@@ -83,6 +85,29 @@ public class PosOrderGoodsServiceImpl extends ServiceImpl<PosOrderGoodsMapper, P
     }
 
     @Override
+    public PosOrderGoods getOrderTeamByTableId(String tableId) {
+        LambdaQueryWrapper<PosOrderGoods> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+        lambdaQueryWrapper.eq(PosOrderGoods::getPosTableId, tableId);
+        lambdaQueryWrapper.eq(PosOrderGoods::getStatus, 0);
+        // 还未开台的预约单不显示
+        lambdaQueryWrapper.eq(PosOrderGoods::getIsBooking, 0);
+        lambdaQueryWrapper.orderByDesc(PosOrderGoods::getCreateTime);
+        lambdaQueryWrapper.last("limit 1");
+        lambdaQueryWrapper.orderByDesc(PosOrderGoods::getCreateTime);
+        PosOrderGoods posOrderGood = getOne(lambdaQueryWrapper);
+        if (posOrderGood == null || StrUtil.isEmpty(posOrderGood.getTeamId())){
+            return posOrderGood;
+        }
+        PosOrderTeam team = posOrderTeamService.getById(posOrderGood.getTeamId());
+        if (team != null){
+            posOrderGood.setTeamIndex(team.getSortIndex());
+            posOrderGood.setIsMain(posOrderGood.getId().equals(team.getOrderId()));
+        }
+        return posOrderGood;
+    }
+
+    /**挂房账*/
+    @Override
     public Boolean addRoomFee(PosOrderGoods posOrderGoods,String hotelId) {
         if (posOrderGoods.getToRoomFeeOrderId().isEmpty()){
             throw new JeecgBootException("未找到挂房费的订单");
@@ -150,33 +175,9 @@ public class PosOrderGoodsServiceImpl extends ServiceImpl<PosOrderGoodsMapper, P
     @Override
     public PosOrderGoods addOrder(PosOrderGoods posOrderGoods) {
         // 直接点击结账时id为空
-        if (ObjectUtils.isEmpty(posOrderGoods.getId())) {
-            // 点击结账,且不是桌台 就创建一个新订单
-            if (ObjectUtils.isEmpty(posOrderGoods.getPosTableId())) {
-                // 找出今日最后的一个账单
-                LocalDateTime localDateTime = LocalDateTime.now().withNano(0).withSecond(0).withMinute(0).withHour(0);
-                LocalDateTime[] arr = new LocalDateTime[]{localDateTime, localDateTime.withHour(23).withMinute(59)};
-                LambdaQueryWrapper<PosOrderGoods> lambdaQueryWrapper = new LambdaQueryWrapper<>();
-                lambdaQueryWrapper.eq(PosOrderGoods::getHotelId, posOrderGoods.getHotelId());
-                lambdaQueryWrapper.ge(PosOrderGoods::getCreateTime, arr[0]);
-                lambdaQueryWrapper.le(PosOrderGoods::getCreateTime, arr[1]);
-                lambdaQueryWrapper.and(o -> o.isNull(PosOrderGoods::getPosTableId).or().eq(PosOrderGoods::getPosTableId,""));
-                Page<PosOrderGoods> page = new Page<>(1, 1);
-                lambdaQueryWrapper.orderByDesc(PosOrderGoods::getCreateTime);
-                IPage<PosOrderGoods> pageList = page(page, lambdaQueryWrapper);
-                // 设置取餐号
-                if (ObjectUtils.isNotEmpty(pageList.getRecords())) {
-                    String no = pageList.getRecords().get(0).getTableNo();
-                    try {
-                        Integer newNo = Integer.parseInt(no) + 1;
-                        posOrderGoods.setTableNo(String.format("%03d", newNo));
-                    } catch (NumberFormatException ex) {
-                        posOrderGoods.setTableNo("001");
-                    }
-                } else {
-                    posOrderGoods.setTableNo("001");
-                }
-            }
+        if (StrUtil.isEmpty(posOrderGoods.getId())) {
+            // 创建取餐号
+            setOrderTableNo(posOrderGoods);
             posOrderGoods.setCode(randomNumber("P"));
         } else {
             // 存在订单(桌台点单,取单支付)
@@ -193,6 +194,374 @@ public class PosOrderGoodsServiceImpl extends ServiceImpl<PosOrderGoodsMapper, P
             posOrderGoods.setTableNo(tableNo);
             posOrderGoods.setIsPending(isPending);
         }
+        // 完善订单和订单详情数据
+        repairOrderGoods(posOrderGoods);
+        // 添加商品消费详情
+        posOrderGoodsDetailService.saveBatch(posOrderGoods.getPosOrderGoodsDetailList());
+        //桌台下单或者挂单时商品减库存
+        for (PosOrderGoodsDetail posOrderGoodsDetail : posOrderGoods.getPosOrderGoodsDetailList()) {
+            // 下单商品时
+            addSellGoods(posOrderGoodsDetail, null);
+            // 下单的是套餐时
+            if (StrUtil.isNotEmpty(posOrderGoodsDetail.getThaliId())){
+                // 添加套餐 出库对象
+                KcDepositoryInGoods depositoryInGoods = addDepositoryInGood(posOrderGoodsDetail);
+                depositoryInGoods.setNum(-depositoryInGoods.getNum());
+                depositoryInGoodsService.save(depositoryInGoods);
+                // 循环添加套餐下的商品 出库对象
+                posOrderGoodsDetail.getChildDetails().forEach(e -> {
+                    e.setId(String.valueOf(IdWorker.getId()));
+                    e.setParentId(posOrderGoodsDetail.getId());
+                    addSellGoods(e, depositoryInGoods.getId());
+                });
+                // 添加套餐下商品消费详情
+                posOrderGoodsDetailService.saveBatch(posOrderGoodsDetail.getChildDetails());
+            }
+        }
+        // 修改桌台状态
+        LambdaUpdateWrapper<PosTable> lambdaUpdateWrapper=new LambdaUpdateWrapper<>();
+        lambdaUpdateWrapper.eq(PosTable::getId,posOrderGoods.getPosTableId());
+        lambdaUpdateWrapper.set(PosTable::getState,2);
+        posTableService.update(lambdaUpdateWrapper);
+        saveOrUpdate(posOrderGoods);
+        return posOrderGoods;
+    }
+
+
+    /**添加预约单*/
+    @Override
+    public Boolean addBookingOrder(PosBookingOrder bookingOrder) {
+        if (bookingOrder.getArriveTime() == null){
+            throw new JeecgBootException("请选择预约时间");
+        }
+        if (CollUtil.isEmpty(bookingOrder.getTableIds())){
+            throw new JeecgBootException("请选择桌台");
+        }
+        List<PosTable> tableList = posTableService.list(Wrappers.<PosTable>lambdaQuery().in(PosTable::getId, bookingOrder.getTableIds()));
+        if (tableList.size() != bookingOrder.getTableIds().size()){
+            throw new JeecgBootException("未找到桌台");
+        }
+        if (StrUtil.isEmpty(bookingOrder.getId())){
+            bookingOrder.setCode(randomNumber("Y"));
+        }
+        List<PosOrderGoods> orderGoodsList = new ArrayList<>();
+        List<PosOrderGoodsDetail> targetOrderGoodsDetailList = new ArrayList<>();
+        tableList.forEach(e -> {
+            PosOrderGoods posOrderGoods = new PosOrderGoods();
+            posOrderGoods.setIsBooking(true);
+            posOrderGoods.setBookingCode(bookingOrder.getCode());
+            posOrderGoods.setCode(randomNumber("P"));
+            posOrderGoods.setPosTableId(e.getId());
+            posOrderGoods.setPosType(e.getPosTypeId());
+            posOrderGoods.setHotelId(bookingOrder.getHotelId());
+            posOrderGoods.setTenantId(TokenUtils.currentTenantId());
+            BigDecimal amount = new BigDecimal(0);
+            for (PosOrderGoodsDetail posOrderGoodsDetail : bookingOrder.getPosOrderGoodsDetailList()) {
+                PosOrderGoodsDetail targetorderGoodsDetail = new PosOrderGoodsDetail();
+                targetorderGoodsDetail.setGoodsId(posOrderGoodsDetail.getGoodsId());
+                targetorderGoodsDetail.setNum(posOrderGoodsDetail.getNum());
+                targetorderGoodsDetail.setMoney(posOrderGoodsDetail.getMoney());
+                targetorderGoodsDetail.setCouponMoney(posOrderGoodsDetail.getMoney());
+                targetorderGoodsDetail.setPayMoney(posOrderGoodsDetail.getMoney());
+                targetorderGoodsDetail.setOrderId(posOrderGoods.getCode());
+                targetorderGoodsDetail.setTenantId(TokenUtils.currentTenantId());
+                targetorderGoodsDetail.setHotelId(bookingOrder.getHotelId());
+                amount = amount.add(posOrderGoodsDetail.getMoney().multiply(BigDecimal.valueOf(posOrderGoodsDetail.getNum())));
+                targetOrderGoodsDetailList.add(targetorderGoodsDetail);
+            }
+            posOrderGoods.setMoney(amount);
+            orderGoodsList.add(posOrderGoods);
+        });
+        posOrderGoodsDetailService.saveBatch(targetOrderGoodsDetailList);
+        saveBatch(orderGoodsList);
+        return posBookingService.saveOrUpdate(bookingOrder);
+    }
+
+    /***/
+    @Override
+    public PosBookingOrder getBookingOrderById(String bookingOrderId){
+        PosBookingOrder bookingOrder = posBookingService.getById(bookingOrderId);
+        if (bookingOrder == null){
+            throw new JeecgBootException("未找到预约单");
+        }
+        List<PosOrderGoods> orderGoodsList = list(Wrappers.<PosOrderGoods>lambdaQuery().eq(PosOrderGoods::getCode, bookingOrder.getCode()));
+        if (orderGoodsList.isEmpty()){
+            throw new JeecgBootException("未找到相关订单");
+        }
+        List<PosOrderGoodsDetail> goodsDetail = posOrderGoodsDetailService.getGoodsDetail(orderGoodsList.get(0).getCode());
+        bookingOrder.setPosOrderGoodsDetailList(goodsDetail);
+        List<String> tableIds = orderGoodsList.stream().map(PosOrderGoods::getPosTableId).collect(Collectors.toList());
+        if (tableIds.isEmpty()){
+            throw new JeecgBootException("未找到相关桌台");
+        }
+        List<PosTable> tableList = posTableService.listByIds(tableIds);
+        bookingOrder.setTableList(tableList);
+        return bookingOrder;
+    }
+
+    /**编辑预定单*/
+    @Override
+    public Boolean editBookingOrder(PosBookingOrder bookingOrder) {
+        List<PosOrderGoods> orderGoodsList = list(Wrappers.<PosOrderGoods>lambdaQuery()
+                .eq(PosOrderGoods::getBookingCode, bookingOrder.getCode()));
+        List<String> orderGoodsCodes = orderGoodsList.stream().map(PosOrderGoods::getCode).collect(Collectors.toList());
+        List<PosOrderGoodsDetail> goodsDetailList = new ArrayList<>();
+        if (!orderGoodsCodes.isEmpty()){
+            goodsDetailList = posOrderGoodsDetailService.list(Wrappers.<PosOrderGoodsDetail>lambdaQuery()
+                    .in(PosOrderGoodsDetail::getOrderId, orderGoodsCodes));
+        }
+        // 相当于重新添加一次预约单
+        Boolean res = addBookingOrder(bookingOrder);
+        // 删除预约单的关联订单和订单详情
+        if (res){
+            removeBatchByIds(orderGoodsList);
+            posOrderGoodsDetailService.removeBatchByIds(goodsDetailList);
+        }
+        return true;
+    }
+
+
+    /**根据桌号查询今日预约单*/
+    @Override
+    public List<PosBookingOrder> getBookingByTableId(String tableId) {
+        List<PosBookingOrder> bookingOrders = posBookingService.getTodayBooking();
+        if (bookingOrders.isEmpty()){
+            return bookingOrders;
+        }
+        List<String> codes = bookingOrders.stream().map(PosBookingOrder::getCode).collect(Collectors.toList());
+        List<PosOrderGoods> orderGoodsList = list(Wrappers.<PosOrderGoods>lambdaQuery().in(PosOrderGoods::getBookingCode, codes));
+        List<String> findCodes = orderGoodsList.stream().filter(e -> tableId.equals(e.getPosTableId())).map(PosOrderGoods::getBookingCode).collect(Collectors.toList());
+        if (findCodes.isEmpty()){
+            return new ArrayList<>();
+        }
+        return bookingOrders.stream().filter(e -> findCodes.contains(e.getId())).collect(Collectors.toList());
+    }
+
+    /**预定开台*/
+    @Override
+    public Boolean addOrderByBookingId(String bookingId) {
+        PosBookingOrder bookingOrder = posBookingService.getById(bookingId);
+        if (bookingOrder == null){
+            throw new JeecgBootException("未找到预约单");
+        }
+        if (!PosBookingStateEnum.NO_ARRIVE.getKey().equals(bookingOrder.getState())){
+            throw new JeecgBootException(Objects.requireNonNull(PosBookingStateEnum.val(bookingOrder.getState())).getTitle() + "的预定单不能开台");
+        }
+        // 找出预约单下所有订单
+        List<PosOrderGoods> orderGoodsList = list(Wrappers.<PosOrderGoods>lambdaQuery()
+                .eq(PosOrderGoods::getBookingCode, bookingOrder.getCode()).eq(PosOrderGoods::getStatus, 0));
+        List<String> tableId = orderGoodsList.stream().map(PosOrderGoods::getPosTableId).collect(Collectors.toList());
+        if (orderGoodsList.isEmpty() || tableId.isEmpty()){
+            throw new JeecgBootException("未找到预约的订单");
+        }
+        List<PosTable> tableList = posTableService.listByIds(tableId);
+        if (tableList.size() != tableId.size()){
+            throw new JeecgBootException("未找到预约的桌台");
+        }
+        // 预约单中有桌台已经被使用,无法开台
+        List<PosTable> useTables = tableList.stream().filter(e -> !TableStateEnum.EMPTY.getKey().equals(e.getState())).collect(Collectors.toList());
+        if (!useTables.isEmpty()){
+            throw new JeecgBootException("桌台号" + useTables.get(0).getName() + "正在被使用,无法开台");
+        }
+        // 扣减库存,添加销售出库记录
+        List<String> orderGoodsCodes = orderGoodsList.stream().map(PosOrderGoods::getCode).collect(Collectors.toList());
+        List<PosOrderGoodsDetail> targetOrderGoodsDetailList = posOrderGoodsDetailService.list(Wrappers.<PosOrderGoodsDetail>lambdaQuery()
+                .in(PosOrderGoodsDetail::getOrderId, orderGoodsCodes));
+        for (PosOrderGoodsDetail posOrderGoodsDetail : targetOrderGoodsDetailList) {
+            CesGoods cesGoods = cesGoodsService.getById(posOrderGoodsDetail.getGoodsId());
+            if (ObjectUtils.isNotEmpty(cesGoods)) {
+                Integer c = cesGoods.getInventory() - posOrderGoodsDetail.getNum();
+                if (c < 0) {
+                    throw new JeecgBootException(cesGoods.getName() + "库存不足");
+                }
+                cesGoods.setInventory(c);
+                cesGoodsService.updateById(cesGoods);
+                KcDepositoryInGoods depositoryInGoods = addDepositoryInGood(posOrderGoodsDetail);
+                depositoryInGoodsService.addSell(depositoryInGoods);
+            }
+        }
+        // 如果订单下有商品就将房间状态改为待下单,没有商品就改为待结账
+        if (targetOrderGoodsDetailList.isEmpty()) {
+            tableList.forEach(e -> e.setState(TableStateEnum.WILL_ORDER.getKey()));
+        } else {
+            tableList.forEach(e -> e.setState(TableStateEnum.WILL_PAYMENT.getKey()));
+        }
+        posTableService.updateBatchById(tableList);
+        orderGoodsList.forEach(e -> e.setIsBooking(false));
+        updateBatchById(orderGoodsList);
+        bookingOrder.setState(PosBookingStateEnum.ARRIVE.getKey());
+        return posBookingService.updateById(bookingOrder);
+    }
+
+    /**预订单退订*/
+    @Override
+    public Boolean cancelBooking(PosBookingOrder bookingOrder) {
+        PosBookingOrder findBookingOrder = posBookingService.getById(bookingOrder.getId());
+        if (findBookingOrder == null){
+            throw new JeecgBootException("未找到预约单");
+        }
+        findBookingOrder.setState(PosBookingStateEnum.RETRUN_MONEY.getKey());
+        findBookingOrder.setRemark(bookingOrder.getRemark());
+        List<PosOrderGoods> orderGoodsList = list(Wrappers.<PosOrderGoods>lambdaQuery().eq(PosOrderGoods::getBookingCode, findBookingOrder.getCode()));
+        List<String> codes = orderGoodsList.stream().map(PosOrderGoods::getCode).collect(Collectors.toList());
+        List<PosOrderGoodsDetail> goodsDetailList = posOrderGoodsDetailService.list(Wrappers.<PosOrderGoodsDetail>lambdaQuery().in(PosOrderGoodsDetail::getOrderId, codes));
+        goodsDetailList.forEach(e -> {
+            KcDepositoryInGoods depositoryInGoods = addDepositoryInGood(e);
+            cesGoodsService.saleReturn(depositoryInGoods);
+        });
+        return posBookingService.updateById(findBookingOrder);
+    }
+
+    /**联台*/
+    @Override
+    public Boolean mergePosOrder(String hotelId, String mainPosOrderId, List<String> posOrderIds) {
+        PosOrderGoods mainOrderGoods = getById(mainPosOrderId);
+        if (mainOrderGoods == null || mainOrderGoods.getStatus() == 1){
+            throw new JeecgBootException("未找到房间订单");
+        }
+        if (CollUtil.isEmpty(posOrderIds)){
+            throw new JeecgBootException("请选择需要联房的订单");
+        }
+        List<PosOrderGoods> orderGoods = listByIds(posOrderIds);
+        if (orderGoods.size() != posOrderIds.size()){
+            throw new JeecgBootException("未找到需要联房的订单");
+        }
+        if (StrUtil.isEmpty(mainOrderGoods.getTeamId())){
+            PosOrderTeam team = posOrderTeamService.addBusTeams(mainOrderGoods.getHotelId(), mainOrderGoods.getId());
+            mainOrderGoods.setTeamId(team.getId());
+        }
+        // 找出被联台订单的已经联房的组号
+        Set<String> teamIds = orderGoods.stream().map(PosOrderGoods::getTeamId).filter(e -> StrUtil.isNotEmpty(e)
+                && !e.equals(mainOrderGoods.getTeamId())).collect(Collectors.toSet());
+        // 删除联房组
+        posOrderTeamService.update(Wrappers.<PosOrderTeam>lambdaUpdate().in(PosOrderTeam::getId,teamIds).set(PosOrderTeam::getIsDelete,true));
+        // 找出所有订单,包含被联房关联的
+        List<PosOrderGoods> nextOrder = list(Wrappers.<PosOrderGoods>lambdaQuery().in(PosOrderGoods::getTeamId, teamIds));
+        orderGoods.addAll(nextOrder);
+        orderGoods.forEach(e -> e.setTeamId(mainOrderGoods.getTeamId()));
+        orderGoods.add(mainOrderGoods);
+        return updateBatchById(orderGoods);
+    }
+
+    /**取消联台*/
+    @Override
+    public Boolean returnMergePosOrder(String posOrderId) {
+        PosOrderGoods posOrder = getById(posOrderId);
+        if (posOrder == null){
+            throw new JeecgBootException("未找到需要取消联台的订单");
+        }
+        PosOrderTeam team = posOrderTeamService.getById(posOrder.getTeamId());
+        if (team == null || team.getIsDelete()){
+            throw new JeecgBootException("未找到关联号");
+        }
+        List<PosOrderGoods> orderGoodsList = list(Wrappers.<PosOrderGoods>lambdaQuery().eq(PosOrderGoods::getTeamId, team.getId()));
+        if (orderGoodsList.size() <= 2){
+            orderGoodsList.forEach(e -> e.setTeamId(""));
+            team.setIsDelete(true);
+        }
+        posOrderTeamService.updateById(team);
+        return updateBatchById(orderGoodsList);
+    }
+
+    /**换桌*/
+    @Override
+    public Boolean changeTable(String posOrderId, String tableId) {
+        PosOrderGoods orderGoods = getById(posOrderId);
+        if (orderGoods == null){
+            throw new JeecgBootException("未找到订单");
+        }
+        PosTable posTable = posTableService.getById(tableId);
+        if (posTable == null){
+            throw new JeecgBootException("未找到要换的桌台");
+        }
+        if (!TableStateEnum.EMPTY.getKey().equals(posTable.getState())){
+            throw new JeecgBootException("要换的桌台不是空桌");
+        }
+        PosTable originalTable = posTableService.getById(orderGoods.getPosTableId());
+        if (originalTable == null){
+            throw new JeecgBootException("未找到要换原桌台");
+        }
+        orderGoods.setPosTableId(posTable.getId());
+        posTable.setState(originalTable.getState());
+        posTable.setState(TableStateEnum.WILL_CLEAN.getKey());
+        ArrayList<PosTable> posTableList = new ArrayList<>();
+        posTableList.add(posTable);
+        posTableList.add(originalTable);
+        posTableService.updateBatchById(posTableList);
+        return updateById(orderGoods);
+    }
+
+    /**转菜*/
+    @Override
+    public Boolean transferDishes(String posOrderId, List<String> orderGoodsDetailIds) {
+        if (CollUtil.isEmpty(orderGoodsDetailIds)){
+            return true;
+        }
+        PosOrderGoods orderGoods = getById(posOrderId);
+        if (orderGoods == null){
+            throw new JeecgBootException("未找到目标桌台订单");
+        }
+        List<PosOrderGoodsDetail> orderGoodsDetailList = posOrderGoodsDetailService.listByIds(orderGoodsDetailIds);
+        if (orderGoodsDetailList.size() != orderGoodsDetailIds.size()){
+            throw new JeecgBootException("未找到需要转菜的商品");
+        }
+        orderGoodsDetailList.forEach(e -> e.setOrderId(orderGoods.getId()));
+        // TODO: 2023/11/7 当桌台菜全部转走时,是否要改变桌台状态
+        return posOrderGoodsDetailService.updateBatchById(orderGoodsDetailList);
+    }
+
+
+    /**设置订单的桌号/取餐号*/
+    private void setOrderTableNo(PosOrderGoods posOrderGoods) {
+        if (StrUtil.isEmpty(posOrderGoods.getPosTableId())) {
+            // 找出今日最后的一个账单
+            LocalDateTime localDateTime = LocalDateTime.now().withNano(0).withSecond(0).withMinute(0).withHour(0);
+            LocalDateTime[] arr = new LocalDateTime[]{localDateTime, localDateTime.withHour(23).withMinute(59)};
+            LambdaQueryWrapper<PosOrderGoods> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+            lambdaQueryWrapper.eq(PosOrderGoods::getHotelId, posOrderGoods.getHotelId());
+            lambdaQueryWrapper.ge(PosOrderGoods::getCreateTime, arr[0]);
+            lambdaQueryWrapper.le(PosOrderGoods::getCreateTime, arr[1]);
+            lambdaQueryWrapper.and(o -> o.isNull(PosOrderGoods::getPosTableId).or().eq(PosOrderGoods::getPosTableId,""));
+            Page<PosOrderGoods> page = new Page<>(1, 1);
+            lambdaQueryWrapper.orderByDesc(PosOrderGoods::getCreateTime);
+            IPage<PosOrderGoods> pageList = page(page, lambdaQueryWrapper);
+            // 设置取餐号
+            if (ObjectUtils.isNotEmpty(pageList.getRecords())) {
+                String no = pageList.getRecords().get(0).getTableNo();
+                try {
+                    Integer newNo = Integer.parseInt(no) + 1;
+                    posOrderGoods.setTableNo(String.format("%03d", newNo));
+                } catch (NumberFormatException ex) {
+                    posOrderGoods.setTableNo("001");
+                }
+            } else {
+                posOrderGoods.setTableNo("001");
+            }
+        }
+
+    }
+
+    /**增加订单详情,创建出库记录,扣减库存*/
+    private void addSellGoods(PosOrderGoodsDetail posOrderGoodsDetail, String parentId) {
+        if (StrUtil.isNotEmpty(posOrderGoodsDetail.getGoodsId())){
+            CesGoods cesGoods = cesGoodsService.getById(posOrderGoodsDetail.getGoodsId());
+            if (ObjectUtils.isNotEmpty(cesGoods)) {
+                Integer c = cesGoods.getInventory() - posOrderGoodsDetail.getNum();
+                if (c < 0) {
+                    throw new JeecgBootException(cesGoods.getName() + "库存不足");
+                }
+                cesGoods.setInventory(c);
+                cesGoodsService.updateById(cesGoods);
+                KcDepositoryInGoods depositoryInGoods = addDepositoryInGood(posOrderGoodsDetail);
+                depositoryInGoods.setParentId(parentId);
+                depositoryInGoodsService.addSell(depositoryInGoods);
+            }
+        }
+
+    }
+
+    /**完善订单数据*/
+    private void repairOrderGoods(PosOrderGoods posOrderGoods) {
         posOrderGoods.setTenantId(TokenUtils.currentTenantId());
         BigDecimal amount = BigDecimal.ZERO;
         if (ObjectUtil.isNotEmpty(posOrderGoods.getMoney())){
@@ -200,53 +569,37 @@ public class PosOrderGoodsServiceImpl extends ServiceImpl<PosOrderGoodsMapper, P
         }
         for (PosOrderGoodsDetail posOrderGoodsDetail : posOrderGoods.getPosOrderGoodsDetailList()) {
             amount = amount.add(posOrderGoodsDetail.getMoney().multiply(BigDecimal.valueOf(posOrderGoodsDetail.getNum())));
-            posOrderGoodsDetail.setTenantId(posOrderGoods.getTenantId());
-            posOrderGoodsDetail.setHotelId(posOrderGoods.getHotelId());
-            posOrderGoodsDetail.setOrderId(posOrderGoods.getCode());
-            posOrderGoodsDetail.setCouponMoney(posOrderGoodsDetail.getMoney());
-            posOrderGoodsDetail.setPayMoney(posOrderGoodsDetail.getMoney());
-            posOrderGoodsDetail.setOrderId(posOrderGoods.getCode());
+            repairOrderGoodsDetail(posOrderGoodsDetail, posOrderGoods);
+            // 订单详情为套餐时
+            if (CollUtil.isNotEmpty(posOrderGoodsDetail.getChildDetails())) {
+                posOrderGoodsDetail.getChildDetails().forEach(e -> repairOrderGoodsDetail(e,posOrderGoods));
+                repairOrderGoodsDetail(posOrderGoodsDetail, posOrderGoods);
+            }
         }
         posOrderGoods.setMoney(amount);
         posOrderGoods.setConsumeMoney(amount);
         posOrderGoods.setCreateTime(new Date());
-
-        if (ObjectUtils.isNotEmpty(posOrderGoods.getToRoomFeeOrderId())) {
+        if (StrUtil.isNotEmpty(posOrderGoods.getToRoomFeeOrderId())) {
             posOrderGoods.setStatus(1);
             posOrderGoods.setSettleTime(new Date());
             posOrderGoods.setPayInfo("挂房账");
-
         }
-        Boolean res = saveOrUpdate(posOrderGoods);
-        if (res) {
-            res = posOrderGoodsDetailService.saveBatch(posOrderGoods.getPosOrderGoodsDetailList());
-            if (res && (ObjectUtils.isNotEmpty(posOrderGoods.getPosTableId()) || StrUtil.isNotEmpty(posOrderGoods.getToRoomFeeOrderId()))) {
-                //桌台下单或者挂单时商品减库存
-                for (PosOrderGoodsDetail posOrderGoodsDetail : posOrderGoods.getPosOrderGoodsDetailList()) {
-                    CesGoods cesGoods = cesGoodsService.getById(posOrderGoodsDetail.getGoodsId());
-                    if (ObjectUtils.isNotEmpty(cesGoods)) {
-                        Integer c = cesGoods.getInventory() - posOrderGoodsDetail.getNum();
-                        if (c < 0) {
-                            c = 0;
-                        }
-                        cesGoods.setInventory(c);
-                        cesGoodsService.updateById(cesGoods);
-                        KcDepositoryInGoods depositoryInGoods = addDepositoryInGood(posOrderGoodsDetail);
-                        depositoryInGoodsService.addSell(depositoryInGoods);
-                    }
-                }
-            }
-            LambdaUpdateWrapper<PosTable> lambdaUpdateWrapper=new LambdaUpdateWrapper<>();
-            lambdaUpdateWrapper.eq(PosTable::getId,posOrderGoods.getPosTableId());
-            lambdaUpdateWrapper.set(PosTable::getState,2);
-            posTableService.update(lambdaUpdateWrapper);
-        }
-        return posOrderGoods;
     }
 
+    /**完善订单详情数据*/
+    private void repairOrderGoodsDetail(PosOrderGoodsDetail posOrderGoodsDetail, PosOrderGoods posOrderGoods){
+        posOrderGoodsDetail.setTenantId(posOrderGoods.getTenantId());
+        posOrderGoodsDetail.setHotelId(posOrderGoods.getHotelId());
+        posOrderGoodsDetail.setCouponMoney(posOrderGoodsDetail.getMoney());
+        posOrderGoodsDetail.setPayMoney(posOrderGoodsDetail.getMoney());
+        posOrderGoodsDetail.setOrderId(posOrderGoods.getCode());
+    }
+
+
     public KcDepositoryInGoods addDepositoryInGood(PosOrderGoodsDetail orderGoodsDetail){
         KcDepositoryInGoods depositoryInGoods = new KcDepositoryInGoods();
         depositoryInGoods.setGoodsId(orderGoodsDetail.getGoodsId());
+        depositoryInGoods.setThaliId(orderGoodsDetail.getThaliId());
         depositoryInGoods.setNum(orderGoodsDetail.getNum());
         depositoryInGoods.setFeeGoodId(orderGoodsDetail.getId());
         depositoryInGoods.setHotelId(orderGoodsDetail.getHotelId());

+ 34 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/impl/PosOrderTeamImpl.java

@@ -0,0 +1,34 @@
+package org.jeecg.modules.pos.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.jeecg.modules.pos.entity.PosOrderTeam;
+import org.jeecg.modules.pos.mapper.PosOrderTeamMapper;
+import org.jeecg.modules.pos.service.IPosOrderTeamService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+public class PosOrderTeamImpl extends ServiceImpl<PosOrderTeamMapper,PosOrderTeam> implements IPosOrderTeamService {
+    @Override
+    public PosOrderTeam addBusTeams(String hotelId, String orderId) {
+        PosOrderTeam team = new PosOrderTeam();
+        List<PosOrderTeam> existTeams = list(Wrappers.<PosOrderTeam>query().eq("is_delete", 0).eq("hotel_id", hotelId)); // 1团队房,2联房
+        Integer sortIndex = 1;
+        List<Integer> indexs = existTeams.stream().map(s->s.getSortIndex()).collect(Collectors.toList());
+        while(true){
+            Integer finalSortIndex = sortIndex;
+            if(indexs.stream().filter(s->s.equals(finalSortIndex)).count() == 0) {
+                break;
+            }
+            sortIndex++;
+        }
+        team.setOrderId(orderId);
+        team.setHotelId(hotelId);
+        team.setSortIndex(sortIndex);
+        save(team);
+        return team;
+    }
+}

+ 7 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/pos/service/impl/PosThaliInGoodsServiceImpl.java

@@ -3,10 +3,13 @@ package org.jeecg.modules.pos.service.impl;
 import org.jeecg.modules.pos.entity.PosThaliInGoods;
 import org.jeecg.modules.pos.mapper.PosThaliInGoodsMapper;
 import org.jeecg.modules.pos.service.IPosThaliInGoodsService;
+import org.jeecg.modules.rooms.Vo.CesGoodsVo;
 import org.springframework.stereotype.Service;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 
+import java.util.List;
+
 /**
  * @Description: pos_thali_in_goods
  * @Author: jeecg-boot
@@ -16,4 +19,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 @Service
 public class PosThaliInGoodsServiceImpl extends ServiceImpl<PosThaliInGoodsMapper, PosThaliInGoods> implements IPosThaliInGoodsService {
 
+    @Override
+    public List<CesGoodsVo> getThaliInGoodsDetail(List<String> thaliIds) {
+        return baseMapper.getThaliInGoodsDetail(thaliIds);
+    }
 }