Merge remote-tracking branch 'origin/test' into dev

This commit is contained in:
Tankaikai
2024-12-17 10:09:13 +08:00
51 changed files with 1685 additions and 142 deletions

16
pom.xml
View File

@@ -21,7 +21,17 @@
</properties>
<dependencies>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.3</version>
</dependency>
<!-- zxing生成二维码 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
@@ -205,10 +215,6 @@
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>

View File

@@ -0,0 +1,15 @@
package com.chaozhanggui.system.cashierservice.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}

View File

@@ -140,7 +140,15 @@ public class OrderController {
String userId = jsonObject.getString("accountId");
orderVo.setMerchantId(Integer.valueOf(userId));
orderVo.setUserId(jsonObject.getString("staffId"));
return orderService.createOrder(orderVo, clientType, token, null);
return orderService.createOrder(orderVo, clientType, token, null, true);
}
/**
* 转台并台
*/
@PutMapping("/switch")
public Result switchTable(@Validated @RequestBody SwitchTableDTO switchTableDTO, @RequestHeader("token") String token) {
return Result.success(CodeEnum.SUCCESS, orderService.switchTable(switchTableDTO, token));
}
@PostMapping("/createBackOrder")

View File

@@ -5,9 +5,13 @@ import com.chaozhanggui.system.cashierservice.entity.dto.ClearTableDTO;
import com.chaozhanggui.system.cashierservice.service.ShopInfoService;
import com.chaozhanggui.system.cashierservice.sign.CodeEnum;
import com.chaozhanggui.system.cashierservice.sign.Result;
import com.chaozhanggui.system.cashierservice.util.AliUploadUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@CrossOrigin(origins = "*")
@RestController
@@ -78,4 +82,9 @@ public class ShopInfoController {
public Result queryPwdInfo(@RequestParam("shopId") String shopId) {
return shopInfoService.queryShopPwdInfo(shopId);
}
@PostMapping("upload")
public Result upload(@RequestParam("file") MultipartFile file) throws Exception {
return Result.success(CodeEnum.SUCCESS, AliUploadUtils.uploadSuffix(file.getInputStream(), file.getOriginalFilename()));
}
}

View File

@@ -0,0 +1,111 @@
package com.chaozhanggui.system.cashierservice.controller;
import com.chaozhanggui.system.cashierservice.entity.dto.calltable.*;
import com.chaozhanggui.system.cashierservice.exception.MsgException;
import com.chaozhanggui.system.cashierservice.service.TbCallService;
import com.chaozhanggui.system.cashierservice.sign.CodeEnum;
import com.chaozhanggui.system.cashierservice.sign.Result;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
/**
* 叫号
*/
@RestController
@RequestMapping("/callTable")
@AllArgsConstructor
public class TbCallTableController {
private static final Logger log = LoggerFactory.getLogger(TbCallTableController.class);
private final TbCallService tbCallService;
@GetMapping
public Result get(@RequestParam(required = false) Integer callTableId, @RequestParam Integer shopId,
@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer size,
@RequestParam(required = false) Integer state) {
return Result.success(CodeEnum.SUCCESS, tbCallService.get(page, size, shopId, callTableId, state));
}
@PostMapping
public Result add(@Validated @RequestBody CallTableDTO addCallTableDTO) {
return Result.success(CodeEnum.SUCCESS, tbCallService.add(addCallTableDTO));
}
@PutMapping
public Result update(@Validated @RequestBody UpdateCallTableDTO callTableDTO) {
return Result.success(CodeEnum.SUCCESS, tbCallService.update(callTableDTO));
}
@DeleteMapping
public Result delete(@Validated @RequestBody BaseCallTableDTO baseCallTableDTO) {
return Result.success(CodeEnum.SUCCESS, tbCallService.delete(baseCallTableDTO));
}
@PostMapping("takeNumber")
public Result takeNumber(@Validated @RequestBody TakeNumberDTO takeNumberDTO) {
return Result.success(CodeEnum.SUCCESS, tbCallService.takeNumber(takeNumberDTO));
}
@GetMapping("takeNumberCode")
public Result takeNumberCode(@RequestParam Integer shopId, @RequestParam Integer callTableId) {
return Result.success(CodeEnum.SUCCESS, tbCallService.takeNumberCode(shopId, callTableId));
}
@PostMapping("call")
public Result call(@Validated @RequestBody CallQueueDTO callQueueDTO) {
try {
return Result.success(CodeEnum.SUCCESS, tbCallService.call(callQueueDTO));
} catch (MsgException e) {
log.error("异常", e);
return Result.success(CodeEnum.SUCCESS, new HashMap<String, Object>() {{
put("state", "0");
put("message", e.getMessage());
}});
}
}
@PutMapping("updateState")
public Result confirm(@Validated @RequestBody UpdateCallQueueDTO updateCallQueueDTO) {
return Result.success(CodeEnum.SUCCESS, tbCallService.updateInfo(updateCallQueueDTO));
}
@GetMapping("queue")
public Result getQueue(@RequestParam Integer shopId, @RequestParam(required = false) Integer callTableId,
@RequestParam(required = false) Integer state, @RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
return Result.success(CodeEnum.SUCCESS, tbCallService.getQueue(shopId, callTableId, state, page, size));
}
@GetMapping("callRecord")
public Result getCallRecord(@RequestParam Integer shopId, @RequestParam(required = false) Integer callTableId,
@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer size) {
return Result.success(CodeEnum.SUCCESS, tbCallService.getCallRecord(shopId, callTableId, page, size));
}
@GetMapping("config")
public Result getConfig(@RequestParam Integer shopId) {
return Result.success(CodeEnum.SUCCESS, tbCallService.getConfig(shopId));
}
@PutMapping("config")
public Result updateConfig(@RequestBody UpdateConfigDTO configDTO) {
return Result.success(CodeEnum.SUCCESS, tbCallService.updateConfig(configDTO));
}
}

View File

@@ -20,7 +20,9 @@ public interface TbProductMapper {
List<TbProduct> selectByShopIdAndShopTypeCheckGrounding(@Param("shopId") String shopId, @Param("categoryId") String categoryId,@Param("commdityName") String commdityName);
List<TbProduct> selectByShopIdAndShopTypeUnGrounding(@Param("shopId") String shopId,@Param("commdityName") String commdityName);
Integer countOrderByshopIdAndProductId(@Param("shopId") String shopId, @Param("productId") String productId, @Param("masterId") String masterId,@Param("day") String day, @Param("tableId") String tableId);
Integer countOrderByshopIdAndProductId(@Param("shopId") String shopId, @Param("productId") String productId,
@Param("masterId") String masterId,@Param("day") String day,
@Param("tableId") String tableId, @Param("useType") String useType);
@Update("update tb_product set stock_number = stock_number - #{num,jdbcType=INTEGER} where id = #{productId}")
void updateStockById(@Param("productId")Integer productId, @Param("num")Integer num);

View File

@@ -8,7 +8,7 @@ import java.io.Serializable;
import java.util.Date;
/**
*
* 叫号配置表
* @TableName tb_call_config
*/
@TableName(value ="tb_call_config")
@@ -65,14 +65,9 @@ public class TbCallConfig implements Serializable {
private Date updateTime;
/**
* 是否过号顺延
* 临近几桌提醒
*/
private Integer isPostpone;
/**
* 顺延号码数量
*/
private Integer postponeNum;
private Integer nearNum;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
@@ -218,31 +213,17 @@ public class TbCallConfig implements Serializable {
}
/**
* 是否过号顺延
* 临近几桌提醒
*/
public Integer getIsPostpone() {
return isPostpone;
public Integer getNearNum() {
return nearNum;
}
/**
* 是否过号顺延
* 临近几桌提醒
*/
public void setIsPostpone(Integer isPostpone) {
this.isPostpone = isPostpone;
}
/**
* 顺延号码数量
*/
public Integer getPostponeNum() {
return postponeNum;
}
/**
* 顺延号码数量
*/
public void setPostponeNum(Integer postponeNum) {
this.postponeNum = postponeNum;
public void setNearNum(Integer nearNum) {
this.nearNum = nearNum;
}
@Override
@@ -267,8 +248,7 @@ public class TbCallConfig implements Serializable {
&& (this.getShopId() == null ? other.getShopId() == null : this.getShopId().equals(other.getShopId()))
&& (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
&& (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()))
&& (this.getIsPostpone() == null ? other.getIsPostpone() == null : this.getIsPostpone().equals(other.getIsPostpone()))
&& (this.getPostponeNum() == null ? other.getPostponeNum() == null : this.getPostponeNum().equals(other.getPostponeNum()));
&& (this.getNearNum() == null ? other.getNearNum() == null : this.getNearNum().equals(other.getNearNum()));
}
@Override
@@ -285,8 +265,7 @@ public class TbCallConfig implements Serializable {
result = prime * result + ((getShopId() == null) ? 0 : getShopId().hashCode());
result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
result = prime * result + ((getIsPostpone() == null) ? 0 : getIsPostpone().hashCode());
result = prime * result + ((getPostponeNum() == null) ? 0 : getPostponeNum().hashCode());
result = prime * result + ((getNearNum() == null) ? 0 : getNearNum().hashCode());
return result;
}
@@ -306,8 +285,7 @@ public class TbCallConfig implements Serializable {
sb.append(", shopId=").append(shopId);
sb.append(", createTime=").append(createTime);
sb.append(", updateTime=").append(updateTime);
sb.append(", isPostpone=").append(isPostpone);
sb.append(", postponeNum=").append(postponeNum);
sb.append(", nearNum=").append(nearNum);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();

View File

@@ -8,7 +8,7 @@ import java.io.Serializable;
import java.util.Date;
/**
*
* 叫号排号表
* @TableName tb_call_queue
*/
@TableName(value ="tb_call_queue")
@@ -109,6 +109,11 @@ public class TbCallQueue implements Serializable {
*/
private String createDay;
/**
* 是否已经顺延 0 未顺延 1已顺延一次 2顺延一次仍然过号
*/
private Integer isPostpone;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
@@ -378,6 +383,20 @@ public class TbCallQueue implements Serializable {
this.createDay = createDay;
}
/**
* 是否已经顺延 0 未顺延 1已顺延一次 2顺延一次仍然过号
*/
public Integer getIsPostpone() {
return isPostpone;
}
/**
* 是否已经顺延 0 未顺延 1已顺延一次 2顺延一次仍然过号
*/
public void setIsPostpone(Integer isPostpone) {
this.isPostpone = isPostpone;
}
@Override
public boolean equals(Object that) {
if (this == that) {
@@ -408,7 +427,8 @@ public class TbCallQueue implements Serializable {
&& (this.getSubState() == null ? other.getSubState() == null : this.getSubState().equals(other.getSubState()))
&& (this.getConfirmTime() == null ? other.getConfirmTime() == null : this.getConfirmTime().equals(other.getConfirmTime()))
&& (this.getCallNum() == null ? other.getCallNum() == null : this.getCallNum().equals(other.getCallNum()))
&& (this.getCreateDay() == null ? other.getCreateDay() == null : this.getCreateDay().equals(other.getCreateDay()));
&& (this.getCreateDay() == null ? other.getCreateDay() == null : this.getCreateDay().equals(other.getCreateDay()))
&& (this.getIsPostpone() == null ? other.getIsPostpone() == null : this.getIsPostpone().equals(other.getIsPostpone()));
}
@Override
@@ -434,6 +454,7 @@ public class TbCallQueue implements Serializable {
result = prime * result + ((getConfirmTime() == null) ? 0 : getConfirmTime().hashCode());
result = prime * result + ((getCallNum() == null) ? 0 : getCallNum().hashCode());
result = prime * result + ((getCreateDay() == null) ? 0 : getCreateDay().hashCode());
result = prime * result + ((getIsPostpone() == null) ? 0 : getIsPostpone().hashCode());
return result;
}
@@ -462,6 +483,7 @@ public class TbCallQueue implements Serializable {
sb.append(", confirmTime=").append(confirmTime);
sb.append(", callNum=").append(callNum);
sb.append(", createDay=").append(createDay);
sb.append(", isPostpone=").append(isPostpone);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();

View File

@@ -122,7 +122,7 @@ public class TbShopPermission extends Model<TbShopPermission> {
* @return 主键值
*/
@Override
protected Serializable pkVal() {
public Serializable pkVal() {
return this.id;
}
}

View File

@@ -70,7 +70,7 @@ public class TbShopStaffPermission extends Model<TbShopStaffPermission> {
* @return 主键值
*/
@Override
protected Serializable pkVal() {
public Serializable pkVal() {
return this.id;
}
}

View File

@@ -0,0 +1,23 @@
package com.chaozhanggui.system.cashierservice.entity.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
public class SwitchTableDTO {
@NotNull
private Integer shopId;
@NotEmpty(message = "取餐码不为空")
private String masterId;
private Integer orderId;
private List<Integer> cartIds;
private Boolean isFull;
@NotEmpty(message = "当前台桌id不为空")
private String currentTableId;
@NotEmpty(message = "目标台桌id不为空")
private String targetTableId;
}

View File

@@ -0,0 +1,13 @@
package com.chaozhanggui.system.cashierservice.entity.dto.calltable;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
public class BaseCallTableDTO {
@NotNull
private Integer callTableId;
@NotNull
private Integer shopId;
}

View File

@@ -0,0 +1,13 @@
package com.chaozhanggui.system.cashierservice.entity.dto.calltable;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
public class CallQueueDTO{
@NotNull
private Integer callQueueId;
@NotNull
private Integer shopId;
}

View File

@@ -0,0 +1,29 @@
package com.chaozhanggui.system.cashierservice.entity.dto.calltable;
import lombok.Data;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Data
public class CallTableDTO {
@NotNull
private Integer shopId;
@NotEmpty
private String name;
private String note;
@NotNull
@Min(1)
private Integer waitTime;
@NotBlank
private String prefix;
@NotNull
@Min(1)
private Integer start;
@Min(1)
private Integer nearNum;
private Integer isPostpone;
private Integer postponeNum;
}

View File

@@ -0,0 +1,18 @@
package com.chaozhanggui.system.cashierservice.entity.dto.calltable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
@EqualsAndHashCode(callSuper = true)
@Data
public class TakeNumberDTO extends BaseCallTableDTO{
private Integer userId;
@NotEmpty
@Pattern(regexp = "^1\\d{10}$|^(0\\d{2,3}-?|\\(0\\d{2,3}\\))?[1-9]\\d{4,7}(-\\d{1,8})?$",message = "手机号码格式错误")
private String phone;
private String note;
private String name;
}

View File

@@ -0,0 +1,15 @@
package com.chaozhanggui.system.cashierservice.entity.dto.calltable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import javax.validation.constraints.NotNull;
@EqualsAndHashCode(callSuper = true)
@Data
@Getter
public class UpdateCallQueueDTO extends CallQueueDTO{
@NotNull
private Integer state;
}

View File

@@ -0,0 +1,23 @@
package com.chaozhanggui.system.cashierservice.entity.dto.calltable;
import lombok.Data;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
@Data
public class UpdateCallTableDTO{
@NotNull
private Integer callTableId;
@NotNull
private Integer shopId;
private String name;
private String note;
@Min(1)
private Integer waitTime;
private String prefix;
@Min(1)
private Integer start;
@Min(1)
private Integer nearNum;
}

View File

@@ -0,0 +1,16 @@
package com.chaozhanggui.system.cashierservice.entity.dto.calltable;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
public class UpdateConfigDTO {
@NotNull
private Integer shopId;
private Integer isOnline;
private String bgCover;
private Integer isPostpone;
private Integer postponeNum;
private Integer nearNum;
}

View File

@@ -0,0 +1,12 @@
package com.chaozhanggui.system.cashierservice.entity.vo;
import com.chaozhanggui.system.cashierservice.entity.TbCallQueue;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class CallRecordVO extends TbCallQueue {
private String tableNote;
private Long sinceAt;
}

View File

@@ -16,12 +16,15 @@ public class CustomFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
log.info(">>>> customFilter init <<<<");
}
public boolean isMultipartRequest(HttpServletRequest request) {
String contentType = request.getContentType();
return contentType != null && contentType.toLowerCase().startsWith("multipart/form-data");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info(">>>> customFilter doFilter start <<<<");
RequestWrapper requestWapper = null;
if (servletRequest instanceof HttpServletRequest) {
if (servletRequest instanceof HttpServletRequest && !isMultipartRequest((HttpServletRequest)servletRequest)) {
requestWapper = new RequestWrapper((HttpServletRequest) servletRequest);
}

View File

@@ -1,5 +1,7 @@
package com.chaozhanggui.system.cashierservice.interceptor;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
@@ -9,73 +11,70 @@ import java.io.*;
public class RequestWrapper extends HttpServletRequestWrapper {
private final String body;
public RequestWrapper(HttpServletRequest request) {
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
InputStream inputStream = null;
try {
// 仅处理普通请求体不影响multipart请求
if (!(request instanceof MultipartHttpServletRequest)) {
inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
int bytesRead;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
body = stringBuilder.toString();
} else {
// 如果是Multipart请求不做处理直接返回
body = null;
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
if (body != null) {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
return new ServletInputStream() {
@Override
public boolean isFinished() {
return byteArrayInputStream.available() == 0;
}
@Override
public boolean isReady() {
return byteArrayInputStream.available() > 0;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
} else {
// 如果是Multipart请求返回空的输入流交给Spring处理
return super.getInputStream();
}
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
if (body != null) {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
} else {
// 如果是Multipart请求返回空的reader
return super.getReader();
}
}
public String getBody() {

View File

@@ -15,6 +15,7 @@ import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@@ -121,7 +122,7 @@ public class SignInterceptor implements HandlerInterceptor {
* @param request
* @return
*/
private Map<String, Object> getParameterMap(HttpServletRequest request) {
private Map<String, Object> getParameterMap(HttpServletRequest request) throws IOException {
RequestWrapper requestWrapper = new RequestWrapper(request);
String body = requestWrapper.getBody();
if (ObjectUtil.isNotEmpty(body)) {

View File

@@ -5,8 +5,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author Administrator
* @description 针对表【tb_call_config】的数据库操作Mapper
* @createDate 2024-09-19 14:35:05
* @description 针对表【tb_call_config(叫号配置表)】的数据库操作Mapper
* @createDate 2024-12-10 10:12:45
* @Entity com.chaozhanggui.system.cashierservice.entity.TbCallConfig
*/
public interface TbCallConfigMapper extends BaseMapper<TbCallConfig> {

View File

@@ -1,16 +1,23 @@
package com.chaozhanggui.system.cashierservice.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chaozhanggui.system.cashierservice.entity.TbCallQueue;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.chaozhanggui.system.cashierservice.entity.vo.CallRecordVO;
import org.apache.ibatis.annotations.Select;
/**
* @author Administrator
* @description 针对表【tb_call_queue】的数据库操作Mapper
* @createDate 2024-09-19 14:35:05
* @description 针对表【tb_call_queue(叫号排号表)】的数据库操作Mapper
* @createDate 2024-12-10 10:12:45
* @Entity com.chaozhanggui.system.cashierservice.entity.TbCallQueue
*/
public interface TbCallQueueMapper extends BaseMapper<TbCallQueue> {
@Select("select a.*, b.note as tableNote, TIMESTAMPDIFF(SECOND, a.create_time, NOW()) as since_at from tb_call_queue a " +
"left join tb_call_table b on a.call_table_id=b.id " +
"where a.shop_id=#{shopId} and a.state in (3, 2, 1) order by a.create_time desc")
Page<CallRecordVO> selectCallRecord(Integer shopId, Integer callTableId, Page<Object> objectPage);
}

View File

@@ -5,8 +5,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author Administrator
* @description 针对表【tb_call_table】的数据库操作Mapper
* @createDate 2024-09-19 14:35:05
* @description 针对表【tb_call_table(叫号桌型表)】的数据库操作Mapper
* @createDate 2024-12-10 10:12:45
* @Entity com.chaozhanggui.system.cashierservice.entity.TbCallTable
*/
public interface TbCallTableMapper extends BaseMapper<TbCallTable> {

View File

@@ -1,5 +1,7 @@
package com.chaozhanggui.system.cashierservice.service;
import cn.hutool.core.comparator.CompareUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
@@ -11,7 +13,10 @@ import com.chaozhanggui.system.cashierservice.mybatis.TbVersionMapper;
import com.chaozhanggui.system.cashierservice.rabbit.RabbitProducer;
import com.chaozhanggui.system.cashierservice.sign.CodeEnum;
import com.chaozhanggui.system.cashierservice.sign.Result;
import com.chaozhanggui.system.cashierservice.util.*;
import com.chaozhanggui.system.cashierservice.util.MD5Util;
import com.chaozhanggui.system.cashierservice.util.RedisCst;
import com.chaozhanggui.system.cashierservice.util.RedisUtil;
import com.chaozhanggui.system.cashierservice.util.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -62,7 +67,6 @@ public class LoginService {
}
if (ObjectUtil.isEmpty(loginReq.getSerialNumber())) {
return Result.fail(CodeEnum.SERIALNUMBER);
}
@@ -92,7 +96,7 @@ public class LoginService {
return Result.fail(CodeEnum.MERCHANTEIXST);
}
TbPlussShopStaff tbPlussShopStaff = tbPlussShopStaffMapper.selectByAccountAndShopId(loginReq.getLoginName(),account.getShopId());
TbPlussShopStaff tbPlussShopStaff = tbPlussShopStaffMapper.selectByAccountAndShopId(loginReq.getLoginName(), account.getShopId());
if (ObjectUtil.isEmpty(tbPlussShopStaff)) {
return Result.fail(CodeEnum.ACCOUNTEIXST);
} else if (!tbPlussShopStaff.getStatus()) {
@@ -120,7 +124,13 @@ public class LoginService {
tbTokenMapper.insert(tbToken);
TbShopInfo shopInfo = tbShopInfoMapper.selectByPrimaryKey(Integer.valueOf(account.getShopId()));
if (shopInfo.getExpireAt() != null) {
Long expireAt = shopInfo.getExpireAt();
Date time = DateUtil.calendar(expireAt).getTime();
if (CompareUtil.compare(time, new Date()) < 0) {
return Result.fail("店铺已到期,请联系区域经理续费");
}
}
redisUtil.saveMessage(key, token, 365 * 24 * 60 * 60);
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
@@ -129,15 +139,21 @@ public class LoginService {
accountMap.put("accountId", account.getId());
accountMap.put("merchantName", account.getAccount());
accountMap.put("loginName", tbPlussShopStaff.getAccount());
accountMap.put("loginAccount",tbPlussShopStaff.getName());
accountMap.put("loginAccount", tbPlussShopStaff.getName());
accountMap.put("clientType", loginReq.getClientType());
accountMap.put("shopId", account.getShopId());
accountMap.put("staffId", tbPlussShopStaff.getId());
accountMap.put("userCode", tbPlussShopStaff.getCode());
accountMap.put("token", token);
accountMap.put("loginTime", System.currentTimeMillis());
accountMap.put("expireDate", "");
if (Objects.nonNull(shopInfo)) {
accountMap.put("shopName", shopInfo.getShopName());
if(shopInfo.getExpireAt() != null) {
Long expireAt = shopInfo.getExpireAt();
Date time = DateUtil.calendar(expireAt).getTime();
accountMap.put("expireDate", DateUtil.formatDateTime(time));
}
}
accountMap.put("uuid", uuid);
accountMap.put("isStaff", "staff".equals(tbPlussShopStaff.getType()));
@@ -153,8 +169,8 @@ public class LoginService {
public TbVersion getCurrentPcVersion() {
LambdaQueryWrapper<TbVersion> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TbVersion::getSource,"PC");
queryWrapper.eq(TbVersion::getSel,1);
queryWrapper.eq(TbVersion::getSource, "PC");
queryWrapper.eq(TbVersion::getSel, 1);
return versionMapper.selectOne(queryWrapper);
}
@@ -162,7 +178,7 @@ public class LoginService {
String key = RedisCst.ONLINE_USER.concat(":").concat(clientType).concat(":").concat(loginName);
String cacheToken = redisUtil.getMessage(key)+"";
String cacheToken = redisUtil.getMessage(key) + "";
TbToken tbToken = tbTokenMapper.selectByToken(token);
@@ -199,32 +215,33 @@ public class LoginService {
}
public Result getShopInfo(String token){
JSONObject jsonObject= TokenUtil.parseParamFromToken(token);
if(Objects.isNull(jsonObject)){
public Result getShopInfo(String token) {
JSONObject jsonObject = TokenUtil.parseParamFromToken(token);
if (Objects.isNull(jsonObject)) {
return Result.fail(CodeEnum.TOKENTERROR);
}
TbShopInfo shopInfo= tbShopInfoMapper.selectByPrimaryKey(Integer.valueOf(jsonObject.getString("shopId")));
TbShopInfo shopInfo = tbShopInfoMapper.selectByPrimaryKey(Integer.valueOf(jsonObject.getString("shopId")));
return Result.success(SUCCESS,shopInfo);
return Result.success(SUCCESS, shopInfo);
}
public Result getStaffDiscount(String token){
public Result getStaffDiscount(String token) {
JSONObject jsonObject= TokenUtil.parseParamFromToken(token);
if(Objects.isNull(jsonObject)){
JSONObject jsonObject = TokenUtil.parseParamFromToken(token);
if (Objects.isNull(jsonObject)) {
return Result.fail(CodeEnum.TOKENTERROR);
}
Integer staffId=Integer.valueOf(jsonObject.getString("staffId"));
Integer staffId = Integer.valueOf(jsonObject.getString("staffId"));
TbPlussShopStaff staff= tbPlussShopStaffMapper.selectByPrimaryKey(staffId);
if(Objects.nonNull(staff)&&Objects.nonNull(staff.getMaxDiscountAmount())){
return Result.success(SUCCESS,staff.getMaxDiscountAmount());
TbPlussShopStaff staff = tbPlussShopStaffMapper.selectByPrimaryKey(staffId);
if (Objects.nonNull(staff) && Objects.nonNull(staff.getMaxDiscountAmount())) {
return Result.success(SUCCESS, staff.getMaxDiscountAmount());
}
return Result.success(SUCCESS, BigDecimal.ZERO);
}
}

View File

@@ -61,5 +61,17 @@ public interface MpCashierCartService extends IService<TbCashierCart> {
* @param statuses 状态
*/
List<TbCashierCart> selectByIds(Integer shopId, Integer orderId, List<Integer> ids, TableConstant.OrderInfo.Status... statuses);
/**
* 根据就餐模式查询购物车信息
* @param shopEatTypeInfoDTO 就餐模式
* @param masterId 取餐码
* @param orderId 订单id
* @param onlySearchPc 只查询pc
* @param statuses 状态
*/
List<TbCashierCart> selectByShopEatTypeAndOrderId(ShopEatTypeInfoDTO shopEatTypeInfoDTO, String masterId, Integer orderId, boolean onlySearchPc, TableConstant.OrderInfo.Status... statuses);
Long countByShopEatType(ShopEatTypeInfoDTO shopEatTypeInfoDTO, String masterId, Integer orderId, boolean onlySearchPc, TableConstant.OrderInfo.Status... statuses);
}

View File

@@ -15,5 +15,12 @@ import java.util.List;
*/
public interface MpShopTableService extends IService<TbShopTable> {
/**
* 查询台桌信息
* @param tableId 台桌id
* @param shopId 店铺id
* @return 台桌信息
*/
TbShopTable selectByTableId(String tableId, Integer shopId);
}

View File

@@ -884,7 +884,7 @@ public class OrderService {
}
@Transactional(rollbackFor = Exception.class)
public Result createOrder(OrderVo orderVo, String clientType, String token, Integer oldOrderId) {
public Result createOrder(OrderVo orderVo, String clientType, String token, Integer oldOrderId, boolean isPrint) {
TbShopInfo shopInfo = tbShopInfoMapper.selectByPrimaryKey(orderVo.getShopId());
if (shopInfo == null) {
throw new MsgException("店铺信息不存在");
@@ -962,9 +962,12 @@ public class OrderService {
Integer mealNum = null;
Integer orderId = null;
int cartCount = 0;
boolean hasNewCart = false;
for (TbCashierCart cart : list) {
if (cart.getOrderId() != null) {
orderId = cart.getOrderId();
}else {
hasNewCart = true;
}
cashierIds.add(cart.getId());
if ("-999".equals(cart.getProductId())) {
@@ -1127,7 +1130,7 @@ public class OrderService {
orderInfo.setPackFee(packAMount);
orderInfo.setSendType(eatTypeInfoDTO.getSendType());
// 堂食自取增加下单次数
if (eatTypeInfoDTO.isDineInAfter()) {
if (eatTypeInfoDTO.isDineInAfter() && hasNewCart) {
orderInfo.setPlaceNum(currentPlaceNum);
}
mPOrderInfoMapper.updateById(orderInfo);
@@ -1204,15 +1207,19 @@ public class OrderService {
// 代课下单
mpShopTableMapper.update(null, new LambdaUpdateWrapper<TbShopTable>()
.eq(TbShopTable::getQrcode, orderInfo.getTableId())
.set(TbShopTable::getProductNum, cashierIds.isEmpty() ? 0 : cashierIds.size())
.set(TbShopTable::getTotalAmount, orderInfo.getOrderAmount())
.set(TbShopTable::getRealAmount, orderInfo.getOrderAmount())
.set(TbShopTable::getUseNum, mealNum)
.set(TbShopTable::getStatus, TableStateEnum.USING.getState()));
// 打印票据
if (!addOrderDetailList.isEmpty()) {
if (!addOrderDetailList.isEmpty() && isPrint) {
log.info("待打印菜品信息: {}", addOrderDetailList);
rabbitMsgUtils.printDishesTicket(orderInfo.getId(), false, addOrderDetailList.toArray(new TbOrderDetail[0]));
}
if (!removedOrderDetailList.isEmpty()) {
if (!removedOrderDetailList.isEmpty() && isPrint) {
log.info("待打印退菜菜品信息: {}", removedOrderDetailList);
// 退单票
rabbitMsgUtils.printDishesTicket(orderInfo.getId(), true, removedOrderDetailList.toArray(new TbOrderDetail[0]));
@@ -1375,7 +1382,7 @@ public class OrderService {
orderVo.setTableId(tableId);
JSONObject jsonObject = TokenUtil.parseParamFromToken(token);
orderVo.setMerchantId(Integer.valueOf(jsonObject.getString("accountId")));
Result result = createOrder(orderVo, clientType, token, null);
Result result = createOrder(orderVo, clientType, token, null, true);
if (!"0".equals(result.getCode())) {
return result;
}
@@ -1526,9 +1533,13 @@ public class OrderService {
mpCashierCartMapper.deleteBatchIds(ids);
}
mpShopTableMapper.update(null, new LambdaUpdateWrapper<TbShopTable>()
.eq(TbShopTable::getQrcode, cartVo.getTableId())
.set(TbShopTable::getStatus, TableStateEnum.IDLE.getState()));
Long count = mpCashierCartService.countByShopEatType(shopEatTypeInfoDTO, cartVo.getMasterId(), orderId > 0 ? orderId : null, false, TableConstant.OrderInfo.Status.CREATE, TableConstant.OrderInfo.Status.RETURN);
if (count == 0) {
mpShopTableMapper.update(null, new LambdaUpdateWrapper<TbShopTable>()
.eq(TbShopTable::getQrcode, cartVo.getTableId())
.set(TbShopTable::getStatus, TableStateEnum.IDLE.getState()));
}
// 打印退款票据
int finalOrderId = orderId;
@@ -2392,4 +2403,130 @@ public class OrderService {
return Result.success(CodeEnum.SUCCESS);
}
@Transactional(rollbackFor = Exception.class)
public Object switchTable(SwitchTableDTO switchTableDTO, String token) {
// 查询当前台桌信息
ShopEatTypeInfoDTO shopEatTypeInfoDTO = checkEatModel(switchTableDTO.getShopId(), switchTableDTO.getCurrentTableId());
ShopEatTypeInfoDTO targetShopEatTypeInfoDTO = checkEatModel(switchTableDTO.getShopId(), switchTableDTO.getTargetTableId());
if (!shopEatTypeInfoDTO.isDineInAfter()) {
throw new MsgException("仅后付费模式支持转台");
}
TbShopTable shopTable = mpShopTableService.selectByTableId(switchTableDTO.getTargetTableId(), switchTableDTO.getShopId());
if (shopTable == null) {
throw new MsgException("目标台桌信息不存在");
}
if (TableConstant.ShopTable.State.CLEANING.getValue().equals(shopTable.getStatus())) {
throw new MsgException("当前台桌清理中,不能转台");
}
List<TbCashierCart> cashierCarts;
long totalSize = 99999;
if (switchTableDTO.getIsFull() != null && switchTableDTO.getIsFull()) {
cashierCarts = mpCashierCartService.selectByShopEatTypeAndOrderId(shopEatTypeInfoDTO, switchTableDTO.getMasterId(), switchTableDTO.getOrderId(),
true, TableConstant.OrderInfo.Status.CREATE, TableConstant.OrderInfo.Status.RETURN);
}else {
if (switchTableDTO.getCartIds().isEmpty()) {
throw new MsgException("请选择转单商品");
}
totalSize = mpCashierCartService.countByShopEatType(shopEatTypeInfoDTO, switchTableDTO.getMasterId(), switchTableDTO.getOrderId(),
true, TableConstant.OrderInfo.Status.CREATE, TableConstant.OrderInfo.Status.RETURN);
cashierCarts = mpCashierCartService.selectByIds(switchTableDTO.getShopId(), null, switchTableDTO.getCartIds(),
TableConstant.OrderInfo.Status.CREATE, TableConstant.OrderInfo.Status.RETURN);
}
if (cashierCarts.isEmpty()) {
throw new MsgException("当前台桌购物车为空");
}
String masterId = ((JSONObject)createCode(switchTableDTO.getShopId().toString(), "pc", "", "0", switchTableDTO.getTargetTableId()).getData()).getString("code");
// String masterId = getMasterId(switchTableDTO.getShopId(), switchTableDTO.getTargetTableId(), null).getString("masterId");
// 查询目标购物车
List<TbCashierCart> targetCarts = mpCashierCartService.selectByShopEatTypeAndOrderId(targetShopEatTypeInfoDTO, masterId, null, false);
TbCashierCart targetSeatFee = null;
Integer targetOrderId = null;
for (TbCashierCart targetCart : targetCarts) {
if (TableConstant.CART_SEAT_ID.equals(targetCart.getProductId())) {
targetSeatFee = targetCart;
}
if (targetCart.getOrderId() != null) {
targetOrderId = targetCart.getOrderId();
}
}
// 修改原有购物车数据
ArrayList<Integer> cartIds = new ArrayList<>();
Integer orderId = switchTableDTO.getOrderId();
TbCashierCart currentSeatFee = null;
ArrayList<TbCashierCart> updateCartInfos = new ArrayList<>();
for (TbCashierCart item : cashierCarts) {
if (item.getOrderId() == null) {
throw new MsgException("未下单商品不允许转台并台");
}
if (targetSeatFee == null || !TableConstant.CART_SEAT_ID.equals(item.getProductId())) {
item.setTableId(switchTableDTO.getTargetTableId());
item.setMasterId(masterId);
updateCartInfos.add(item);
}
cartIds.add(item.getId());
if (item.getOrderId() != null) {
orderId = item.getOrderId();
}
if (TableConstant.CART_SEAT_ID.equals(item.getProductId())) {
currentSeatFee = item;
}
}
if (currentSeatFee != null && targetSeatFee != null) {
targetSeatFee.setNumber(currentSeatFee.getNumber().add(targetSeatFee.getNumber()));
targetSeatFee.setTotalNumber(currentSeatFee.getTotalNumber().add(targetSeatFee.getTotalNumber()));
targetSeatFee.setTotalAmount(targetSeatFee.getSalePrice().multiply(targetSeatFee.getTotalNumber()));
mpCashierCartService.updateById(targetSeatFee);
mpCashierCartService.removeById(currentSeatFee.getId());
}
mpCashierCartService.updateBatchById(updateCartInfos);
mpCashierCartService.update(new LambdaUpdateWrapper<TbCashierCart>()
.in(TbCashierCart::getId, cartIds)
.set(TbCashierCart::getOrderId, null)
.set(TbCashierCart::getPlaceNum, null));
mpOrderDetailService.removeByCartIds(cartIds);
// 删除原有台桌detail和order信息
if (orderId != null && ((switchTableDTO.getIsFull() != null && switchTableDTO.getIsFull()) || switchTableDTO.getCartIds().size() == totalSize)) {
mpOrderInfoService.removeById(orderId);
}
if (switchTableDTO.getIsFull() != null && !switchTableDTO.getIsFull() && switchTableDTO.getCartIds().size() != totalSize){
// 重新创建订单数据
OrderVo createOrderDTO = new OrderVo();
createOrderDTO.setMasterId(switchTableDTO.getMasterId());
createOrderDTO.setShopId(switchTableDTO.getShopId());
createOrderDTO.setTableId(switchTableDTO.getCurrentTableId());
JSONObject jsonObject = TokenUtil.parseParamFromToken(token);
String userId = jsonObject.getString("accountId");
createOrderDTO.setMerchantId(Integer.valueOf(userId));
createOrder(createOrderDTO, "pc", token, switchTableDTO.getOrderId(), false);
}
if (targetOrderId != null) {
// 重新创建订单数据
OrderVo createOrderDTO = new OrderVo();
createOrderDTO.setMasterId(masterId);
createOrderDTO.setShopId(switchTableDTO.getShopId());
createOrderDTO.setTableId(switchTableDTO.getTargetTableId());
JSONObject jsonObject = TokenUtil.parseParamFromToken(token);
String userId = jsonObject.getString("accountId");
createOrderDTO.setMerchantId(Integer.valueOf(userId));
createOrder(createOrderDTO, "pc", token, targetOrderId, false);
}
return true;
}
}

View File

@@ -7,6 +7,7 @@ import com.chaozhanggui.system.cashierservice.dao.*;
import com.chaozhanggui.system.cashierservice.entity.*;
import com.chaozhanggui.system.cashierservice.entity.dto.ProductStatusDTO;
import com.chaozhanggui.system.cashierservice.entity.dto.ProductStockDTO;
import com.chaozhanggui.system.cashierservice.entity.dto.ShopEatTypeInfoDTO;
import com.chaozhanggui.system.cashierservice.entity.vo.ProductGroupVo;
import com.chaozhanggui.system.cashierservice.entity.vo.ShopCategoryVo;
import com.chaozhanggui.system.cashierservice.exception.MsgException;
@@ -15,9 +16,11 @@ import com.chaozhanggui.system.cashierservice.mapper.MpShopUnitMapper;
import com.chaozhanggui.system.cashierservice.rabbit.RabbitProducer;
import com.chaozhanggui.system.cashierservice.sign.CodeEnum;
import com.chaozhanggui.system.cashierservice.sign.Result;
import com.chaozhanggui.system.cashierservice.util.BeanUtil;
import com.chaozhanggui.system.cashierservice.util.DateUtils;
import com.chaozhanggui.system.cashierservice.util.JSONUtil;
import com.chaozhanggui.system.cashierservice.util.PageHelperUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -55,6 +58,9 @@ public class ProductService {
private TbShopUnitMapper tbShopUnitMapper;
@Autowired
private MpShopUnitMapper mpShopUnitMapper;
private MpCashierCartService cashierCartService;
@Autowired
private OrderService orderService;
public ProductService(RabbitProducer producer) {
this.producer = producer;
@@ -87,7 +93,7 @@ public class ProductService {
String day = DateUtils.getDay();
if(ObjectUtil.isNotEmpty(tbProductWithBLOBs)){
tbProductWithBLOBs.parallelStream().forEach(it->{
Integer orderCount=tbProductMapper.countOrderByshopIdAndProductId(it.getShopId(),it.getId().toString(),masterId,day, "");
Integer orderCount=tbProductMapper.countOrderByshopIdAndProductId(it.getShopId(),it.getId().toString(),masterId,day, "", null);
it.setOrderCount((ObjectUtil.isNull(orderCount)||ObjectUtil.isEmpty(orderCount))?0:orderCount);
TbProductSpec tbProductSpec= tbProductSpecMapper.selectByPrimaryKey(it.getSpecId());
if(ObjectUtil.isEmpty(tbProductSpec)){
@@ -118,7 +124,8 @@ public class ProductService {
public Result queryNewCommodityInfo(String shopId, String categoryId, String commdityName, String tableId, int page, int pageSize, String masterId) {
List<TbProduct> tbProductWithBLOBs=null;
PageHelperUtil.startPage(page,pageSize);
PageHelperUtil.startPage(page, pageSize);
if(ObjectUtil.isEmpty(categoryId)){
tbProductWithBLOBs=tbProductMapper.selectByShopIdAndCheckGrounding(shopId,commdityName);
}else {
@@ -139,10 +146,11 @@ public class ProductService {
));
}
String day = DateUtils.getDay();
ShopEatTypeInfoDTO shopEatTypeInfoDTO = orderService.checkEatModel(shopId, tableId);
if(ObjectUtil.isNotEmpty(tbProductWithBLOBs)){
Map<String, TbShopUnit> finalShopUnitsMap = shopUnitsMap;
tbProductWithBLOBs.parallelStream().forEach(it->{
Integer orderCount=tbProductMapper.countOrderByshopIdAndProductId(it.getShopId(),it.getId().toString(),masterId,day, tableId);
Integer orderCount=tbProductMapper.countOrderByshopIdAndProductId(it.getShopId(),it.getId().toString(),masterId,day, tableId, shopEatTypeInfoDTO.getUseType());
it.setOrderCount((ObjectUtil.isNull(orderCount)||ObjectUtil.isEmpty(orderCount))?0:orderCount);
TbProductSpec tbProductSpec= tbProductSpecMapper.selectByPrimaryKey(it.getSpecId());
if(ObjectUtil.isEmpty(tbProductSpec)){
@@ -165,6 +173,7 @@ public class ProductService {
});
}
PageInfo pageInfo=new PageInfo(tbProductWithBLOBs);
pageInfo.setList(page <= pageInfo.getNavigateLastPage() ? pageInfo.getList() : new ArrayList());
return Result.success(CodeEnum.SUCCESS,pageInfo);
}

View File

@@ -0,0 +1,13 @@
package com.chaozhanggui.system.cashierservice.service;
import com.chaozhanggui.system.cashierservice.entity.TbCallConfig;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author Administrator
* @description 针对表【tb_call_config(叫号配置表)】的数据库操作Service
* @createDate 2024-12-10 10:12:45
*/
public interface TbCallConfigService extends IService<TbCallConfig> {
}

View File

@@ -0,0 +1,13 @@
package com.chaozhanggui.system.cashierservice.service;
import com.chaozhanggui.system.cashierservice.entity.TbCallQueue;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author Administrator
* @description 针对表【tb_call_queue(叫号排号表)】的数据库操作Service
* @createDate 2024-12-10 10:12:45
*/
public interface TbCallQueueService extends IService<TbCallQueue> {
}

View File

@@ -0,0 +1,30 @@
package com.chaozhanggui.system.cashierservice.service;
import com.chaozhanggui.system.cashierservice.entity.dto.calltable.*;
public interface TbCallService {
Object add(CallTableDTO addCallTableDTO);
Object update(UpdateCallTableDTO callTableDTO);
Object delete(BaseCallTableDTO baseCallTableDTO);
Object takeNumber(TakeNumberDTO takeNumber);
Object call(CallQueueDTO callQueueDTO);
Object updateInfo(UpdateCallQueueDTO updateCallQueueDTO);
Object get(Integer page, Integer size, Integer shopId, Integer callTableId, Integer state);
Object takeNumberCode(Integer shopId, Integer callTableId);
Object getQueue(Integer shopId, Integer callTableId, Integer state, Integer page, Integer size);
Object getCallRecord(Integer shopId, Integer callTableId, Integer page, Integer size);
Object getConfig(Integer shopId);
Object updateConfig(UpdateConfigDTO configDTO);
}

View File

@@ -0,0 +1,13 @@
package com.chaozhanggui.system.cashierservice.service;
import com.chaozhanggui.system.cashierservice.entity.TbCallTable;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author Administrator
* @description 针对表【tb_call_table(叫号桌型表)】的数据库操作Service
* @createDate 2024-12-10 10:12:45
*/
public interface TbCallTableService extends IService<TbCallTable> {
}

View File

@@ -4,9 +4,11 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
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.extension.service.impl.ServiceImpl;
import com.chaozhanggui.system.cashierservice.bean.OrderPlatformTypeEnum;
import com.chaozhanggui.system.cashierservice.bean.constant.TableConstant;
import com.chaozhanggui.system.cashierservice.entity.TbCashierCart;
import com.chaozhanggui.system.cashierservice.entity.TbOrderDetail;
@@ -17,8 +19,10 @@ import com.chaozhanggui.system.cashierservice.service.MpCashierCartService;
import com.chaozhanggui.system.cashierservice.service.MpOrderDetailService;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* (TbShopPermission)表服务实现类
@@ -96,7 +100,9 @@ public class MpCashierCartServiceImpl extends ServiceImpl<MPCashierCartMapper, T
.eq(TbCashierCart::getShopId, shopId)
.eq(TbCashierCart::getId, cartId);
if (statuses.length != 0) {
queryWrapper.in(TbCashierCart::getStatus, CollUtil.newArrayList(statuses));
queryWrapper.in(TbCashierCart::getStatus, Arrays.stream(statuses)
.map(TableConstant.OrderInfo.Status::getValue)
.collect(Collectors.toList()));
}
return getOne(queryWrapper);
}
@@ -104,13 +110,99 @@ public class MpCashierCartServiceImpl extends ServiceImpl<MPCashierCartMapper, T
public List<TbCashierCart> selectByIds(Integer shopId, Integer orderId, List<Integer> ids, TableConstant.OrderInfo.Status... statuses) {
LambdaQueryWrapper<TbCashierCart> queryWrapper = new LambdaQueryWrapper<TbCashierCart>()
.eq(TbCashierCart::getShopId, shopId)
.eq(TbCashierCart::getOrderId, orderId)
.in(TbCashierCart::getId, ids);
if (orderId != null) {
queryWrapper.eq(TbCashierCart::getOrderId, orderId);
}
if (statuses.length != 0) {
queryWrapper.in(TbCashierCart::getStatus, CollUtil.newArrayList(statuses));
queryWrapper.in(TbCashierCart::getStatus, Arrays.stream(statuses)
.map(TableConstant.OrderInfo.Status::getValue)
.collect(Collectors.toList()));
}
return list(queryWrapper);
}
@Override
public List<TbCashierCart> selectByShopEatTypeAndOrderId(ShopEatTypeInfoDTO shopEatTypeInfoDTO, String masterId,
Integer orderId, boolean onlySearchPc, TableConstant.OrderInfo.Status... statuses) {
LambdaQueryWrapper<TbCashierCart> queryWrapper = new LambdaQueryWrapper<TbCashierCart>()
.eq(TbCashierCart::getShopId, shopEatTypeInfoDTO.getShopId())
.eq(TbCashierCart::getUseType, shopEatTypeInfoDTO.getUseType())
.gt(TbCashierCart::getCreatedAt, DateUtil.offsetDay(DateUtil.date(), -1).getTime())
.and(q -> q.eq(TbCashierCart::getMasterId, masterId).or().isNull(TbCashierCart::getMasterId));
if (statuses.length == 0) {
queryWrapper.in(TbCashierCart::getStatus, "create", "return");
} else {
queryWrapper.in(TbCashierCart::getStatus, Arrays.stream(statuses)
.map(TableConstant.OrderInfo.Status::getValue)
.collect(Collectors.toList()));
}
if (orderId != null) {
queryWrapper.and(q -> q.eq(TbCashierCart::getOrderId, orderId)
.or().isNull(TbCashierCart::getOrderId));
}
if (onlySearchPc) {
queryWrapper.ne(TbCashierCart::getPlatformType, "mimiapp");
}
// 非堂食校验台桌状态
if (shopEatTypeInfoDTO.isTakeout()) {
queryWrapper.and(q -> q.isNull(TbCashierCart::getTableId).or().eq(TbCashierCart::getTableId, ""))
.in(TbCashierCart::getPlatformType, OrderPlatformTypeEnum.PC.getValue(), OrderPlatformTypeEnum.CASH.getValue());
} else {
if (StrUtil.isNotBlank(shopEatTypeInfoDTO.getTableId())) {
queryWrapper.eq(TbCashierCart::getTableId, shopEatTypeInfoDTO.getTableId());
} else {
queryWrapper.and(q -> q.isNull(TbCashierCart::getTableId).or().eq(TbCashierCart::getTableId, ""));
}
}
return list(queryWrapper);
}
@Override
public Long countByShopEatType(ShopEatTypeInfoDTO shopEatTypeInfoDTO, String masterId,
Integer orderId, boolean onlySearchPc, TableConstant.OrderInfo.Status... statuses) {
LambdaQueryWrapper<TbCashierCart> queryWrapper = new LambdaQueryWrapper<TbCashierCart>()
.eq(TbCashierCart::getShopId, shopEatTypeInfoDTO.getShopId())
.eq(TbCashierCart::getUseType, shopEatTypeInfoDTO.getUseType())
.gt(TbCashierCart::getCreatedAt, DateUtil.offsetDay(DateUtil.date(), -1).getTime())
.and(q -> q.eq(TbCashierCart::getMasterId, masterId).or().isNull(TbCashierCart::getMasterId));
if (statuses.length == 0) {
queryWrapper.in(TbCashierCart::getStatus, "create", "return");
} else {
queryWrapper.in(TbCashierCart::getStatus, Arrays.stream(statuses)
.map(TableConstant.OrderInfo.Status::getValue)
.collect(Collectors.toList()));
}
if (orderId != null) {
queryWrapper.and(q -> q.eq(TbCashierCart::getOrderId, orderId)
.or().isNull(TbCashierCart::getOrderId));
}
if (onlySearchPc) {
queryWrapper.ne(TbCashierCart::getPlatformType, "mimiapp");
}
// 非堂食校验台桌状态
if (shopEatTypeInfoDTO.isTakeout()) {
queryWrapper.and(q -> q.isNull(TbCashierCart::getTableId).or().eq(TbCashierCart::getTableId, ""))
.in(TbCashierCart::getPlatformType, OrderPlatformTypeEnum.PC.getValue(), OrderPlatformTypeEnum.CASH.getValue());
} else {
if (StrUtil.isNotBlank(shopEatTypeInfoDTO.getTableId())) {
queryWrapper.eq(TbCashierCart::getTableId, shopEatTypeInfoDTO.getTableId());
} else {
queryWrapper.and(q -> q.isNull(TbCashierCart::getTableId).or().eq(TbCashierCart::getTableId, ""));
}
}
return (long) count(queryWrapper);
}
}

View File

@@ -1,5 +1,6 @@
package com.chaozhanggui.system.cashierservice.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chaozhanggui.system.cashierservice.bean.constant.TableConstant;
@@ -22,6 +23,12 @@ import java.util.List;
@Service
public class MpShopTableServiceImpl extends ServiceImpl<MpShopTableMapper, TbShopTable> implements MpShopTableService {
@Override
public TbShopTable selectByTableId(String tableId, Integer shopId) {
return getOne(new LambdaQueryWrapper<TbShopTable>()
.eq(TbShopTable::getShopId, shopId)
.eq(TbShopTable::getQrcode, tableId));
}
}

View File

@@ -0,0 +1,22 @@
package com.chaozhanggui.system.cashierservice.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chaozhanggui.system.cashierservice.entity.TbCallConfig;
import com.chaozhanggui.system.cashierservice.service.TbCallConfigService;
import com.chaozhanggui.system.cashierservice.mapper.TbCallConfigMapper;
import org.springframework.stereotype.Service;
/**
* @author Administrator
* @description 针对表【tb_call_config(叫号配置表)】的数据库操作Service实现
* @createDate 2024-12-10 10:12:45
*/
@Service
public class TbCallConfigServiceImpl extends ServiceImpl<TbCallConfigMapper, TbCallConfig>
implements TbCallConfigService{
}

View File

@@ -0,0 +1,22 @@
package com.chaozhanggui.system.cashierservice.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chaozhanggui.system.cashierservice.entity.TbCallQueue;
import com.chaozhanggui.system.cashierservice.service.TbCallQueueService;
import com.chaozhanggui.system.cashierservice.mapper.TbCallQueueMapper;
import org.springframework.stereotype.Service;
/**
* @author Administrator
* @description 针对表【tb_call_queue(叫号排号表)】的数据库操作Service实现
* @createDate 2024-12-10 10:12:45
*/
@Service
public class TbCallQueueServiceImpl extends ServiceImpl<TbCallQueueMapper, TbCallQueue>
implements TbCallQueueService{
}

View File

@@ -0,0 +1,576 @@
package com.chaozhanggui.system.cashierservice.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chaozhanggui.system.cashierservice.dao.TbShopInfoMapper;
import com.chaozhanggui.system.cashierservice.dao.TbShopUserMapper;
import com.chaozhanggui.system.cashierservice.entity.*;
import com.chaozhanggui.system.cashierservice.entity.dto.calltable.*;
import com.chaozhanggui.system.cashierservice.exception.MsgException;
import com.chaozhanggui.system.cashierservice.mapper.TbCallQueueMapper;
import com.chaozhanggui.system.cashierservice.mybatis.MpShopUserMapper;
import com.chaozhanggui.system.cashierservice.service.TbCallConfigService;
import com.chaozhanggui.system.cashierservice.service.TbCallQueueService;
import com.chaozhanggui.system.cashierservice.service.TbCallService;
import com.chaozhanggui.system.cashierservice.service.TbCallTableService;
import com.chaozhanggui.system.cashierservice.util.RabbitMsgUtils;
import com.chaozhanggui.system.cashierservice.util.RedisCst;
import com.chaozhanggui.system.cashierservice.util.Utils;
import com.chaozhanggui.system.cashierservice.util.WxAccountUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@Service
public class TbCallServiceImpl implements TbCallService {
@Value("${wx.mini.page.call}")
private String callPageUrl;
private final TbCallTableService callTableService;
private final TbCallQueueService callQueueService;
private final MpShopUserMapper shopUserMapper;
private final TbShopInfoMapper shopInfoMapper;
private final StringRedisTemplate redisTemplate;
private final TbCallQueueMapper tbCallQueueMapper;
private final WxAccountUtil wxMiniUtils;
private final TbCallConfigService tbCallConfigService;
private final RabbitMsgUtils rabbitMsgUtils;
public TbCallServiceImpl(TbCallTableService callTableService, TbCallQueueService callQueueService,
MpShopUserMapper shopUserMapper, TbShopInfoMapper shopInfoMapper,
StringRedisTemplate redisTemplate, TbCallQueueMapper tbCallQueueMapper,
WxAccountUtil wxMiniUtils, TbCallConfigService tbCallConfigService, RabbitMsgUtils rabbitMsgUtils) {
this.callTableService = callTableService;
this.callQueueService = callQueueService;
this.shopUserMapper = shopUserMapper;
this.shopInfoMapper = shopInfoMapper;
this.redisTemplate = redisTemplate;
this.tbCallQueueMapper = tbCallQueueMapper;
this.wxMiniUtils = wxMiniUtils;
this.tbCallConfigService = tbCallConfigService;
this.rabbitMsgUtils = rabbitMsgUtils;
}
@Override
public Object add(CallTableDTO addCallTableDTO) {
Integer count = callTableService.lambdaQuery()
.eq(TbCallTable::getShopId, addCallTableDTO.getShopId())
.and(q -> q.eq(TbCallTable::getName, addCallTableDTO.getName())
.or()
.eq(TbCallTable::getPrefix, addCallTableDTO.getPrefix())).count();
if (count > 0) {
throw new MsgException("名称或前缀已存在");
}
TbCallTable callTable = new TbCallTable();
BeanUtil.copyProperties(addCallTableDTO, callTable);
callTable.setCreateTime(DateUtil.date());
return callTableService.save(callTable);
}
@Override
public Object update(UpdateCallTableDTO callTableDTO) {
TbCallTable callTable = callTableService.lambdaQuery()
.eq(TbCallTable::getShopId, callTableDTO.getShopId())
.eq(TbCallTable::getId, callTableDTO.getCallTableId()).one();
if (callTable == null) {
throw new MsgException("桌型不存在");
}
TbCallTable newInfo = new TbCallTable();
BeanUtil.copyProperties(callTableDTO, newInfo);
newInfo.setId(callTable.getId());
newInfo.setUpdateTime(DateUtil.date());
return callTableService.updateById(newInfo);
}
@Override
public Object delete(BaseCallTableDTO baseCallTableDTO) {
return callTableService.remove(new LambdaQueryWrapper<TbCallTable>()
.eq(TbCallTable::getId, baseCallTableDTO.getCallTableId())
.eq(TbCallTable::getShopId, baseCallTableDTO.getShopId()));
}
private String getCallNumber(Integer shopId, TbCallTable callTable) {
return Utils.runFunAndCheckKey(() -> {
String callNumKey = RedisCst.getTableCallNumKey(shopId, callTable.getId());
String value = redisTemplate.opsForValue().get(callNumKey);
AtomicReference<String> newVal = new AtomicReference<>("");
// 初始化
if (StrUtil.isBlank(value)) {
Boolean setFlag = Utils.runFunAndRetry(() -> redisTemplate.opsForValue().setIfAbsent(callNumKey, callTable.getStart().toString()), flag -> !flag,
r -> newVal.set(redisTemplate.opsForValue().get(callNumKey)));
if (setFlag) {
return callTable.getPrefix() + callTable.getStart();
}else if (StrUtil.isNotBlank(newVal.get())){
value = String.valueOf((Integer.parseInt(newVal.get()) + 1));
redisTemplate.opsForValue().set(callNumKey, value);
return callTable.getPrefix() + value;
}else {
throw new MsgException("生成排队号码失败");
}
}else {
value = String.valueOf((Integer.parseInt(value) + 1));
redisTemplate.opsForValue().set(callNumKey, value);
return callTable.getPrefix() + value;
}
}, redisTemplate, RedisCst.getLockKey("UPDATE_TABLE", shopId, callTable.getId()));
}
@Override
public Object takeNumber(TakeNumberDTO takeNumberDTO) {
TbShopInfo shopInfo = shopInfoMapper.selectByPrimaryKey(takeNumberDTO.getShopId());
if (shopInfo == null) {
throw new MsgException("店铺信息不存在");
}
TbCallTable callTable = callTableService.lambdaQuery()
.eq(TbCallTable::getShopId, takeNumberDTO.getShopId())
.eq(TbCallTable::getId, takeNumberDTO.getCallTableId()).one();
if (callTable == null) {
throw new MsgException("桌型不存在");
}
// 查询当前
// 拿取系统内部用户信息
TbCallQueue callQueue;
if (takeNumberDTO.getUserId() != null) {
TbShopUser shopUser = shopUserMapper.selectOne(new LambdaQueryWrapper<TbShopUser>()
.eq(TbShopUser::getStatus, 1)
.eq(TbShopUser::getShopId, takeNumberDTO.getShopId())
.eq(TbShopUser::getId, takeNumberDTO.getUserId()));
if (shopUser == null) {
throw new MsgException("用户不存在");
}
callQueue = callQueueService.lambdaQuery()
.eq(TbCallQueue::getUserId, shopUser.getId())
.eq(TbCallQueue::getShopId, takeNumberDTO.getShopId())
.in(TbCallQueue::getState, 0, 1)
.eq(TbCallQueue::getCreateDay, DateUtil.today())
.ne(TbCallQueue::getIsPostpone, 2)
.eq(TbCallQueue::getCallTableId, takeNumberDTO.getCallTableId()).one();
if (callQueue != null) {
throw new MsgException("当前用户已取号");
}
callQueue = new TbCallQueue();
BeanUtil.copyProperties(takeNumberDTO, callQueue);
callQueue.setPhone(StrUtil.isBlank(takeNumberDTO.getPhone()) ? shopUser.getTelephone() : takeNumberDTO.getPhone());
// callQueue.setOpenId(shopUser.getMiniOpenId());
}else {
// if (StrUtil.isBlank(takeNumberDTO.getPhone()) || StrUtil.isBlank(takeNumberDTO.getOpenId())) {
// throw new MsgException("手机号或openId不能为空");
// }
callQueue = callQueueService.lambdaQuery()
.eq(TbCallQueue::getPhone, takeNumberDTO.getPhone())
.eq(TbCallQueue::getShopId, takeNumberDTO.getShopId())
.eq(TbCallQueue::getCreateDay, DateUtil.today())
.in(TbCallQueue::getState, 0, 1)
.ne(TbCallQueue::getIsPostpone, 2)
.eq(TbCallQueue::getCallTableId, takeNumberDTO.getCallTableId()).one();
if (callQueue != null) {
throw new MsgException("当前用户已取号");
}
callQueue = new TbCallQueue();
BeanUtil.copyProperties(takeNumberDTO, callQueue);
callQueue.setPhone(takeNumberDTO.getPhone());
// callQueue.setOpenId(takeNumberDTO.getOpenId());
callQueue.setSubState(0);
}
callQueue.setCreateDay(DateUtil.today());
callQueue.setCallNum(getCallNumber(takeNumberDTO.getShopId(), callTable));
callQueue.setCreateTime(DateUtil.date());
callQueue.setShopId(shopInfo.getId());
callQueue.setShopName(shopInfo.getShopName());
callQueueService.save(callQueue);
// 打印排号票信息
rabbitMsgUtils.printCallNumTicket(callQueue.getId(), callQueue.getShopId());
HashMap<String, Object> data = new HashMap<>();
data.put("tableName", callTable.getName());
data.put("tableNote", callTable.getNote());
data.put("callNum", callQueue.getCallNum());
return data;
}
@Override
public Object call(CallQueueDTO callQueueDTO) {
TbCallQueue callQueue = callQueueService.lambdaQuery()
.notIn(TbCallQueue::getState, -1, 2)
.eq(TbCallQueue::getCreateDay, DateUtil.today())
.eq(TbCallQueue::getId, callQueueDTO.getCallQueueId())
.eq(TbCallQueue::getShopId, callQueueDTO.getShopId())
.one();
if (callQueue == null) {
throw new MsgException("叫号用户不存在");
}
callQueue.setState(1);
callQueue.setCallCount(callQueue.getCallCount() + 1);
callQueue.setCallTime(DateUtil.date());
callQueueService.updateById(callQueue);
if (callQueue.getSubState().equals(0)) {
return new HashMap<String, Object>(){{
put("state", "-1");
}};
}
// 发送模板消息通知用户
TbShopInfo shopInfo = shopInfoMapper.selectByPrimaryKey(callQueue.getShopId());
if (shopInfo == null) {
throw new MsgException("店铺信息不存在");
}
List<TbCallQueue> current = callQueueService.lambdaQuery()
.eq(TbCallQueue::getCallTableId, callQueue.getCallTableId())
.eq(TbCallQueue::getCreateDay, DateUtil.today())
.and(r -> {
r.eq(TbCallQueue::getState, 1)
.or()
.eq(TbCallQueue::getState, 0);
})
.orderByAsc(TbCallQueue::getCreateTime)
.page(new Page<>(1, 1)).getRecords();
if (StrUtil.isBlank(callQueue.getOpenId())) {
return new HashMap<String, Object>(){{
put("state", "-1");
}};
}
wxMiniUtils.sendCurrentOrNearCallMsg(shopInfo.getShopName(), getStrByState(Integer.valueOf(callQueue.getState())),
callQueue.getCallNum(), current.isEmpty() ? "" : current.get(0).getCallNum(), "排号信息", callQueue.getOpenId(), false);
TbCallConfig config = getConfig(callQueueDTO.getShopId());
// 临近用户提醒
List<TbCallQueue> nearList = callQueueService.lambdaQuery()
.eq(TbCallQueue::getCallTableId, callQueue.getCallTableId())
.eq(TbCallQueue::getCreateDay, DateUtil.today())
.gt(TbCallQueue::getId, current.get(0).getId())
.page(new Page<>(config.getNearNum(), 1)).getRecords();
if (!nearList.isEmpty()) {
TbCallQueue nearQueue = nearList.get(0);
wxMiniUtils.sendCurrentOrNearCallMsg(shopInfo.getShopName(), getStrByState(Integer.valueOf(nearQueue.getState())),
nearQueue.getCallNum(), current.isEmpty() ? "" : current.get(0).getCallNum(), "排号信息", nearQueue.getOpenId(), true);
}
return new HashMap<String, Object>(){{
put("state", "1");
}};
}
private String getStrByState(Integer state) {
String msg = "";
switch (state) {
case -1:
msg = "已取消";
break;
case 0:
msg = "排队中";
break;
case 1:
msg = "已到号";
break;
case 3:
msg = "已过号";
}
return msg;
}
@Override
public Object updateInfo(UpdateCallQueueDTO updateCallQueueDTO) {
TbCallQueue callQueue = callQueueService.lambdaQuery()
.eq(TbCallQueue::getShopId, updateCallQueueDTO.getShopId())
.eq(TbCallQueue::getCreateDay, DateUtil.today())
.eq(TbCallQueue::getId, updateCallQueueDTO.getCallQueueId()).one();
if (callQueue == null) {
throw new MsgException("叫号用户不存在");
}
switch (updateCallQueueDTO.getState()) {
case -1:
callQueue.setCancelTime(DateUtil.date());
break;
case 0:
callQueue.setState(0);
break;
case 1:
if (callQueue.getSubState().equals(0)) {
throw new MsgException("当前用户未订阅微信提醒");
}
callQueue.setState(1);
callQueue.setCallCount(callQueue.getCallCount() + 1);
callQueue.setCallTime(DateUtil.date());
break;
case 2:
callQueue.setConfirmTime(DateUtil.date());
break;
case 3:
callQueue.setPassTime(DateUtil.date());
// 已经顺延
callQueue.setIsPostpone(callQueue.getIsPostpone() == null ? 1 : callQueue.getIsPostpone() == 0 ? 1 : 2);
TbShopInfo shopInfo = shopInfoMapper.selectByPrimaryKey(callQueue.getShopId());
if (shopInfo == null) {
throw new MsgException("店铺信息不存在");
}
if(StrUtil.isBlank(callQueue.getOpenId()) && callQueue.getSubState() != 1) {
break;
}
TbCallTable callTable = callTableService.getById(callQueue.getCallTableId());
Integer isPostpone = callTable.getIsPostpone();
Integer postponeNum = callTable.getPostponeNum();
// 判断是否需要顺延, 暂时注释
if (false && callQueue.getIsPostpone() == 0 && isPostpone != null && isPostpone == 1 && postponeNum != null && postponeNum > 0) {
// 查询当前桌以及顺延桌数
List<TbCallQueue> current = callQueueService.lambdaQuery()
.eq(TbCallQueue::getCallTableId, callQueue.getCallTableId())
.eq(TbCallQueue::getCreateDay, DateUtil.today())
.eq(TbCallQueue::getShopId, callTable.getShopId())
.ge(TbCallQueue::getId, callQueue.getId())
.orderByAsc(TbCallQueue::getCreateTime)
.page(new Page<>(1, postponeNum + 1)) // 获取当前桌和顺延的桌数
.getRecords();
// 确保有足够的桌可以顺延
if (current.size() > 1) {
// 获取当前桌以及顺延桌
TbCallQueue currentTable = new TbCallQueue();
BeanUtil.copyProperties(current.get(0), currentTable);
// 顺延替换信息,将每一张顺延桌向前移动
for (int i = 0; i < current.size() - 1; i++) {
exchangeCallQueueInfo(current.get(i), current.get(i + 1)); // 当前桌替换为顺延桌
}
exchangeCallQueueInfo(current.get(current.size() - 1), currentTable);
callQueue = current.get(current.size() - 1);
// 更新数据库中的桌号信息
callQueueService.updateBatchById(current);
}
}
List<TbCallQueue> current = callQueueService.lambdaQuery()
.eq(TbCallQueue::getCallTableId, callQueue.getCallTableId())
.eq(TbCallQueue::getCreateDay, DateUtil.today())
.and(r -> {
r.eq(TbCallQueue::getState, 1)
.or()
.eq(TbCallQueue::getState, 0);
})
.orderByAsc(TbCallQueue::getCreateTime)
.page(new Page<>(1, 1)).getRecords();
wxMiniUtils.sendPassCallMsg(shopInfo.getShopName(), getStrByState(Integer.valueOf(updateCallQueueDTO.getState())),
callQueue.getCallNum(), current.isEmpty() ? "" : current.get(0).getCallNum(), "即将过号", callQueue.getOpenId());
break;
default:
throw new MsgException("错误类型");
}
callQueue.setState(updateCallQueueDTO.getState());
return callQueueService.updateById(callQueue);
}
private void exchangeCallQueueInfo(TbCallQueue setCallQueue, TbCallQueue copyCallQueue) {
setCallQueue.setOpenId(copyCallQueue.getOpenId());
setCallQueue.setState(copyCallQueue.getState());
setCallQueue.setSubState(copyCallQueue.getSubState());
setCallQueue.setCreateTime(copyCallQueue.getCreateTime());
setCallQueue.setName(copyCallQueue.getName());
setCallQueue.setNote(copyCallQueue.getNote());
setCallQueue.setCallNum(copyCallQueue.getCallNum());
setCallQueue.setCallTime(copyCallQueue.getCallTime());
setCallQueue.setCallCount(copyCallQueue.getCallCount());
setCallQueue.setPassTime(copyCallQueue.getPassTime());
setCallQueue.setCancelTime(copyCallQueue.getCancelTime());
setCallQueue.setUserId(copyCallQueue.getUserId());
setCallQueue.setConfirmTime(copyCallQueue.getConfirmTime());
}
@Override
public Object get(Integer page, Integer size, Integer shopId, Integer callTableId, Integer state) {
LambdaQueryWrapper<TbCallTable> query = new LambdaQueryWrapper<TbCallTable>()
.eq(TbCallTable::getShopId, shopId)
.eq(TbCallTable::getState, 1);
if (callTableId != null) {
query.eq(TbCallTable::getId, callTableId);
}
if (state != null) {
query.eq(TbCallTable::getState, state);
}
Page<TbCallTable> pageInfo = callTableService.page(new Page<>(page, size), query);
ArrayList<Map<String, Object>> info = new ArrayList<>();
Long totalCount = 0L;
for (TbCallTable item : pageInfo.getRecords()) {
LambdaQueryChainWrapper<TbCallQueue> q = callQueueService.lambdaQuery()
.eq(TbCallQueue::getCallTableId, item.getId())
.eq(TbCallQueue::getShopId, shopId)
.eq(TbCallQueue::getCreateDay, DateUtil.today())
.in(TbCallQueue::getState, 0, 1);
Integer count = q.count();
totalCount += count;
Map<String, Object> map = BeanUtil.beanToMap(item, false, false);
map.put("totalCount", count);
map.put("isPostpone", item.getIsPostpone() == 1);
info.add(map);
}
Map<String, Object> toMap = BeanUtil.beanToMap(pageInfo);
toMap.put("records", info);
toMap.put("totalCount", totalCount);
return toMap;
}
@Override
public Object takeNumberCode(Integer shopId, Integer callTableId) {
// 创建二维码配置对象设置宽度和高度为400
QrConfig config = new QrConfig(400, 400);
// 使用字节数组输出流来存储二维码图片
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// 生成二维码图片,输出到字节数组输出流
QrCodeUtil.generate(StrUtil.format(callPageUrl, shopId, ""), config, "png", outputStream);
// 将图片转换为 Base64 字符串
String base64 = Base64.getEncoder().encodeToString(outputStream.toByteArray());
// 返回Base64格式的图片字符串
return "data:image/png;base64," + base64;
}
@Override
public Object getQueue(Integer shopId, Integer callTableId, Integer state, Integer page, Integer size) {
List<Integer> tableIds;
if (callTableId != null) {
tableIds = Collections.singletonList(callTableId);
}else {
List<TbCallTable> list = callTableService.lambdaQuery()
.eq(TbCallTable::getShopId, shopId)
.eq(TbCallTable::getState, 1).list();
if (list.isEmpty()) {
return new Page<>();
}
tableIds = list.stream()
.map(TbCallTable::getId)
.collect(Collectors.toList());
}
LambdaQueryWrapper<TbCallQueue> query = new LambdaQueryWrapper<TbCallQueue>()
.eq(TbCallQueue::getShopId, shopId)
.eq(TbCallQueue::getCreateDay, DateUtil.today())
.in(TbCallQueue::getCallTableId, tableIds);
state = null;
if (state != null) {
query.eq(TbCallQueue::getState, state);
}else {
query.in(TbCallQueue::getState, 0, 1);
}
Page<TbCallQueue> pageInfo = callQueueService.page(new Page<>(page, size),
query.orderByAsc(TbCallQueue::getCreateTime)
.orderByDesc(TbCallQueue::getState));
List<TbCallQueue> list1 = pageInfo.getRecords();
// 创建返回的结果集
List<Map<String, Object>> resultList = new ArrayList<>();
// 遍历每一个叫号中的记录,计算前面状态为"0" (排队中) 的人数
for (TbCallQueue calling : list1) {
// 计算前面等待的人数 (状态为"0"且在叫号记录创建时间之前的)
long waitingCount = 0;
if (calling.getState() == 0) {
waitingCount = list1.stream()
.filter(item -> item.getState() == 0 || item.getState() == 1) // 过滤出状态为"排队中"的
.filter(item -> item.getCreateTime().compareTo(calling.getCreateTime()) < 0 ) // 时间在当前叫号之前
.count();
}
// 创建一个Map来保存叫号中的记录及其前面排队的人数
Map<String, Object> map = BeanUtil.beanToMap(calling, false, false);
map.put("waitingCount", waitingCount);
// 将该map加入结果集
resultList.add(map);
}
Map<String, Object> toMap = BeanUtil.beanToMap(pageInfo, false, false);
toMap.put("records", resultList);
// 返回结果列表
return toMap;
}
@Override
public Object getCallRecord(Integer shopId, Integer callTableId, Integer page, Integer size) {
return tbCallQueueMapper.selectCallRecord(shopId, callTableId, new Page<>(page, size));
}
@Override
public TbCallConfig getConfig(Integer shopId) {
TbCallConfig config = tbCallConfigService.lambdaQuery().eq(TbCallConfig::getShopId, shopId).one();
if (config == null) {
config = new TbCallConfig();
config.setShopId(shopId);
config.setCreateTime(DateUtil.date());
tbCallConfigService.save(config);
config = tbCallConfigService.lambdaQuery().eq(TbCallConfig::getShopId, shopId).one();
}
return config;
}
@Override
public Object updateConfig(UpdateConfigDTO configDTO) {
TbCallConfig config = tbCallConfigService.lambdaQuery().eq(TbCallConfig::getShopId, configDTO.getShopId()).one();
if (config == null) {
throw new MsgException("未查询到配置信息");
}
TbCallConfig tbCallConfig = new TbCallConfig();
BeanUtil.copyProperties(configDTO, tbCallConfig);
tbCallConfig.setId(config.getId());
tbCallConfig.setUpdateTime(DateUtil.date());
return tbCallConfigService.updateById(tbCallConfig);
}
}

View File

@@ -0,0 +1,22 @@
package com.chaozhanggui.system.cashierservice.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chaozhanggui.system.cashierservice.entity.TbCallTable;
import com.chaozhanggui.system.cashierservice.service.TbCallTableService;
import com.chaozhanggui.system.cashierservice.mapper.TbCallTableMapper;
import org.springframework.stereotype.Service;
/**
* @author Administrator
* @description 针对表【tb_call_table(叫号桌型表)】的数据库操作Service实现
* @createDate 2024-12-10 10:12:45
*/
@Service
public class TbCallTableServiceImpl extends ServiceImpl<TbCallTableMapper, TbCallTable>
implements TbCallTableService{
}

View File

@@ -0,0 +1,94 @@
/**
* Copyright (c) 2018 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.chaozhanggui.system.cashierservice.util;
import com.aliyun.oss.OSSClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.UUID;
/**
* 阿里云存储
*
* @author Mark sunlightcs@gmail.com
*/
@Component
public class AliUploadUtils {
private static String secret;
private static String key;
private static String endPoint;
private static String bucketName;
private static String prefix;
private static String url;
// 构造器注入
public AliUploadUtils(@Value("${aliyun.keysecret}") String secret,
@Value("${aliyun.keyid}") String key,
@Value("${aliyun.oss.endpoint}") String endPoint,
@Value("${aliyun.oss.bucketname}") String bucketName,
@Value("${aliyun.prefix}") String prefix,
@Value("${aliyun.url}") String url) {
AliUploadUtils.secret = secret;
AliUploadUtils.key = key;
AliUploadUtils.endPoint = endPoint;
AliUploadUtils.bucketName = bucketName;
AliUploadUtils.prefix = prefix;
AliUploadUtils.url = url;
}
/**
* 文件路径
* @param prefix 前缀
* @param suffix 后缀
* @return 返回上传路径
*/
public static String getPath(String prefix, String suffix) {
//生成uuid
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
//文件路径
String path = DateUtils.getDays() + "/" + uuid;
if(StringUtils.isNotBlank(prefix)){
path = prefix + "/" + path;
}
return path + "." + suffix;
}
public static String upload(InputStream inputStream, String path) throws Exception {
OSSClient client = new OSSClient(endPoint, key,
secret);
try {
client.putObject(bucketName, path, inputStream);
client.shutdown();
} catch (Exception e){
throw new Exception("上传异常");
}
return "https://"+ url + "/" + path;
}
public static String uploadSuffix(InputStream inputStream, String fileName) throws Exception {
return upload(inputStream, getPath(prefix, getFileExtension(fileName)));
}
public static String getFileExtension(String fileName) {
int dotIndex = fileName.lastIndexOf(".");
if (dotIndex > 0) {
return fileName.substring(dotIndex).replace(".", "");
} else {
return "";
}
}
}

View File

@@ -1,5 +1,6 @@
package com.chaozhanggui.system.cashierservice.util;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
public class PageHelperUtil {
@@ -7,7 +8,7 @@ public class PageHelperUtil {
/**
* 解决页数超限 仍返回数据问题
*/
public static void startPage(int page, int pageSize) {
PageHelper.startPage(page, pageSize, true, false, false);
public static Page<Object> startPage(int page, int pageSize) {
return PageHelper.startPage(page, pageSize, true, true, false);
}
}

View File

@@ -2,6 +2,7 @@ package com.chaozhanggui.system.cashierservice.util;
import com.alibaba.fastjson.JSONObject;
import com.chaozhanggui.system.cashierservice.entity.TbOrderDetail;
import com.chaozhanggui.system.cashierservice.entity.dto.CallNumPrintDTO;
import com.chaozhanggui.system.cashierservice.rabbit.RabbitConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
@@ -80,4 +81,20 @@ public class RabbitMsgUtils implements RabbitTemplate.ConfirmCallback {
public void updateCons(JSONObject jsonObject1) {
sendMsg(RabbitConstants.EXCHANGE_CONS, RabbitConstants.ROUTING_KEY_CONS, jsonObject1, "储值卡记录", true);
}
public void printCallNumTicket(Integer callQueueId, Integer shopId) {
CallNumPrintDTO printDTO = new CallNumPrintDTO();
printDTO.setCallQueueId(callQueueId);
printDTO.setShopId(shopId);
try {
JSONObject currentUserInfo = TokenUtil.getCurrentUserInfo();
log.info("用户信息: {}", currentUserInfo);
printDTO.setCurrentUserId(currentUserInfo.getLong("accountId"));
printDTO.setCurrentUserName(currentUserInfo.getString("name"));
printDTO.setCurrentUserNickName(currentUserInfo.getString("nickname"));
} catch (Exception e) {
log.error("获取当前用户信息失败", e);
}
sendMsg(RabbitConstants.EXCHANGE_PRINT, RabbitConstants.ROUTING_KEY_CALL_TABLE, printDTO, "排号小票打印", true);
}
}

View File

@@ -30,7 +30,8 @@ public class RedisCst {
// 选择人数锁
public static final String CHOSE_TABLE_COUNT = "CHOSE_TABLE_COUNT";
// 排队取号全局号码
static String TABLE_CALL_NUMBER = "TABLE_CALL_NUMBER:";
public static String getCurrentOrderKey(String tableId, String shopId) {
@@ -50,4 +51,8 @@ public class RedisCst {
}
return key.toString();
}
public static String getTableCallNumKey(Integer shopId, Integer callTableId) {
return TABLE_CALL_NUMBER + shopId + ":" + callTableId;
}
}

View File

@@ -7,7 +7,10 @@ import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;
@@ -106,4 +109,11 @@ public class TokenUtil {
public static void main(String[] args) {
parseParamFromToken("eyJhbGciOiJIUzI1NiJ9.eyJhY2NvdW50SWQiOiI2IiwiY2xpZW50VHlwZSI6InBjIiwic2hvcElkIjoiMTUiLCJleHAiOjE3MTA1ODc3NjAsImlhdCI6MTcwOTExNjUzMSwibG9naW5OYW1lIjoiMTg4MjE3Nzc4OCJ9.RXfyRgkfC13JGVypd9TQvbNNl_-btyQ-7xnvlj3ej0M");
}
public static JSONObject getCurrentUserInfo() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String token = request.getHeader("token");
return parseParamFromToken(token);
}
}

View File

@@ -31,6 +31,12 @@ public class WxAccountUtil {
private final TbShopMsgStateMapper shopMsgStateMapper;
static LinkedHashMap<String,String> linkedHashMap=new LinkedHashMap<>();
@Value("${wx.mini.user.msgId.currentCall}")
private String currentCallTempId;
@Value("${wx.mini.user.msgId.nearCall}")
private String nearCallTempId;
static {
linkedHashMap.put("40001","获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口");
@@ -132,4 +138,76 @@ public class WxAccountUtil {
return null;
}
}
public void sendCurrentOrNearCallMsg(String shopName, String state, String callNum, String currentNum, String note, String openId, boolean isNear) {
Map<String, Object> data = new HashMap<String, Object>() {{
put("thing1", new HashMap<String, Object>() {{
put("value", shopName);
}});
put("phrase2", new HashMap<String, Object>() {{
put("value", state);
}});
put("character_string3", new HashMap<String, Object>() {{
put("value", callNum);
}});
put("character_string4", new HashMap<String, Object>() {{
put("value", currentNum);
}});
put("thing5", new HashMap<String, Object>() {{
put("value", note);
}});
}};
try {
sendTempMsg(isNear ? nearCallTempId : currentCallTempId, openId, data, "排队到号");
} catch (Exception e) {
log.error("发送失败, openId:{}, msg: {}", openId, e.getMessage());
}
}
public JSONObject sendTempMsg(String tempId, String toUserOpenId, Map<String, Object> data, String note) {
log.info("开始发送" + note + "模板消息, 接收用户openId: {}, 消息数据: {}", toUserOpenId, data);
String accessToken= getAccessToken();
JSONObject object1=new JSONObject();
object1.put("template_id", tempId);
object1.put("touser", toUserOpenId);
object1.put("data",data);
object1.put("miniprogram_state","trial");
object1.put("lang","zh_CN");
String response= HttpRequest.post("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=".concat(accessToken)).body(object1.toString()).execute().body();
log.info("微信模板消息发送成功,相应内容:{}",response);
JSONObject resObj=JSONObject.parseObject(response);
if(ObjectUtil.isNotEmpty(resObj)&&ObjectUtil.isNotNull(resObj)&&"0".equals(resObj.get("errcode")+"")){
return resObj;
}
throw new RuntimeException(linkedHashMap.getOrDefault(resObj.get("errcode") + "", "未知错误"));
}
public void sendPassCallMsg(String shopName, String state, String callNum, String currentNum, String note, String openId) {
Map<String, Object> data = new HashMap<String, Object>() {{
put("thing1", new HashMap<String, Object>() {{
put("value", shopName);
}});
put("character_string2", new HashMap<String, Object>() {{
put("value", callNum);
}});
put("character_string3", new HashMap<String, Object>() {{
put("value", currentNum);
}});
put("phrase4", new HashMap<String, Object>() {{
put("value", state);
}});
put("thing5", new HashMap<String, Object>() {{
put("value", note);
}});
}};
try {
sendTempMsg(currentCallTempId, openId, data, "过号");
} catch (Exception e) {
log.error("发送失败, openId:{}, msg: {}", openId, e.getMessage());
}
}
}

View File

@@ -60,6 +60,13 @@ wx:
secrete: a34a61adc0602118b49400baa8812454
warnMsgTmpId: AV-KybUHaK3KtFVLqpy6PHccHBS7XeX__mOM4RbufnQ
mini:
user:
appId: wxd88fffa983758a30
secrete: a34a61adc0602118b49400baa8812454
msgId:
nearCall: yxOjWK-KjMEZ_BaHWqDJJpHiUPXN6JWqr7u9y65RIWM
currentCall: 3BgFazRpVlvreh5z9u4cNP_VeclXKSQfh-r3x2_bYx4
passCall: qUhvEfvCtIcBA3DOn3QMqsGOolrEpyr0YBh99i-AUqw
page:
call: https://cashier.sxczgkj.cn/make?shopId={}&queueId={}
ali:
@@ -76,3 +83,13 @@ mybatis-plus:
# php服务器地址
phpServer: https://czgdoumei.sxczgkj.com/index.php/api
# oss配置
aliyun:
prefix: upload
keyid: LTAI5tPdEfYSZcqHbjCrtPRD
keysecret: DZjyHBq3nTujF0NMLxnZgsecU8ZCvy
url: cashier-oss.oss-cn-beijing.aliyuncs.com
oss:
bucketname: cashier-oss
endpoint: oss-cn-beijing.aliyuncs.com

View File

@@ -15,14 +15,13 @@
<result property="shopId" column="shop_id" jdbcType="INTEGER"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
<result property="isPostpone" column="is_postpone" jdbcType="TINYINT"/>
<result property="postponeNum" column="postpone_num" jdbcType="INTEGER"/>
<result property="nearNum" column="near_num" jdbcType="INTEGER"/>
</resultMap>
<sql id="Base_Column_List">
id,page_address,is_online,
bg_cover,success_msg,near_msg,
calling_msg,shop_id,create_time,
update_time,is_postpone,postpone_num
update_time,near_num
</sql>
</mapper>

View File

@@ -24,6 +24,7 @@
<result property="confirmTime" column="confirm_time" jdbcType="TIMESTAMP"/>
<result property="callNum" column="call_num" jdbcType="VARCHAR"/>
<result property="createDay" column="create_day" jdbcType="VARCHAR"/>
<result property="isPostpone" column="is_postpone" jdbcType="TINYINT"/>
</resultMap>
<sql id="Base_Column_List">
@@ -33,6 +34,6 @@
call_count,pass_time,cancel_time,
note,user_id,open_id,
sub_state,confirm_time,call_num,
create_day
create_day,is_postpone
</sql>
</mapper>

View File

@@ -17,12 +17,15 @@
<result property="qrcode" column="qrcode" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
<result property="isPostpone" column="is_postpone" jdbcType="TINYINT"/>
<result property="postponeNum" column="postpone_num" jdbcType="INTEGER"/>
</resultMap>
<sql id="Base_Column_List">
id,name,note,
wait_time,prefix,start,
near_num,state,shop_id,
qrcode,create_time,update_time
qrcode,create_time,update_time,
is_postpone,postpone_num
</sql>
</mapper>

View File

@@ -537,9 +537,12 @@
shop_id = #{shopId}
AND product_id = #{productId}
AND `status` = 'create'
and master_id = #{masterId}
and table_id = #{tableId}
and trade_day = #{day}
AND created_at > UNIX_TIMESTAMP(NOW() - INTERVAL 1 DAY) * 1000
AND (master_id = #{masterId} OR master_id IS NULL)
<if test="tableId != null and tableId != ''">
and table_id = #{tableId}
</if>
AND use_type = #{useType}
group by shop_id,product_id
</select>