This commit is contained in:
huchuansai
2025-09-13 14:04:56 +08:00
35 changed files with 2897 additions and 67487 deletions

View File

@@ -0,0 +1,64 @@
package com.starry.admin.common.config;
import java.util.Arrays;
import java.util.Collections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 跨域配置
*
* @author admin
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.exposedHeaders("*")
.maxAge(3600);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
// 允许所有域名进行跨域调用
configuration.setAllowedOriginPatterns(Collections.singletonList("*"));
// 允许所有请求头
configuration.setAllowedHeaders(Collections.singletonList("*"));
// 允许所有HTTP方法
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD"));
// 允许发送Cookie
configuration.setAllowCredentials(true);
// 暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
configuration.setExposedHeaders(Arrays.asList("*"));
// 预检请求的缓存时间(秒)
configuration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public CorsFilter corsFilter() {
return new CorsFilter(corsConfigurationSource());
}
}

View File

@@ -0,0 +1,207 @@
package com.starry.admin.common.filter;
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
import com.starry.admin.modules.clerk.service.impl.PlayClerkUserInfoServiceImpl;
import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity;
import com.starry.admin.modules.custom.service.impl.PlayCustomUserInfoServiceImpl;
import com.starry.admin.modules.weichat.service.WxTokenService;
import com.starry.common.context.CustomSecurityContextHolder;
import java.io.IOException;
import java.util.UUID;
import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.MDC;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 请求关联ID过滤器为每个HTTP请求生成唯一的跟踪ID
* 用于日志关联和请求链路追踪
*
* @author Claude
*/
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorrelationFilter implements Filter {
@Resource
@Lazy
private WxTokenService wxTokenService;
@Resource
@Lazy
private PlayClerkUserInfoServiceImpl clerkUserInfoService;
@Resource
@Lazy
private PlayCustomUserInfoServiceImpl customUserInfoService;
public static final String CORRELATION_ID_HEADER = "X-Correlation-ID";
public static final String CORRELATION_ID_MDC_KEY = "correlationId";
public static final String USER_ID_MDC_KEY = "userId";
public static final String TENANT_ID_MDC_KEY = "tenantId";
public static final String TENANT_KEY_MDC_KEY = "tenantKey";
public static final String REQUEST_URI_MDC_KEY = "requestUri";
public static final String REQUEST_METHOD_MDC_KEY = "requestMethod";
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (!(request instanceof HttpServletRequest)) {
chain.doFilter(request, response);
return;
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
try {
// 生成或获取关联ID
String correlationId = getOrGenerateCorrelationId(httpRequest);
// 设置MDC上下文
MDC.put(CORRELATION_ID_MDC_KEY, correlationId);
MDC.put(REQUEST_URI_MDC_KEY, httpRequest.getRequestURI());
MDC.put(REQUEST_METHOD_MDC_KEY, httpRequest.getMethod());
// 提取并设置租户信息
String tenantKey = httpRequest.getHeader("tenantkey");
if (tenantKey != null && !tenantKey.trim().isEmpty()) {
MDC.put(TENANT_KEY_MDC_KEY, tenantKey);
}
// 尝试从安全上下文获取租户ID
try {
String tenantId = CustomSecurityContextHolder.getTenantId();
if (tenantId != null && !tenantId.trim().isEmpty() && !"9999".equals(tenantId)) {
MDC.put(TENANT_ID_MDC_KEY, tenantId);
}
} catch (Exception e) {
// 忽略获取租户ID的异常
}
// 尝试获取用户ID可能来自JWT或其他认证信息
String userId = extractUserId(httpRequest);
if (userId != null) {
MDC.put(USER_ID_MDC_KEY, userId);
}
// 将关联ID添加到响应头
httpResponse.setHeader(CORRELATION_ID_HEADER, correlationId);
// 继续过滤器链
chain.doFilter(request, response);
} finally {
// 清理MDC上下文
MDC.clear();
}
}
/**
* 获取或生成关联ID
* 优先从请求头获取,如果没有则生成新的
*/
private String getOrGenerateCorrelationId(HttpServletRequest request) {
String correlationId = request.getHeader(CORRELATION_ID_HEADER);
if (correlationId == null || correlationId.trim().isEmpty()) {
correlationId = "REQ-" + UUID.randomUUID().toString().substring(0, 8);
}
return correlationId;
}
/**
* 尝试从请求中提取用户ID
* 根据项目的认证机制:支持微信端(clerk/custom token)和管理端(Authorization header)
*/
private String extractUserId(HttpServletRequest request) {
try {
// 1. 微信端 - Clerk用户认证
String clerkToken = request.getHeader("clerkusertoken");
if (clerkToken != null && !clerkToken.trim().isEmpty()) {
return extractUserIdFromWxToken(clerkToken, "clerk");
}
// 2. 微信端 - Custom用户认证
String customToken = request.getHeader("customusertoken");
if (customToken != null && !customToken.trim().isEmpty()) {
return extractUserIdFromWxToken(customToken, "custom");
}
// 3. 管理端 - JWT Bearer token认证
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
return extractUserIdFromJwtToken(authHeader);
}
} catch (Exception e) {
// 如果解析失败不影响主流程只是记录日志时没有用户ID
// 可以选择记录debug日志但不抛异常
}
return null;
}
/**
* 从微信token中提取真实用户ID
*/
private String extractUserIdFromWxToken(String token, String userType) {
try {
// 使用WxTokenService解析JWT token获取真实用户ID
String userId = wxTokenService.getWxUserIdByToken(token);
if (userId != null) {
// 根据用户类型获取更多用户信息(可选)
if ("clerk".equals(userType)) {
PlayClerkUserInfoEntity clerkUser = clerkUserInfoService.selectById(userId);
if (clerkUser != null) {
// 返回格式: clerk_userId 或者可以包含昵称等信息
return "clerk_" + userId;
}
} else if ("custom".equals(userType)) {
PlayCustomUserInfoEntity customUser = customUserInfoService.selectById(userId);
if (customUser != null) {
return "custom_" + userId;
}
}
// 如果查询用户详情失败至少返回基础用户ID
return userType + "_" + userId;
}
} catch (Exception e) {
// Token解析失败可能是过期或无效token不影响主流程
}
return null;
}
/**
* 从管理端JWT token中提取用户ID
*/
private String extractUserIdFromJwtToken(String authHeader) {
try {
// 管理端的JWT解析比较复杂这里先返回标识
// 实际应该通过JwtToken组件或SecurityUtils获取当前登录用户信息
return "admin_user";
} catch (Exception e) {
return null;
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化逻辑
}
@Override
public void destroy() {
// 清理逻辑
}
}

View File

@@ -24,9 +24,6 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
/**
* @author admin
@@ -62,7 +59,7 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
.antMatchers("/health", "/health/**").permitAll()
// 跨域请求会先进行一次options请求
.antMatchers(HttpMethod.OPTIONS).permitAll().anyRequest()// 除上面外的所有请求全部需要鉴权认证
.authenticated().and().cors().configurationSource(this.corsConfigurationSource());
.authenticated().and().cors();
// 禁用缓存
httpSecurity.headers().cacheControl();
// 添加Logout filter
@@ -74,18 +71,6 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
.authenticationEntryPoint(customAuthenticationEntryPoint);
}
private CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedHeader("*"); // 这个得加上一些复杂的请求方式会带有header不加上跨域会失效。
corsConfiguration.addAllowedMethod("*");
corsConfiguration.addExposedHeader("*");
corsConfiguration.addAllowedOriginPattern("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfiguration);
return source;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());

View File

@@ -1,44 +1,194 @@
package com.starry.admin.modules.order.module.constant;
import lombok.Getter;
/**
* 订单相关枚举和常量
*
* @author admin
* @since 2024/5/8 15:41
**/
*/
public class OrderConstant {
/**
* 订单状态-待接单
*
* @since 2024/5/8 15:42
**/
* 订单状态枚举
*/
@Getter
public enum OrderStatus {
PENDING("0", "已下单(待接单)"),
ACCEPTED("1", "已接单(待开始)"),
IN_PROGRESS("2", "已开始(服务中)"),
COMPLETED("3", "已完成"),
CANCELLED("4", "已取消");
private final String code;
private final String description;
OrderStatus(String code, String description) {
this.code = code;
this.description = description;
}
public static OrderStatus fromCode(String code) {
for (OrderStatus status : values()) {
if (status.code.equals(code)) {
return status;
}
}
throw new IllegalArgumentException("Unknown order status code: " + code);
}
}
/**
* 订单类型枚举
*/
@Getter
public enum OrderType {
REFUND("-1", "退款订单"),
RECHARGE("0", "充值订单"),
WITHDRAWAL("1", "提现订单"),
NORMAL("2", "普通订单");
private final String code;
private final String description;
OrderType(String code, String description) {
this.code = code;
this.description = description;
}
public static OrderType fromCode(String code) {
for (OrderType type : values()) {
if (type.code.equals(code)) {
return type;
}
}
throw new IllegalArgumentException("Unknown order type code: " + code);
}
}
/**
* 下单类型枚举
*/
@Getter
public enum PlaceType {
OTHER("-1", "其他类型"),
SPECIFIED("0", "指定单"),
RANDOM("1", "随机单"),
REWARD("2", "打赏单");
private final String code;
private final String description;
PlaceType(String code, String description) {
this.code = code;
this.description = description;
}
public static PlaceType fromCode(String code) {
for (PlaceType type : values()) {
if (type.code.equals(code)) {
return type;
}
}
throw new IllegalArgumentException("Unknown place type code: " + code);
}
}
/**
* 性别枚举
*/
@Getter
public enum Gender {
UNKNOWN("0", "未知"),
MALE("1", ""),
FEMALE("2", "");
private final String code;
private final String description;
Gender(String code, String description) {
this.code = code;
this.description = description;
}
public static Gender fromCode(String code) {
for (Gender gender : values()) {
if (gender.code.equals(code)) {
return gender;
}
}
throw new IllegalArgumentException("Unknown gender code: " + code);
}
}
/**
* 打赏类型枚举
*/
@Getter
public enum RewardType {
NOT_APPLICABLE("", "非打赏订单"),
BALANCE("0", "余额打赏"),
GIFT("1", "礼物打赏");
private final String code;
private final String description;
RewardType(String code, String description) {
this.code = code;
this.description = description;
}
public static RewardType fromCode(String code) {
// Handle null, empty string, or whitespace as NOT_APPLICABLE
if (code == null || code.trim().isEmpty()) {
return NOT_APPLICABLE;
}
for (RewardType type : values()) {
if (code.equals(type.code)) {
return type;
}
}
throw new IllegalArgumentException("Unknown reward type code: " + code);
}
}
/**
* 商品类型枚举
*/
@Getter
public enum CommodityType {
GIFT("0", "礼物"),
SERVICE("1", "服务");
private final String code;
private final String description;
CommodityType(String code, String description) {
this.code = code;
this.description = description;
}
public static CommodityType fromCode(String code) {
for (CommodityType type : values()) {
if (type.code.equals(code)) {
return type;
}
}
throw new IllegalArgumentException("Unknown commodity type code: " + code);
}
}
// Legacy constants for backward compatibility - consider deprecating
@Deprecated
public final static String ORDER_STATUS_0 = "0";
/**
* 订单状态-待开始
*
* @since 2024/5/8 15:42
**/
@Deprecated
public final static String ORDER_STATUS_1 = "1";
/**
* 订单状态-服务中
*
* @since 2024/5/8 15:42
**/
@Deprecated
public final static String ORDER_STATUS_2 = "2";
/**
* 订单状态-已完成
*
* @since 2024/5/8 15:42
**/
@Deprecated
public final static String ORDER_STATUS_3 = "3";
/**
* 订单状态-已取消
*
* @since 2024/5/8 15:42
**/
@Deprecated
public final static String ORDER_STATUS_4 = "4";
}

View File

@@ -0,0 +1,45 @@
package com.starry.admin.modules.order.module.dto;
import com.starry.admin.modules.order.module.constant.OrderConstant;
import java.math.BigDecimal;
import lombok.Builder;
import lombok.Data;
/**
* 商品信息值对象
*
* @author admin
*/
@Data
@Builder
public class CommodityInfo {
/**
* 商品ID
*/
private String commodityId;
/**
* 商品类型
*/
private OrderConstant.CommodityType commodityType;
/**
* 商品单价
*/
private BigDecimal commodityPrice;
/**
* 商品属性-服务时长
*/
private String serviceDuration;
/**
* 商品名称
*/
private String commodityName;
/**
* 商品数量
*/
private String commodityNumber;
}

View File

@@ -0,0 +1,128 @@
package com.starry.admin.modules.order.module.dto;
import com.starry.admin.modules.order.module.constant.OrderConstant;
import com.starry.admin.modules.order.module.constant.OrderConstant.RewardType;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Data;
/**
* 订单创建请求对象 - 使用Builder模式替换20+参数的方法
*
* @author admin
*/
@Data
@Builder
public class OrderCreationRequest {
/**
* 订单ID
*/
@NotBlank(message = "订单ID不能为空")
private String orderId;
/**
* 订单编号
*/
@NotBlank(message = "订单编号不能为空")
private String orderNo;
/**
* 订单状态
*/
@NotNull(message = "订单状态不能为空")
private OrderConstant.OrderStatus orderStatus;
/**
* 订单类型
*/
@NotNull(message = "订单类型不能为空")
private OrderConstant.OrderType orderType;
/**
* 下单类型
*/
@NotNull(message = "下单类型不能为空")
private OrderConstant.PlaceType placeType;
/**
* 打赏类型0:余额;1:礼物)
*/
private RewardType rewardType;
/**
* 是否是首单
*/
private boolean isFirstOrder;
/**
* 商品信息
*/
@Valid
@NotNull(message = "商品信息不能为空")
private CommodityInfo commodityInfo;
/**
* 支付信息
*/
@Valid
@NotNull(message = "支付信息不能为空")
private PaymentInfo paymentInfo;
/**
* 下单人
*/
@NotBlank(message = "下单人不能为空")
private String purchaserBy;
/**
* 接单人(可选)
*/
private String acceptBy;
/**
* 微信号码
*/
private String weiChatCode;
/**
* 订单备注
*/
private String remark;
/**
* 随机单要求(仅随机单时需要)
*/
private RandomOrderRequirements randomOrderRequirements;
/**
* 获取首单标识字符串(兼容现有系统)
*/
public String getFirstOrderString() {
return isFirstOrder ? "1" : "0";
}
/**
* 验证随机单要求
*/
public boolean isValidForRandomOrder() {
return placeType == OrderConstant.PlaceType.RANDOM
&& randomOrderRequirements != null;
}
/**
* 是否为打赏单
*/
public boolean isRewardOrder() {
return placeType == OrderConstant.PlaceType.REWARD;
}
/**
* 是否为指定单
*/
public boolean isSpecifiedOrder() {
return placeType == OrderConstant.PlaceType.SPECIFIED;
}
}

View File

@@ -0,0 +1,40 @@
package com.starry.admin.modules.order.module.dto;
import java.math.BigDecimal;
import java.util.List;
import lombok.Builder;
import lombok.Data;
/**
* 支付信息值对象
*
* @author admin
*/
@Data
@Builder
public class PaymentInfo {
/**
* 订单金额
*/
private BigDecimal orderMoney;
/**
* 订单最终金额(支付金额)
*/
private BigDecimal finalAmount;
/**
* 优惠金额
*/
private BigDecimal discountAmount;
/**
* 优惠券ID列表
*/
private List<String> couponIds;
/**
* 支付方式0余额支付,1:微信支付,2:支付宝支付
*/
private String payMethod;
}

View File

@@ -0,0 +1,36 @@
package com.starry.admin.modules.order.module.dto;
import com.starry.admin.modules.order.module.constant.OrderConstant;
import lombok.Builder;
import lombok.Data;
/**
* 随机单要求信息值对象
*
* @author admin
*/
@Data
@Builder
public class RandomOrderRequirements {
/**
* 随机单要求-店员性别
*/
private OrderConstant.Gender clerkGender;
/**
* 随机单要求-店员等级ID
*/
private String clerkLevelId;
/**
* 随机单要求-是否排除下单过的成员0:不排除;1:排除)
*/
private String excludeHistory;
/**
* 是否排除历史订单
*/
public boolean shouldExcludeHistory() {
return "1".equals(excludeHistory);
}
}

View File

@@ -2,6 +2,7 @@ package com.starry.admin.modules.order.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.starry.admin.modules.order.module.dto.*;
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
import com.starry.admin.modules.order.module.vo.*;
import com.starry.admin.modules.weichat.entity.order.*;
@@ -43,8 +44,18 @@ public interface IPlayOrderInfoService extends IService<PlayOrderInfoEntity> {
void createRechargeOrder(String orderNo, BigDecimal orderMoney, BigDecimal finalAmount, String purchaserBy);
/**
* 新增订单信息
* 新增订单信息 - 重构版本使用Builder模式
*
* @param request 订单创建请求对象
* @author admin
* @since 2024/6/3 10:53
**/
void createOrderInfo(OrderCreationRequest request);
/**
* 新增订单信息 - 旧版本方法已废弃建议使用OrderCreationRequest
*
* @deprecated 请使用 {@link #createOrderInfo(OrderCreationRequest)} 替代
* @param orderId
* 订单ID
* @param orderNo
@@ -96,6 +107,7 @@ public interface IPlayOrderInfoService extends IService<PlayOrderInfoEntity> {
* @author admin
* @since 2024/6/3 10:53
**/
@Deprecated
void createOrderInfo(String orderId, String orderNo, String orderState, String orderType, String placeType,
String rewardType, String firstOrder, String commodityId, String commodityType, BigDecimal commodityPrice,
String serviceDuration, String commodityName, String commodityNumber, BigDecimal orderMoney,

View File

@@ -19,6 +19,7 @@ import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity;
import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService;
import com.starry.admin.modules.order.mapper.PlayOrderInfoMapper;
import com.starry.admin.modules.order.module.constant.OrderConstant;
import com.starry.admin.modules.order.module.dto.*;
import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity;
import com.starry.admin.modules.order.module.entity.PlayOrderEvaluateInfoEntity;
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
@@ -158,6 +159,132 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl<PlayOrderInfoMapper, P
playCouponDetailsService.updateCouponUseStateByIds(couponIds, "2");
}
@Override
public void createOrderInfo(OrderCreationRequest request) {
// 验证请求
validateOrderCreationRequest(request);
PlayOrderInfoEntity entity = buildOrderEntity(request);
// 处理随机单要求
if (request.getPlaceType() == OrderConstant.PlaceType.RANDOM) {
setRandomOrderRequirements(entity, request.getRandomOrderRequirements());
}
// 处理接单人信息
if (StrUtil.isNotBlank(request.getAcceptBy())) {
setAcceptByInfo(entity, request);
}
// 处理打赏单自动完成逻辑
if (request.isRewardOrder()) {
setRewardOrderCompleted(entity);
}
// 保存订单
userInfoService.saveOrderInfo(entity);
this.baseMapper.insert(entity);
// 修改优惠券状态
playCouponDetailsService.updateCouponUseStateByIds(
request.getPaymentInfo().getCouponIds(), "2");
}
/**
* 验证订单创建请求
*/
private void validateOrderCreationRequest(OrderCreationRequest request) {
if (request.getPlaceType() == OrderConstant.PlaceType.RANDOM
&& !request.isValidForRandomOrder()) {
throw new CustomException("随机单必须提供店员要求信息");
}
}
/**
* 构建订单实体
*/
private PlayOrderInfoEntity buildOrderEntity(OrderCreationRequest request) {
PlayOrderInfoEntity entity = new PlayOrderInfoEntity();
// 基本信息
entity.setId(request.getOrderId());
entity.setOrderNo(request.getOrderNo());
entity.setOrderStatus(request.getOrderStatus().getCode());
entity.setOrderType(request.getOrderType().getCode());
entity.setPlaceType(request.getPlaceType().getCode());
entity.setRewardType(request.getRewardType().getCode());
entity.setFirstOrder(request.getFirstOrderString());
// 固定默认值
entity.setRefundType("0");
entity.setBackendEntry("0");
entity.setPayMethod("0");
entity.setOrderSettlementState("0");
entity.setOrdersExpiredState("0");
// 商品信息
CommodityInfo commodityInfo = request.getCommodityInfo();
entity.setCommodityId(commodityInfo.getCommodityId());
entity.setCommodityType(commodityInfo.getCommodityType().getCode());
entity.setCommodityPrice(commodityInfo.getCommodityPrice());
entity.setServiceDuration(commodityInfo.getServiceDuration());
entity.setCommodityName(commodityInfo.getCommodityName());
entity.setCommodityNumber(commodityInfo.getCommodityNumber());
// 支付信息
PaymentInfo paymentInfo = request.getPaymentInfo();
entity.setOrderMoney(paymentInfo.getOrderMoney());
entity.setFinalAmount(paymentInfo.getFinalAmount());
entity.setDiscountAmount(paymentInfo.getDiscountAmount());
entity.setCouponIds(paymentInfo.getCouponIds());
entity.setUseCoupon(
paymentInfo.getCouponIds() != null && !paymentInfo.getCouponIds().isEmpty() ? "1" : "0");
// 用户信息
entity.setPurchaserBy(request.getPurchaserBy());
entity.setPurchaserTime(LocalDateTime.now());
entity.setWeiChatCode(request.getWeiChatCode());
entity.setRemark(request.getRemark());
return entity;
}
/**
* 设置随机单要求
*/
private void setRandomOrderRequirements(PlayOrderInfoEntity entity, RandomOrderRequirements requirements) {
if (requirements != null) {
entity.setSex(requirements.getClerkGender().getCode());
entity.setLevelId(requirements.getClerkLevelId());
entity.setExcludeHistory(requirements.getExcludeHistory());
}
}
/**
* 设置接单人信息
*/
private void setAcceptByInfo(PlayOrderInfoEntity entity, OrderCreationRequest request) {
entity.setAcceptBy(request.getAcceptBy());
ClerkEstimatedRevenueVo estimatedRevenueVo = getClerkEstimatedRevenue(
request.getAcceptBy(),
request.getPaymentInfo().getCouponIds(),
request.getPlaceType().getCode(),
request.getFirstOrderString(),
request.getPaymentInfo().getFinalAmount());
entity.setEstimatedRevenue(estimatedRevenueVo.getRevenueAmount());
entity.setEstimatedRevenueRatio(estimatedRevenueVo.getRevenueRatio());
}
/**
* 设置打赏单为已完成状态
*/
private void setRewardOrderCompleted(PlayOrderInfoEntity entity) {
LocalDateTime now = LocalDateTime.now();
entity.setAcceptTime(now);
entity.setOrderStartTime(now);
entity.setOrderEndTime(now);
}
@Override
public ClerkEstimatedRevenueVo getClerkEstimatedRevenue(String clerkId, List<String> croupIds, String placeType,
String firstOrder, BigDecimal finalAmount) {

View File

@@ -19,6 +19,12 @@ import com.starry.admin.modules.custom.service.IPlayCustomFollowInfoService;
import com.starry.admin.modules.custom.service.IPlayCustomGiftInfoService;
import com.starry.admin.modules.custom.service.IPlayCustomLeaveMsgService;
import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService;
import com.starry.admin.modules.order.module.constant.OrderConstant;
import com.starry.admin.modules.order.module.constant.OrderConstant.RewardType;
import com.starry.admin.modules.order.module.dto.CommodityInfo;
import com.starry.admin.modules.order.module.dto.OrderCreationRequest;
import com.starry.admin.modules.order.module.dto.PaymentInfo;
import com.starry.admin.modules.order.module.dto.RandomOrderRequirements;
import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity;
import com.starry.admin.modules.order.module.entity.PlayOrderEvaluateInfoEntity;
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
@@ -224,7 +230,34 @@ public class WxCustomController {
}
String orderId = IdUtils.getUuid();
// 记录订单信息
playOrderInfoService.createOrderInfo(orderId, playOrderInfoService.getOrderNo(), "3", "2", "2", "0", "1", "", "0", BigDecimal.ZERO, "", "", "0", new BigDecimal(vo.getMoney()), new BigDecimal(vo.getMoney()), BigDecimal.ZERO, userId, vo.getClerkId(), vo.getWeiChatCode(), new ArrayList<>(), vo.getRemark(), "", "", "");
OrderCreationRequest orderRequest = OrderCreationRequest.builder()
.orderId(orderId)
.orderNo(playOrderInfoService.getOrderNo())
.orderStatus(OrderConstant.OrderStatus.COMPLETED)
.orderType(OrderConstant.OrderType.NORMAL)
.placeType(OrderConstant.PlaceType.REWARD)
.rewardType(RewardType.BALANCE)
.isFirstOrder(true)
.commodityInfo(CommodityInfo.builder()
.commodityId("")
.commodityType(OrderConstant.CommodityType.GIFT)
.commodityPrice(BigDecimal.ZERO)
.serviceDuration("")
.commodityName("")
.commodityNumber("0")
.build())
.paymentInfo(PaymentInfo.builder()
.orderMoney(new BigDecimal(vo.getMoney()))
.finalAmount(new BigDecimal(vo.getMoney()))
.discountAmount(BigDecimal.ZERO)
.couponIds(new ArrayList<>())
.build())
.purchaserBy(userId)
.acceptBy(vo.getClerkId())
.weiChatCode(vo.getWeiChatCode())
.remark(vo.getRemark())
.build();
playOrderInfoService.createOrderInfo(orderRequest);
// 顾客减少余额
customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(), customUserInfo.getAccountBalance().subtract(new BigDecimal(vo.getMoney())), "1", "打赏", new BigDecimal(vo.getMoney()), BigDecimal.ZERO, orderId);
return R.ok("成功");
@@ -247,7 +280,34 @@ public class WxCustomController {
}
String orderId = IdUtils.getUuid();
// 记录订单信息
playOrderInfoService.createOrderInfo(orderId, playOrderInfoService.getOrderNo(), "3", "2", "2", "1", "1", giftInfo.getId(), "0", giftInfo.getPrice(), "", giftInfo.getName(), String.valueOf(vo.getGiftQuantity()), money, money, BigDecimal.ZERO, userId, vo.getClerkId(), vo.getWeiChatCode(), new ArrayList<>(), vo.getRemark(), "", "", "");
OrderCreationRequest orderRequest = OrderCreationRequest.builder()
.orderId(orderId)
.orderNo(playOrderInfoService.getOrderNo())
.orderStatus(OrderConstant.OrderStatus.COMPLETED)
.orderType(OrderConstant.OrderType.NORMAL)
.placeType(OrderConstant.PlaceType.REWARD)
.rewardType(RewardType.GIFT)
.isFirstOrder(true)
.commodityInfo(CommodityInfo.builder()
.commodityId(giftInfo.getId())
.commodityType(OrderConstant.CommodityType.GIFT)
.commodityPrice(giftInfo.getPrice())
.serviceDuration("")
.commodityName(giftInfo.getName())
.commodityNumber(String.valueOf(vo.getGiftQuantity()))
.build())
.paymentInfo(PaymentInfo.builder()
.orderMoney(money)
.finalAmount(money)
.discountAmount(BigDecimal.ZERO)
.couponIds(new ArrayList<>())
.build())
.purchaserBy(userId)
.acceptBy(vo.getClerkId())
.weiChatCode(vo.getWeiChatCode())
.remark(vo.getRemark())
.build();
playOrderInfoService.createOrderInfo(orderRequest);
// 顾客减少余额
customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(), customUserInfo.getAccountBalance().subtract(money), "1", "赠送礼物", money, BigDecimal.ZERO, orderId);
// 陪聊增加余额
@@ -329,7 +389,34 @@ public class WxCustomController {
String orderId = IdUtils.getUuid();
String orderNo = playOrderInfoService.getOrderNo();
// 记录订单信息
playOrderInfoService.createOrderInfo(orderId, orderNo, "0", "2", "0", "", "1", commodityInfo.getCommodityId(), "1", commodityInfo.getCommodityPrice(), commodityInfo.getServiceDuration(), commodityInfo.getCommodityName(), String.valueOf(vo.getCommodityQuantity()), money, money, BigDecimal.ZERO, customId, clerkUserInfo.getId(), vo.getWeiChatCode(), vo.getCouponIds(), vo.getRemark(), "", "", "");
OrderCreationRequest orderRequest = OrderCreationRequest.builder()
.orderId(orderId)
.orderNo(orderNo)
.orderStatus(OrderConstant.OrderStatus.PENDING)
.orderType(OrderConstant.OrderType.NORMAL)
.placeType(OrderConstant.PlaceType.SPECIFIED)
.rewardType(RewardType.NOT_APPLICABLE)
.isFirstOrder(true)
.commodityInfo(CommodityInfo.builder()
.commodityId(commodityInfo.getCommodityId())
.commodityType(OrderConstant.CommodityType.SERVICE)
.commodityPrice(commodityInfo.getCommodityPrice())
.serviceDuration(commodityInfo.getServiceDuration())
.commodityName(commodityInfo.getCommodityName())
.commodityNumber(String.valueOf(vo.getCommodityQuantity()))
.build())
.paymentInfo(PaymentInfo.builder()
.orderMoney(money)
.finalAmount(money)
.discountAmount(BigDecimal.ZERO)
.couponIds(vo.getCouponIds())
.build())
.purchaserBy(customId)
.acceptBy(clerkUserInfo.getId())
.weiChatCode(vo.getWeiChatCode())
.remark(vo.getRemark())
.build();
playOrderInfoService.createOrderInfo(orderRequest);
// 顾客减少余额
customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(), customUserInfo.getAccountBalance().subtract(money), "1", "下单-指定单", money, BigDecimal.ZERO, orderId);
// 发送通知给店员
@@ -357,7 +444,38 @@ public class WxCustomController {
String orderId = IdUtils.getUuid();
String orderNo = playOrderInfoService.getOrderNo();
// 记录订单信息
playOrderInfoService.createOrderInfo(orderId, orderNo, "0", "2", "1", "", "1", commodityInfo.getCommodityId(), "1", commodityInfo.getCommodityPrice(), commodityInfo.getServiceDuration(), commodityInfo.getCommodityName(), String.valueOf(vo.getCommodityQuantity()), money, money, BigDecimal.ZERO, customId, "", vo.getWeiChatCode(), vo.getCouponIds(), vo.getRemark(), vo.getSex(), vo.getLevelId(), vo.getExcludeHistory());
OrderCreationRequest orderRequest = OrderCreationRequest.builder()
.orderId(orderId)
.orderNo(orderNo)
.orderStatus(OrderConstant.OrderStatus.PENDING)
.orderType(OrderConstant.OrderType.NORMAL)
.placeType(OrderConstant.PlaceType.RANDOM)
.rewardType(RewardType.NOT_APPLICABLE)
.isFirstOrder(true)
.commodityInfo(CommodityInfo.builder()
.commodityId(commodityInfo.getCommodityId())
.commodityType(OrderConstant.CommodityType.SERVICE)
.commodityPrice(commodityInfo.getCommodityPrice())
.serviceDuration(commodityInfo.getServiceDuration())
.commodityName(commodityInfo.getCommodityName())
.commodityNumber(String.valueOf(vo.getCommodityQuantity()))
.build())
.paymentInfo(PaymentInfo.builder()
.orderMoney(money)
.finalAmount(money)
.discountAmount(BigDecimal.ZERO)
.couponIds(vo.getCouponIds())
.build())
.purchaserBy(customId)
.weiChatCode(vo.getWeiChatCode())
.remark(vo.getRemark())
.randomOrderRequirements(RandomOrderRequirements.builder()
.clerkGender(OrderConstant.Gender.fromCode(vo.getSex()))
.clerkLevelId(vo.getLevelId())
.excludeHistory(vo.getExcludeHistory())
.build())
.build();
playOrderInfoService.createOrderInfo(orderRequest);
// 顾客减少余额
customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(), customUserInfo.getAccountBalance().subtract(money), "1", "下单-随机单", money, BigDecimal.ZERO, orderId);
// 给全部店员发送通知