diff --git a/.codex_balance_charge_write_test b/.codex_balance_charge_write_test new file mode 100644 index 0000000..e69de29 diff --git a/modules/common/system/controller/FileController.java b/modules/common/system/controller/FileController.java index 5c00c1a..0692ed1 100644 --- a/modules/common/system/controller/FileController.java +++ b/modules/common/system/controller/FileController.java @@ -30,9 +30,17 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.imageio.ImageIO; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.HashMap; import java.util.List; @@ -46,6 +54,11 @@ import java.util.List; @RestController @RequestMapping("/api/file") public class FileController extends BaseController { + private static final int FACE_MIN_WIDTH = 480; + private static final int FACE_MIN_HEIGHT = 640; + private static final int FACE_MAX_WIDTH = 1080; + private static final int FACE_MAX_HEIGHT = 1920; + @Resource private ConfigProperties config; @Resource @@ -172,6 +185,40 @@ public class FileController extends BaseController { } } + @PreAuthorize("hasAuthority('sys:file:upload')") + @OperationLog + @ApiOperation("上传人脸图片并返回base64") + @PostMapping("/upload/face") + public ApiResult uploadFace(@RequestParam MultipartFile file) { + try { + if (file == null || file.isEmpty()) { + return fail("上传失败,文件为空", null); + } + byte[] originalBytes = file.getBytes(); + BufferedImage image; + try (ByteArrayInputStream inputStream = new ByteArrayInputStream(originalBytes)) { + image = ImageIO.read(inputStream); + } + if (image == null) { + return fail("上传失败,无法解析图片", null); + } + int width = image.getWidth(); + int height = image.getHeight(); + boolean inRange = width >= FACE_MIN_WIDTH && height >= FACE_MIN_HEIGHT + && width <= FACE_MAX_WIDTH && height <= FACE_MAX_HEIGHT; + boolean isJpeg = isJpegImage(file.getContentType(), file.getOriginalFilename()); + if (inRange && isJpeg) { + return success(Base64.getEncoder().encodeToString(originalBytes)); + } + BufferedImage converted = resizeToRange(toRgbImage(image), width, height); + byte[] jpegBytes = toJpegBytes(converted); + return success(Base64.getEncoder().encodeToString(jpegBytes)); + } catch (Exception e) { + e.printStackTrace(); + return fail("上传失败", null).setError(e.toString()); + } + } + @PreAuthorize("hasAuthority('sys:file:list')") @OperationLog @ApiOperation("根据id查询文件") @@ -350,4 +397,61 @@ public class FileController extends BaseController { return fail("修改失败"); } + private static boolean isJpegImage(String contentType, String fileName) { + if (contentType != null) { + String ct = contentType.toLowerCase(); + if (ct.contains("jpeg") || ct.contains("jpg")) { + return true; + } + } + if (fileName != null) { + String lower = fileName.toLowerCase(); + return lower.endsWith(".jpg") || lower.endsWith(".jpeg"); + } + return false; + } + + private static BufferedImage toRgbImage(BufferedImage source) { + if (source.getType() == BufferedImage.TYPE_INT_RGB) { + return source; + } + BufferedImage rgb = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = rgb.createGraphics(); + g2d.setColor(Color.WHITE); + g2d.fillRect(0, 0, rgb.getWidth(), rgb.getHeight()); + g2d.drawImage(source, 0, 0, null); + g2d.dispose(); + return rgb; + } + + private static BufferedImage resizeToRange(BufferedImage image, int width, int height) { + double scale = 1.0; + if (width < FACE_MIN_WIDTH || height < FACE_MIN_HEIGHT) { + scale = Math.max(FACE_MIN_WIDTH / (double) width, FACE_MIN_HEIGHT / (double) height); + } else if (width > FACE_MAX_WIDTH || height > FACE_MAX_HEIGHT) { + scale = Math.min(FACE_MAX_WIDTH / (double) width, FACE_MAX_HEIGHT / (double) height); + } else { + return image; + } + int targetWidth = Math.max(1, (int) Math.round(width * scale)); + int targetHeight = Math.max(1, (int) Math.round(height * scale)); + BufferedImage resized = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = resized.createGraphics(); + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.drawImage(image, 0, 0, targetWidth, targetHeight, null); + g2d.dispose(); + return resized; + } + + private static byte[] toJpegBytes(BufferedImage image) throws Exception { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + if (!ImageIO.write(image, "jpg", outputStream)) { + throw new IllegalStateException("jpeg encode fail"); + } + return outputStream.toByteArray(); + } + } + } diff --git a/modules/shop/controller/RechargeOrderController.java b/modules/shop/controller/RechargeOrderController.java index 34bcf56..2d91463 100644 --- a/modules/shop/controller/RechargeOrderController.java +++ b/modules/shop/controller/RechargeOrderController.java @@ -4,9 +4,6 @@ import cn.hutool.core.util.IdUtil; import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.system.service.UserService; import com.gxwebsoft.shop.entity.UserBalanceLog; -import com.gxwebsoft.shop.service.RechargeOrderService; -import com.gxwebsoft.shop.entity.RechargeOrder; -import com.gxwebsoft.shop.param.RechargeOrderParam; import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.BatchParam; diff --git a/modules/shop/controller/UserBalanceLogController.java b/modules/shop/controller/UserBalanceLogController.java index 3ad5ce8..c126577 100644 --- a/modules/shop/controller/UserBalanceLogController.java +++ b/modules/shop/controller/UserBalanceLogController.java @@ -8,14 +8,18 @@ import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.BatchParam; import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.common.system.service.UserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.math.BigDecimal; import java.util.List; +import static com.gxwebsoft.common.core.constants.BalanceConstants.BALANCE_ADMIN; + /** * 用户余额变动明细表控制器 * @@ -28,6 +32,8 @@ import java.util.List; public class UserBalanceLogController extends BaseController { @Resource private UserBalanceLogService userBalanceLogService; + @Resource + private UserService userService; @ApiOperation("分页查询用户余额变动明细表") @GetMapping("/page") @@ -54,10 +60,33 @@ public class UserBalanceLogController extends BaseController { @ApiOperation("添加用户余额变动明细表") @PostMapping() public ApiResult save(@RequestBody UserBalanceLog userBalanceLog) { - // 记录当前登录用户id + if (userBalanceLog.getUserId() == null) { + return fail("用户ID不能为空"); + } + if (userBalanceLog.getMoney() == null || userBalanceLog.getMoney().compareTo(BigDecimal.ZERO) <= 0) { + return fail("充值金额必须大于0"); + } + User user = userService.addBalanceInner(userBalanceLog.getUserId(), userBalanceLog.getMoney()); + if (user == null) { + return fail("用户不存在"); + } User loginUser = getLoginUser(); - if (loginUser != null) { - userBalanceLog.setUserId(loginUser.getUserId()); + if (userBalanceLog.getScene() == null) { + userBalanceLog.setScene(BALANCE_ADMIN); + } + userBalanceLog.setBalance(user.getBalance()); + if (loginUser != null && userBalanceLog.getAdminId() == null) { + userBalanceLog.setAdminId(loginUser.getUserId()); + } + if ((userBalanceLog.getComments() == null || userBalanceLog.getComments().trim().isEmpty()) + && userBalanceLog.getRemark() != null) { + userBalanceLog.setComments(userBalanceLog.getRemark()); + } + if (userBalanceLog.getStatus() == null) { + userBalanceLog.setStatus(0); + } + if (userBalanceLog.getDeleted() == null) { + userBalanceLog.setDeleted(0); } if (userBalanceLogService.save(userBalanceLog)) { return success("添加成功"); diff --git a/modules/shop/mapper/RechargeOrderMapper.java b/modules/shop/mapper/RechargeOrderMapper.java index c27a982..8cc2bfb 100644 --- a/modules/shop/mapper/RechargeOrderMapper.java +++ b/modules/shop/mapper/RechargeOrderMapper.java @@ -2,8 +2,6 @@ package com.gxwebsoft.shop.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; -import com.gxwebsoft.shop.entity.RechargeOrder; -import com.gxwebsoft.shop.param.RechargeOrderParam; import org.apache.ibatis.annotations.Param; import java.util.List; diff --git a/modules/shop/service/RechargeOrderService.java b/modules/shop/service/RechargeOrderService.java index 94a7dc2..92966cf 100644 --- a/modules/shop/service/RechargeOrderService.java +++ b/modules/shop/service/RechargeOrderService.java @@ -2,8 +2,6 @@ package com.gxwebsoft.shop.service; import com.baomidou.mybatisplus.extension.service.IService; import com.gxwebsoft.common.core.web.PageResult; -import com.gxwebsoft.shop.entity.RechargeOrder; -import com.gxwebsoft.shop.param.RechargeOrderParam; import java.util.List; diff --git a/modules/shop/service/impl/RechargeOrderServiceImpl.java b/modules/shop/service/impl/RechargeOrderServiceImpl.java index b7fefd3..e9c4f6c 100644 --- a/modules/shop/service/impl/RechargeOrderServiceImpl.java +++ b/modules/shop/service/impl/RechargeOrderServiceImpl.java @@ -1,10 +1,6 @@ package com.gxwebsoft.shop.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.gxwebsoft.shop.mapper.RechargeOrderMapper; -import com.gxwebsoft.shop.service.RechargeOrderService; -import com.gxwebsoft.shop.entity.RechargeOrder; -import com.gxwebsoft.shop.param.RechargeOrderParam; import com.gxwebsoft.common.core.web.PageParam; import com.gxwebsoft.common.core.web.PageResult; import org.springframework.stereotype.Service; diff --git a/pom.xml b/pom.xml index b231a39..94956ea 100644 --- a/pom.xml +++ b/pom.xml @@ -104,6 +104,11 @@ mybatis-plus-generator 3.4.1 + + com.baomidou + dynamic-datasource-spring-boot-starter + 3.4.1 + diff --git a/sql/alter_think_vip_add_training_institution.sql b/sql/alter_think_vip_add_training_institution.sql new file mode 100644 index 0000000..b10a1fe --- /dev/null +++ b/sql/alter_think_vip_add_training_institution.sql @@ -0,0 +1,3 @@ +ALTER TABLE `think_vip` +ADD COLUMN `training_institution_id` int NULL DEFAULT NULL COMMENT '培训机构ID' AFTER `vip_type`, +ADD KEY `idx_training_institution_id` (`training_institution_id`); diff --git a/sql/sys_user_request_record.sql b/sql/sys_user_request_record.sql new file mode 100644 index 0000000..f96da8d --- /dev/null +++ b/sql/sys_user_request_record.sql @@ -0,0 +1,16 @@ +CREATE TABLE `sys_user_request_record` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user_id` int NOT NULL COMMENT '用户ID', + `phone` varchar(20) DEFAULT NULL COMMENT '手机号', + `url` varchar(255) NOT NULL COMMENT '请求接口', + `request_method` varchar(10) DEFAULT NULL COMMENT '请求方式', + `ip` varchar(50) DEFAULT NULL COMMENT 'IP地址', + `tenant_id` int DEFAULT NULL COMMENT '租户ID', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '请求时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_phone` (`phone`), + KEY `idx_url` (`url`), + KEY `idx_ip` (`ip`), + KEY `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户接口请求记录表'; diff --git a/sql/think_training_institution.sql b/sql/think_training_institution.sql new file mode 100644 index 0000000..2c87e8c --- /dev/null +++ b/sql/think_training_institution.sql @@ -0,0 +1,11 @@ +CREATE TABLE `think_training_institution` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` varchar(100) NOT NULL COMMENT '机构名称', + `contact_name` varchar(50) NOT NULL COMMENT '联系人', + `contact_phone` varchar(20) NOT NULL COMMENT '联系方式', + `create_time` int NOT NULL DEFAULT '0' COMMENT '创建时间', + `update_time` int NOT NULL DEFAULT '0' COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_contact_phone` (`contact_phone`), + KEY `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='培训机构表'; diff --git a/src/main/java/com/gxwebsoft/common/core/config/MybatisPlusConfig.java b/src/main/java/com/gxwebsoft/common/core/config/MybatisPlusConfig.java index a262e4f..bb8dfc8 100644 --- a/src/main/java/com/gxwebsoft/common/core/config/MybatisPlusConfig.java +++ b/src/main/java/com/gxwebsoft/common/core/config/MybatisPlusConfig.java @@ -15,6 +15,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; @@ -32,28 +35,31 @@ public class MybatisPlusConfig { private RedisUtil redisUtil; @Bean - public MybatisPlusInterceptor mybatisPlusInterceptor(HttpServletRequest request) { + public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 多租户插件配置 TenantLineHandler tenantLineHandler = new TenantLineHandler() { @Override public Expression getTenantId() { + HttpServletRequest request = getCurrentRequest(); // 从域名拿ID - String Domain = request.getHeader("Domain"); - if (StrUtil.isNotBlank(Domain)) { - String key = "Domain:" + Domain; - String tenantId = redisUtil.get(key); + if (request != null) { + String Domain = request.getHeader("Domain"); + if (StrUtil.isNotBlank(Domain)) { + String key = "Domain:" + Domain; + String tenantId = redisUtil.get(key); + if (tenantId != null) { + System.out.println("从域名拿TID = " + tenantId); + return new LongValue(tenantId); + } + } + // 从请求头拿ID + final String tenantId = request.getHeader("tenantId"); if (tenantId != null) { - System.out.println("从域名拿TID = " + tenantId); return new LongValue(tenantId); } } - // 从请求头拿ID - final String tenantId = request.getHeader("tenantId"); - if (tenantId != null) { - return new LongValue(tenantId); - } // return getLoginUserTenantId(); return new LongValue(10150); } @@ -137,7 +143,11 @@ public class MybatisPlusConfig { "think_wechat_bill_log", "think_wechat_deposit", "think_card_balance", - "sys_log" + "sys_log", + "think_small_recharge", + "think_user_in_access", + "think_users_black", + "think_training_institution" // "booking_user", // "booking_user_card", @@ -200,4 +210,12 @@ public class MybatisPlusConfig { return new NullValue(); } + private HttpServletRequest getCurrentRequest() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + if (requestAttributes instanceof ServletRequestAttributes) { + return ((ServletRequestAttributes) requestAttributes).getRequest(); + } + return null; + } + } diff --git a/src/main/java/com/gxwebsoft/common/core/config/SchedulingConfig.java b/src/main/java/com/gxwebsoft/common/core/config/SchedulingConfig.java new file mode 100644 index 0000000..22b518b --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/config/SchedulingConfig.java @@ -0,0 +1,23 @@ +package com.gxwebsoft.common.core.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +/** + * 定时任务线程池配置 + */ +@Configuration +public class SchedulingConfig { + + @Bean + public TaskScheduler taskScheduler() { + ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); + scheduler.setPoolSize(4); + scheduler.setThreadNamePrefix("scheduled-"); + scheduler.setWaitForTasksToCompleteOnShutdown(true); + scheduler.setAwaitTerminationSeconds(30); + return scheduler; + } +} diff --git a/src/main/java/com/gxwebsoft/common/core/security/JwtAuthenticationFilter.java b/src/main/java/com/gxwebsoft/common/core/security/JwtAuthenticationFilter.java index 000948d..2d31f2a 100644 --- a/src/main/java/com/gxwebsoft/common/core/security/JwtAuthenticationFilter.java +++ b/src/main/java/com/gxwebsoft/common/core/security/JwtAuthenticationFilter.java @@ -1,6 +1,7 @@ package com.gxwebsoft.common.core.security; import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.http.HttpRequest; import com.alibaba.fastjson.JSONObject; import com.gxwebsoft.common.core.Constants; @@ -11,6 +12,8 @@ import com.gxwebsoft.common.core.utils.RedisUtil; import com.gxwebsoft.common.core.utils.SignCheckUtil; import com.gxwebsoft.common.system.entity.Menu; import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.common.system.entity.UserRequestRecord; +import com.gxwebsoft.common.system.service.UserRequestRecordService; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -25,6 +28,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; @@ -41,6 +45,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { private ConfigProperties configProperties; @Resource private RedisUtil redisUtil; + @Resource + private UserRequestRecordService userRequestRecordService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) @@ -83,6 +89,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( user, null, authorities); SecurityContextHolder.getContext().setAuthentication(authentication); + saveUserRequestRecord(user, request); // token将要过期签发新token, 防止突然退出登录 // long expiration = (claims.getExpiration().getTime() - new Date().getTime()) / 1000 / 60; @@ -109,4 +116,22 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { chain.doFilter(request, response); } + /** + * 保存登录用户接口请求记录 + */ + private void saveUserRequestRecord(User user, HttpServletRequest request) { + if (user == null || user.getUserId() == null) { + return; + } + UserRequestRecord record = new UserRequestRecord(); + record.setUserId(user.getUserId()); + record.setPhone(user.getPhone()); + record.setUrl(request.getRequestURI()); + record.setRequestMethod(request.getMethod()); + record.setIp(ServletUtil.getClientIP(request)); + record.setTenantId(user.getTenantId()); + record.setCreateTime(new Date()); + userRequestRecordService.saveAsync(record); + } + } diff --git a/src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java b/src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java index 5cfb786..f8ebadc 100644 --- a/src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java +++ b/src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java @@ -81,7 +81,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { "/api/think/think-cards-bills/make-bill", "/api/think/think-recharge-log/refund-notify", "/api/think/think-ftp-check-bill/async", - "/api/think/think-card-balance/set-data" + "/api/think/think-card-balance/set-data", + "/api/think/think-invoice/getRes", + "/api/think/think-small-recharge/notify", + "/api/shop/balance-charge-log/notify", + "/api/shop/balance-charge-log/refund-notify", + "/api/think/gate-control/**" // "/api/think/think-order/fixInvoiceData" ) .permitAll() diff --git a/src/main/java/com/gxwebsoft/common/core/utils/RedisUtil.java b/src/main/java/com/gxwebsoft/common/core/utils/RedisUtil.java index f02ce42..e5b6e87 100644 --- a/src/main/java/com/gxwebsoft/common/core/utils/RedisUtil.java +++ b/src/main/java/com/gxwebsoft/common/core/utils/RedisUtil.java @@ -50,6 +50,11 @@ public class RedisUtil { stringRedisTemplate.opsForValue().set(key, JSONUtil.toJSONString(entity),time,unit); } + public boolean setIfAbsent(String key, String value, Long time, TimeUnit unit){ + Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(key, value, time, unit); + return Boolean.TRUE.equals(success); + } + /** * 读取redis缓存 * @param key [表名]:id diff --git a/src/main/java/com/gxwebsoft/common/system/controller/FileController.java b/src/main/java/com/gxwebsoft/common/system/controller/FileController.java index c5480c1..2970e11 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/FileController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/FileController.java @@ -23,9 +23,17 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.imageio.ImageIO; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.HashMap; import java.util.List; @@ -39,6 +47,11 @@ import java.util.List; @RestController @RequestMapping("/api/file") public class FileController extends BaseController { + private static final int FACE_MIN_WIDTH = 480; + private static final int FACE_MIN_HEIGHT = 640; + private static final int FACE_MAX_WIDTH = 1080; + private static final int FACE_MAX_HEIGHT = 1920; + @Resource private ConfigProperties config; @Resource @@ -157,6 +170,39 @@ public class FileController extends BaseController { } } + @PreAuthorize("hasAuthority('sys:file:upload')") + @ApiOperation("上传人脸图片并返回base64") + @PostMapping("/upload/face") + public ApiResult uploadFace(@RequestParam MultipartFile file) { + try { + if (file == null || file.isEmpty()) { + return fail("上传失败,文件为空", null); + } + byte[] originalBytes = file.getBytes(); + BufferedImage image; + try (ByteArrayInputStream inputStream = new ByteArrayInputStream(originalBytes)) { + image = ImageIO.read(inputStream); + } + if (image == null) { + return fail("上传失败,无法解析图片", null); + } + int width = image.getWidth(); + int height = image.getHeight(); + boolean inRange = width >= FACE_MIN_WIDTH && height >= FACE_MIN_HEIGHT + && width <= FACE_MAX_WIDTH && height <= FACE_MAX_HEIGHT; + boolean isJpeg = isJpegImage(file.getContentType(), file.getOriginalFilename()); + if (inRange && isJpeg) { + return success(Base64.getEncoder().encodeToString(originalBytes)); + } + BufferedImage converted = resizeToRange(toRgbImage(image), width, height); + byte[] jpegBytes = toJpegBytes(converted); + return success("上传成功", Base64.getEncoder().encodeToString(jpegBytes)); + } catch (Exception e) { + e.printStackTrace(); + return fail("上传失败", null).setError(e.toString()); + } + } + @PreAuthorize("hasAuthority('sys:file:list')") @ApiOperation("根据id查询文件") @GetMapping("/{id}") @@ -324,4 +370,61 @@ public class FileController extends BaseController { return fail("修改失败"); } + private static boolean isJpegImage(String contentType, String fileName) { + if (contentType != null) { + String ct = contentType.toLowerCase(); + if (ct.contains("jpeg") || ct.contains("jpg")) { + return true; + } + } + if (fileName != null) { + String lower = fileName.toLowerCase(); + return lower.endsWith(".jpg") || lower.endsWith(".jpeg"); + } + return false; + } + + private static BufferedImage toRgbImage(BufferedImage source) { + if (source.getType() == BufferedImage.TYPE_INT_RGB) { + return source; + } + BufferedImage rgb = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = rgb.createGraphics(); + g2d.setColor(Color.WHITE); + g2d.fillRect(0, 0, rgb.getWidth(), rgb.getHeight()); + g2d.drawImage(source, 0, 0, null); + g2d.dispose(); + return rgb; + } + + private static BufferedImage resizeToRange(BufferedImage image, int width, int height) { + double scale = 1.0; + if (width < FACE_MIN_WIDTH || height < FACE_MIN_HEIGHT) { + scale = Math.max(FACE_MIN_WIDTH / (double) width, FACE_MIN_HEIGHT / (double) height); + } else if (width > FACE_MAX_WIDTH || height > FACE_MAX_HEIGHT) { + scale = Math.min(FACE_MAX_WIDTH / (double) width, FACE_MAX_HEIGHT / (double) height); + } else { + return image; + } + int targetWidth = Math.max(1, (int) Math.round(width * scale)); + int targetHeight = Math.max(1, (int) Math.round(height * scale)); + BufferedImage resized = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = resized.createGraphics(); + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.drawImage(image, 0, 0, targetWidth, targetHeight, null); + g2d.dispose(); + return resized; + } + + private static byte[] toJpegBytes(BufferedImage image) throws Exception { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + if (!ImageIO.write(image, "jpg", outputStream)) { + throw new IllegalStateException("jpeg encode fail"); + } + return outputStream.toByteArray(); + } + } + } diff --git a/src/main/java/com/gxwebsoft/common/system/entity/UserRequestRecord.java b/src/main/java/com/gxwebsoft/common/system/entity/UserRequestRecord.java new file mode 100644 index 0000000..f575824 --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/system/entity/UserRequestRecord.java @@ -0,0 +1,50 @@ +package com.gxwebsoft.common.system.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 用户接口请求记录 + * + * @author WebSoft + * @since 2026-07-29 + */ +@Data +@ApiModel(description = "用户接口请求记录") +@TableName("sys_user_request_record") +public class UserRequestRecord implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(type = IdType.AUTO) + private Integer id; + + @ApiModelProperty("用户id") + private Integer userId; + + @ApiModelProperty("手机号") + private String phone; + + @ApiModelProperty("请求接口") + private String url; + + @ApiModelProperty("请求方式") + private String requestMethod; + + @ApiModelProperty("ip地址") + private String ip; + + @ApiModelProperty(value = "租户id") + private Integer tenantId; + + @ApiModelProperty("请求时间") + private Date createTime; + +} diff --git a/src/main/java/com/gxwebsoft/common/system/mapper/UserRequestRecordMapper.java b/src/main/java/com/gxwebsoft/common/system/mapper/UserRequestRecordMapper.java new file mode 100644 index 0000000..db1476b --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/system/mapper/UserRequestRecordMapper.java @@ -0,0 +1,25 @@ +package com.gxwebsoft.common.system.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gxwebsoft.common.system.entity.UserRequestRecord; + +/** + * 用户接口请求记录Mapper + * + * @author WebSoft + * @since 2026-07-29 + */ +public interface UserRequestRecordMapper extends BaseMapper { + + /** + * 添加, 排除租户拦截 + * + * @param entity UserRequestRecord + * @return int + */ + @Override + @InterceptorIgnore(tenantLine = "true") + int insert(UserRequestRecord entity); + +} diff --git a/src/main/java/com/gxwebsoft/common/system/service/UserRequestRecordService.java b/src/main/java/com/gxwebsoft/common/system/service/UserRequestRecordService.java new file mode 100644 index 0000000..5d52d50 --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/system/service/UserRequestRecordService.java @@ -0,0 +1,21 @@ +package com.gxwebsoft.common.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gxwebsoft.common.system.entity.UserRequestRecord; + +/** + * 用户接口请求记录Service + * + * @author WebSoft + * @since 2026-07-29 + */ +public interface UserRequestRecordService extends IService { + + /** + * 异步添加 + * + * @param userRequestRecord UserRequestRecord + */ + void saveAsync(UserRequestRecord userRequestRecord); + +} diff --git a/src/main/java/com/gxwebsoft/common/system/service/UserService.java b/src/main/java/com/gxwebsoft/common/system/service/UserService.java index e26372f..6dc90ad 100644 --- a/src/main/java/com/gxwebsoft/common/system/service/UserService.java +++ b/src/main/java/com/gxwebsoft/common/system/service/UserService.java @@ -1,11 +1,13 @@ package com.gxwebsoft.common.system.service; +import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.extension.service.IService; import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.param.UserParam; import org.springframework.security.core.userdetails.UserDetailsService; +import java.math.BigDecimal; import java.util.List; /** @@ -99,6 +101,27 @@ public interface UserService extends IService, UserDetailsService { User getByUnionId(UserParam userParam); + @DS("server") + User getByIdInner(Integer id); + + @DS("server") + User getByUidInner(Integer uid); + + @DS("server") + User getByPhoneInner(String phone); + + @DS("server") + List listByPhoneInner(String phone); + + @DS("server") + List listByIdsInner(List userIds); + + @DS("server") + Boolean updateInner(User user); + + @DS("server") + User addBalanceInner(Integer userId, BigDecimal amount); + User getByOauthId(UserParam userParam); List listStatisticsRel(UserParam param); diff --git a/src/main/java/com/gxwebsoft/common/system/service/impl/UserRequestRecordServiceImpl.java b/src/main/java/com/gxwebsoft/common/system/service/impl/UserRequestRecordServiceImpl.java new file mode 100644 index 0000000..32cade5 --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/system/service/impl/UserRequestRecordServiceImpl.java @@ -0,0 +1,29 @@ +package com.gxwebsoft.common.system.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gxwebsoft.common.system.entity.UserRequestRecord; +import com.gxwebsoft.common.system.mapper.UserRequestRecordMapper; +import com.gxwebsoft.common.system.service.UserRequestRecordService; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +/** + * 用户接口请求记录Service实现 + * + * @author WebSoft + * @since 2026-07-29 + */ +@Service +public class UserRequestRecordServiceImpl extends ServiceImpl + implements UserRequestRecordService { + + @Async + @Override + public void saveAsync(UserRequestRecord userRequestRecord) { + if (userRequestRecord == null || userRequestRecord.getUserId() == null) { + return; + } + baseMapper.insert(userRequestRecord); + } + +} diff --git a/src/main/java/com/gxwebsoft/common/system/service/impl/UserServiceImpl.java b/src/main/java/com/gxwebsoft/common/system/service/impl/UserServiceImpl.java index 694ab34..660f618 100644 --- a/src/main/java/com/gxwebsoft/common/system/service/impl/UserServiceImpl.java +++ b/src/main/java/com/gxwebsoft/common/system/service/impl/UserServiceImpl.java @@ -1,7 +1,7 @@ package com.gxwebsoft.common.system.service.impl; import cn.hutool.core.util.StrUtil; -import com.alibaba.fastjson.JSONObject; +import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -17,7 +17,6 @@ import com.gxwebsoft.common.system.param.UserParam; import com.gxwebsoft.common.system.service.RoleMenuService; import com.gxwebsoft.common.system.service.UserRoleService; import com.gxwebsoft.common.system.service.UserService; -import com.gxwebsoft.oa.entity.Company; import com.gxwebsoft.oa.service.CompanyService; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; @@ -27,9 +26,8 @@ import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; -import java.util.HashMap; +import java.math.BigDecimal; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; /** @@ -193,6 +191,59 @@ public class UserServiceImpl extends ServiceImpl implements Us return param.getOne(baseMapper.getOne(param)); } + @Override + @DS("server") + public User getByIdInner(Integer id) { + return getOne(new LambdaQueryWrapper().eq(User::getUserId, id)); + } + + @DS("server") + @Override + public User getByUidInner(Integer uid) { + return getOne(new LambdaQueryWrapper().eq(User::getUid, uid)); + } + + @Override + @DS("server") + public User getByPhoneInner(String phone) { + return getOne(new LambdaQueryWrapper().eq(User::getPhone, phone)); + } + + @Override + @DS("server") + public List listByPhoneInner(String phone) { + return list(new LambdaQueryWrapper() + .like(User::getPhone, phone) + .select(User::getUserId, User::getPhone)); + } + + @Override + @DS("server") + public List listByIdsInner(List userIds) { + return list(new LambdaQueryWrapper() + .in(User::getUserId, userIds) + .select(User::getUserId, User::getPhone)); + } + + @Override + @DS("server") + public Boolean updateInner(User user) { + return updateById(user); + } + + @Override + @DS("server") + public User addBalanceInner(Integer userId, BigDecimal amount) { + User user = getOne(new LambdaQueryWrapper().eq(User::getUserId, userId)); + if (user == null) { + return null; + } + BigDecimal currentBalance = user.getBalance() == null ? BigDecimal.ZERO : user.getBalance(); + user.setBalance(currentBalance.add(amount)); + updateById(user); + return user; + } + @Override public User getByOauthId(UserParam userParam) { return userParam.getOne(baseMapper.getOne(userParam)); diff --git a/src/main/java/com/gxwebsoft/shop/controller/BalanceChargeLogController.java b/src/main/java/com/gxwebsoft/shop/controller/BalanceChargeLogController.java new file mode 100644 index 0000000..1ac4b20 --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/controller/BalanceChargeLogController.java @@ -0,0 +1,352 @@ +package com.gxwebsoft.shop.controller; + +import cn.hutool.core.util.RandomUtil; +import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.common.system.service.UserService; +import com.gxwebsoft.shop.entity.UserBalanceLog; +import com.gxwebsoft.shop.service.UserBalanceLogService; +import com.gxwebsoft.shop.service.BalanceChargeLogService; +import com.gxwebsoft.shop.entity.BalanceChargeLog; +import com.gxwebsoft.shop.param.BalanceChargeLogParam; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.common.core.web.BatchParam; +import com.gxwebsoft.think.service.ThinkOrderService; +import com.gxwebsoft.think.service.WechatConfigService; +import com.wechat.pay.java.core.Config; +import com.wechat.pay.java.core.notification.NotificationConfig; +import com.wechat.pay.java.core.notification.NotificationParser; +import com.wechat.pay.java.core.notification.RequestParam; +import com.wechat.pay.java.service.refund.RefundService; +import com.wechat.pay.java.service.refund.model.AmountReq; +import com.wechat.pay.java.service.refund.model.CreateRequest; +import com.wechat.pay.java.service.refund.model.RefundNotification; +import com.wechat.pay.java.service.refund.model.Status; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; + +/** + * 控制器 + * + * @author LX + * @since 2026-05-07 14:57:22 + */ +@Api(tags = "管理") +@RestController +@RequestMapping("/api/shop/balance-charge-log") +public class BalanceChargeLogController extends BaseController { + private static final DateTimeFormatter ORDER_NO_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + + @Resource + private BalanceChargeLogService balanceChargeLogService; + @Resource + private ThinkOrderService thinkOrderService; + @Resource + private WechatConfigService wechatConfigService; + @Resource + private UserService userService; + @Resource + private UserBalanceLogService userBalanceLogService; + + @ApiOperation("分页查询") + @GetMapping("/page") + public ApiResult> page(BalanceChargeLogParam param) { + // 使用关联查询 + return success(balanceChargeLogService.pageRel(param)); + } + + @ApiOperation("查询全部") + @GetMapping() + public ApiResult> list(BalanceChargeLogParam param) { + // 使用关联查询 + return success(balanceChargeLogService.listRel(param)); + } + + @PreAuthorize("hasAuthority('shop:balanceChargeLog:list')") + @ApiOperation("根据id查询") + @GetMapping("/{id}") + public ApiResult get(@PathVariable("id") Integer id) { + // 使用关联查询 + return success(balanceChargeLogService.getByIdRel(id)); + } + + @Transactional(rollbackFor = Exception.class) + @ApiOperation("余额充值") + @PostMapping("/recharge") + public ApiResult recharge(@RequestBody BalanceChargeLog balanceChargeLog) { + if (getLoginUserId() == null) { + return fail("请先登录"); + } + if (balanceChargeLog.getAmount() == null || balanceChargeLog.getAmount().compareTo(BigDecimal.ZERO) <= 0) { + return fail("充值金额必须大于0"); + } + User loginUser = getLoginUser(); + if (loginUser == null || loginUser.getOpenid() == null || loginUser.getOpenid().trim().isEmpty()) { + return fail("当前账号未绑定微信"); + } + + LocalDateTime now = LocalDateTime.now(); + BalanceChargeLog chargeLog = new BalanceChargeLog(); + chargeLog.setAmount(balanceChargeLog.getAmount().setScale(2, RoundingMode.HALF_UP)); + chargeLog.setUserId(getLoginUserId()); + chargeLog.setTenantId(getTenantId()); + chargeLog.setIsPaid(0); + chargeLog.setRemark(balanceChargeLog.getRemark() == null || balanceChargeLog.getRemark().trim().isEmpty() + ? "用户余额充值" + : balanceChargeLog.getRemark().trim()); + chargeLog.setOrderNo(ORDER_NO_FORMATTER.format(now) + RandomUtil.randomNumbers(5)); + chargeLog.setCreateTime(now); + chargeLog.setUpdateTime(now); + + if (balanceChargeLogService.save(chargeLog)) { + String notify = "https://gxtyzx-api2.websoft.top/api/shop/balance-charge-log/notify"; + return success("下单成功", thinkOrderService.createWxOrder( + chargeLog.getAmount(), + chargeLog.getOrderNo(), + "账户余额充值", + loginUser.getOpenid(), + notify + )); + } + return fail("下单失败"); + } + + @ApiOperation("添加") + @PostMapping() + public ApiResult save(@RequestBody BalanceChargeLog balanceChargeLog) { + if (balanceChargeLogService.save(balanceChargeLog)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @ApiOperation("修改") + @PutMapping() + public ApiResult update(@RequestBody BalanceChargeLog balanceChargeLog) { + if (balanceChargeLogService.updateById(balanceChargeLog)) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @ApiOperation("退款") + @PostMapping("/refund") + public ApiResult refund(@RequestBody BalanceChargeLog balanceChargeLog) { + if (balanceChargeLog.getId() == null) { + return fail("请选择退款记录"); + } + BalanceChargeLog chargeLog = balanceChargeLogService.getById(balanceChargeLog.getId()); + if (chargeLog == null) { + return fail("充值记录不存在"); + } + if (chargeLog.getIsPaid() == null || chargeLog.getIsPaid() != 1) { + return fail("只有已支付的充值记录可以退款"); + } + if (chargeLog.getAmount() == null || chargeLog.getAmount().compareTo(BigDecimal.ZERO) <= 0) { + return fail("退款金额异常"); + } + if (chargeLog.getOrderNo() == null || chargeLog.getOrderNo().trim().isEmpty()) { + return fail("充值订单号为空"); + } + User user = userService.getByIdInner(chargeLog.getUserId()); + if (user == null) { + return fail("充值用户不存在"); + } + BigDecimal currentBalance = user.getBalance() == null ? BigDecimal.ZERO : user.getBalance(); + if (currentBalance.compareTo(chargeLog.getAmount()) < 0) { + return fail("用户余额不足,无法退款"); + } + + Config wxConfig = wechatConfigService.getConfig(); + RefundService service = new RefundService.Builder().config(wxConfig).build(); + CreateRequest request = new CreateRequest(); + AmountReq amount = new AmountReq(); + long refundAmount = chargeLog.getAmount() + .multiply(BigDecimal.valueOf(100)) + .setScale(0, RoundingMode.HALF_UP) + .longValue(); + amount.setTotal(refundAmount); + amount.setRefund(refundAmount); + amount.setCurrency("CNY"); + request.setAmount(amount); + request.setOutTradeNo(chargeLog.getOrderNo()); + request.setOutRefundNo("R" + chargeLog.getOrderNo()); + request.setNotifyUrl("https://gxtyzx-api2.websoft.top/api/shop/balance-charge-log/refund-notify"); + service.create(request); + return success("退款申请已提交"); + } + + @ApiOperation("删除") + @DeleteMapping("/{id}") + public ApiResult remove(@PathVariable("id") Integer id) { + if (balanceChargeLogService.removeById(id)) { + return success("删除成功"); + } + return fail("删除失败"); + } + + @ApiOperation("批量添加") + @PostMapping("/batch") + public ApiResult saveBatch(@RequestBody List list) { + if (balanceChargeLogService.saveBatch(list)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @ApiOperation("批量修改") + @PutMapping("/batch") + public ApiResult removeBatch(@RequestBody BatchParam batchParam) { + if (batchParam.update(balanceChargeLogService, "id")) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @ApiOperation("批量删除") + @DeleteMapping("/batch") + public ApiResult removeBatch(@RequestBody List ids) { + if (balanceChargeLogService.removeByIds(ids)) { + return success("删除成功"); + } + return fail("删除失败"); + } + + @ApiOperation("微信支付回调") + @PostMapping("/notify") + public String notify(@RequestBody String body, @RequestHeader Map header) { + try { + RequestParam requestParam = new RequestParam.Builder() + .serialNumber(header.get("wechatpay-serial").toString()) + .nonce(header.get("wechatpay-nonce").toString()) + .signature(header.get("wechatpay-signature").toString()) + .timestamp(header.get("wechatpay-timestamp").toString()) + .body(body) + .build(); + NotificationConfig config = wechatConfigService.getNotificationConfig(); + NotificationParser parser = new NotificationParser(config); + com.wechat.pay.java.service.payments.model.Transaction transaction = + parser.parse(requestParam, com.wechat.pay.java.service.payments.model.Transaction.class); + BalanceChargeLog chargeLog = balanceChargeLogService.lambdaQuery() + .eq(BalanceChargeLog::getOrderNo, transaction.getOutTradeNo()) + .last("limit 1") + .one(); + System.out.println("充值回调:" + transaction); + System.out.println("chargeLog:" + chargeLog); + if (chargeLog != null && (chargeLog.getIsPaid() == null || chargeLog.getIsPaid() == 0)) { + doCharge(chargeLog, transaction.getTransactionId()); + } + return "订单已支付"; + }catch (Exception e){ + System.out.println("充值回调错误:" + e.getMessage()); + return e.getMessage(); + } + } + + @ApiOperation("微信退款回调") + @PostMapping("/refund-notify") + public ApiResult refundNotify(@RequestBody String body, @RequestHeader Map header) { + try { + RequestParam requestParam = new RequestParam.Builder() + .serialNumber(header.get("wechatpay-serial").toString()) + .nonce(header.get("wechatpay-nonce").toString()) + .signature(header.get("wechatpay-signature").toString()) + .timestamp(header.get("wechatpay-timestamp").toString()) + .body(body) + .build(); + NotificationConfig config = wechatConfigService.getNotificationConfig(); + NotificationParser parser = new NotificationParser(config); + RefundNotification notification = parser.parse(requestParam, RefundNotification.class); + System.out.println("充值退款回调:" + notification); + if (notification.getRefundStatus().equals(Status.SUCCESS)) { + String refundNo = notification.getOutRefundNo(); + String orderNo = refundNo != null && refundNo.startsWith("R") ? refundNo.substring(1) : refundNo; + BalanceChargeLog chargeLog = balanceChargeLogService.lambdaQuery() + .eq(BalanceChargeLog::getOrderNo, orderNo) + .last("limit 1") + .one(); + if (chargeLog != null && chargeLog.getIsPaid() != null && chargeLog.getIsPaid() == 1) { + doRefund(chargeLog); + } + } + return success(); + } catch (Exception e) { + System.out.println("充值退款回调错误:" + e.getMessage()); + return fail(e.getMessage()); + } + } + + protected void doCharge(BalanceChargeLog chargeLog, String transactionId) { + System.out.println("here doCharge"); + LocalDateTime now = LocalDateTime.now(); + chargeLog.setIsPaid(1); + chargeLog.setPaidNumber(transactionId); + chargeLog.setUpdateTime(now); + balanceChargeLogService.updateById(chargeLog); + + User user = userService.getByIdInner(chargeLog.getUserId()); + if (user == null) { + return; + } + BigDecimal currentBalance = user.getBalance() == null ? BigDecimal.ZERO : user.getBalance(); + BigDecimal latestBalance = currentBalance.add(chargeLog.getAmount()); + user.setBalance(latestBalance); + userService.updateInner(user); + + UserBalanceLog userBalanceLog = new UserBalanceLog(); + userBalanceLog.setUserId(user.getUserId()); + userBalanceLog.setScene(0); + userBalanceLog.setMoney(chargeLog.getAmount()); + userBalanceLog.setBalance(latestBalance); + userBalanceLog.setRemark("余额充值"); + userBalanceLog.setComments("充值订单号:" + chargeLog.getOrderNo()); + userBalanceLog.setStatus(0); + userBalanceLog.setDeleted(0); + userBalanceLog.setTenantId(chargeLog.getTenantId()); + userBalanceLog.setCreateTime(now); + userBalanceLog.setUpdateTime(now); + userBalanceLogService.save(userBalanceLog); + } + + protected void doRefund(BalanceChargeLog chargeLog) { + LocalDateTime now = LocalDateTime.now(); + User user = userService.getByIdInner(chargeLog.getUserId()); + if (user == null) { + return; + } + BigDecimal currentBalance = user.getBalance() == null ? BigDecimal.ZERO : user.getBalance(); + BigDecimal latestBalance = currentBalance.subtract(chargeLog.getAmount()); + user.setBalance(latestBalance); + userService.updateInner(user); + + chargeLog.setIsPaid(2); + chargeLog.setUpdateTime(now); + balanceChargeLogService.updateById(chargeLog); + + UserBalanceLog userBalanceLog = new UserBalanceLog(); + userBalanceLog.setUserId(user.getUserId()); + userBalanceLog.setScene(2); + userBalanceLog.setMoney(chargeLog.getAmount().negate()); + userBalanceLog.setBalance(latestBalance); + userBalanceLog.setRemark("余额充值退款"); + userBalanceLog.setComments("充值退款订单号:R" + chargeLog.getOrderNo()); + userBalanceLog.setStatus(0); + userBalanceLog.setDeleted(0); + userBalanceLog.setTenantId(chargeLog.getTenantId()); + userBalanceLog.setCreateTime(now); + userBalanceLog.setUpdateTime(now); + userBalanceLogService.save(userBalanceLog); + } +} diff --git a/src/main/java/com/gxwebsoft/shop/controller/RechargeOrderController.java b/src/main/java/com/gxwebsoft/shop/controller/RechargeOrderController.java deleted file mode 100644 index c850190..0000000 --- a/src/main/java/com/gxwebsoft/shop/controller/RechargeOrderController.java +++ /dev/null @@ -1,187 +0,0 @@ -package com.gxwebsoft.shop.controller; - -import cn.hutool.core.util.IdUtil; -import com.gxwebsoft.common.core.web.BaseController; -import com.gxwebsoft.common.system.service.UserService; -import com.gxwebsoft.shop.entity.UserBalanceLog; -import com.gxwebsoft.shop.service.RechargeOrderService; -import com.gxwebsoft.shop.entity.RechargeOrder; -import com.gxwebsoft.shop.param.RechargeOrderParam; -import com.gxwebsoft.common.core.web.ApiResult; -import com.gxwebsoft.common.core.web.PageResult; -import com.gxwebsoft.common.core.web.PageParam; -import com.gxwebsoft.common.core.web.BatchParam; -import com.gxwebsoft.common.core.annotation.OperationLog; -import com.gxwebsoft.common.system.entity.User; -import com.gxwebsoft.shop.service.UserBalanceLogService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import static com.gxwebsoft.common.core.constants.BalanceConstants.BALANCE_ADMIN; - -/** - * 会员充值订单表控制器 - * - * @author 科技小王子 - * @since 2024-07-26 23:18:48 - */ -@Api(tags = "会员充值订单表管理") -@RestController -@RequestMapping("/api/shop/recharge-order") -public class RechargeOrderController extends BaseController { - @Resource - private RechargeOrderService rechargeOrderService; - @Resource - private UserService userService; - @Resource - private UserBalanceLogService userBalanceLogService; - - @PreAuthorize("hasAuthority('shop:rechargeOrder:save')") - @ApiOperation("会员充值") - @PostMapping("/recharge") - @Transactional(rollbackFor = {Exception.class}) - public ApiResult recharge(@RequestBody RechargeOrder rechargeOrder) { - // 充值 - User user = userService.getById(rechargeOrder.getUserId()); - BigDecimal balance = user.getBalance().add(rechargeOrder.getPayPrice()); - user.setBalance(balance); - userService.updateById(user); - // 保存充值记录 - rechargeOrder.setOrderNo(Long.toString(IdUtil.getSnowflakeNextId())); - rechargeOrder.setBalance(balance); - if (rechargeOrderService.save(rechargeOrder)) { - // 记录余额明细 - UserBalanceLog userBalanceLog = new UserBalanceLog(); - userBalanceLog.setUserId(rechargeOrder.getUserId()); - userBalanceLog.setScene(BALANCE_ADMIN); - userBalanceLog.setMoney(rechargeOrder.getPayPrice()); - userBalanceLog.setBalance(balance); - userBalanceLog.setComments("操作人:" + getLoginUser().getNickname()); - userBalanceLog.setRemark(rechargeOrder.getComments()); - userBalanceLog.setMerchantCode(rechargeOrder.getMerchantCode()); - userBalanceLogService.save(userBalanceLog); - return success("充值成功", user); - } - return fail("充值失败"); - } - - @PreAuthorize("hasAuthority('shop:rechargeOrder:list')") - @ApiOperation("分页查询会员充值订单表") - @GetMapping("/page") - public ApiResult> page(RechargeOrderParam param) { - // 使用关联查询 - return success(rechargeOrderService.pageRel(param)); - } - - @PreAuthorize("hasAuthority('shop:rechargeOrder:list')") - @ApiOperation("查询全部会员充值订单表") - @GetMapping() - public ApiResult> list(RechargeOrderParam param) { - // 使用关联查询 - return success(rechargeOrderService.listRel(param)); - } - - @PreAuthorize("hasAuthority('shop:rechargeOrder:list')") - @ApiOperation("根据id查询会员充值订单表") - @GetMapping("/{id}") - public ApiResult get(@PathVariable("id") Integer id) { - // 使用关联查询 - return success(rechargeOrderService.getByIdRel(id)); - } - - @ApiOperation("添加会员充值订单表") - @PostMapping() - public ApiResult save(@RequestBody RechargeOrder rechargeOrder) { - // 记录当前登录用户id - User loginUser = getLoginUser(); - if (loginUser != null) { - rechargeOrder.setUserId(loginUser.getUserId()); - } - if (rechargeOrderService.save(rechargeOrder)) { - return success("添加成功"); - } - return fail("添加失败"); - } - - @ApiOperation("修改会员充值订单表") - @PutMapping() - public ApiResult update(@RequestBody RechargeOrder rechargeOrder) { - if (rechargeOrderService.updateById(rechargeOrder)) { - return success("修改成功"); - } - return fail("修改失败"); - } - - @ApiOperation("删除会员充值订单表") - @DeleteMapping("/{id}") - public ApiResult remove(@PathVariable("id") Integer id) { - if (rechargeOrderService.removeById(id)) { - return success("删除成功"); - } - return fail("删除失败"); - } - - @PreAuthorize("hasAuthority('shop:rechargeOrder:save')") - @ApiOperation("批量充值") - @PostMapping("/batchRecharge") - @Transactional(rollbackFor = {Exception.class}) - public ApiResult batchRecharge(@RequestBody List list) { - if (rechargeOrderService.saveBatch(list)) { - String nickname = getLoginUser().getNickname(); - ArrayList users = new ArrayList<>(list.size()); - ArrayList logs = new ArrayList<>(list.size()); - - list.forEach(d -> { - User user = userService.getByIdRel(d.getUserId()); - BigDecimal balance = user.getBalance().add(d.getPayPrice()); - user.setBalance(balance); - users.add(user); - UserBalanceLog userBalanceLog = new UserBalanceLog(); - userBalanceLog.setUserId(d.getUserId()); - userBalanceLog.setScene(BALANCE_ADMIN); - userBalanceLog.setMoney(d.getPayPrice()); - userBalanceLog.setBalance(balance); - userBalanceLog.setComments("操作人:" + nickname); - userBalanceLog.setRemark(d.getComments()); - userBalanceLog.setMerchantCode(d.getMerchantCode()); - logs.add(userBalanceLog); - }); - - // 批量充值 - userService.updateBatchById(users); - // 记录余额明细 - userBalanceLogService.saveBatch(logs); - return success("充值成功"); - } - return fail("充值失败"); - } - - @PreAuthorize("hasAuthority('shop:rechargeOrder:update')") - @ApiOperation("批量修改会员充值订单表") - @PutMapping("/batch") - public ApiResult removeBatch(@RequestBody BatchParam batchParam) { - if (batchParam.update(rechargeOrderService, "order_id")) { - return success("修改成功"); - } - return fail("修改失败"); - } - - @PreAuthorize("hasAuthority('shop:rechargeOrder:remove')") - @ApiOperation("批量删除会员充值订单表") - @DeleteMapping("/batch") - public ApiResult removeBatch(@RequestBody List ids) { - if (rechargeOrderService.removeByIds(ids)) { - return success("删除成功"); - } - return fail("删除失败"); - } - -} diff --git a/src/main/java/com/gxwebsoft/shop/controller/UserBalanceLogController.java b/src/main/java/com/gxwebsoft/shop/controller/UserBalanceLogController.java index cb6bcd3..8e2093e 100644 --- a/src/main/java/com/gxwebsoft/shop/controller/UserBalanceLogController.java +++ b/src/main/java/com/gxwebsoft/shop/controller/UserBalanceLogController.java @@ -10,19 +10,23 @@ import com.gxwebsoft.common.core.web.PageParam; import com.gxwebsoft.common.core.web.BatchParam; import com.gxwebsoft.common.core.annotation.OperationLog; import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.common.system.service.UserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.math.BigDecimal; import java.util.List; +import static com.gxwebsoft.common.core.constants.BalanceConstants.BALANCE_ADMIN; + /** * 用户余额变动明细表控制器 * - * @author 科技小王子 - * @since 2024-05-29 15:57:44 + * @author LX + * @since 2026-05-07 14:57:22 */ @Api(tags = "用户余额变动明细表管理") @RestController @@ -30,6 +34,8 @@ import java.util.List; public class UserBalanceLogController extends BaseController { @Resource private UserBalanceLogService userBalanceLogService; + @Resource + private UserService userService; @ApiOperation("分页查询用户余额变动明细表") @GetMapping("/page") @@ -56,10 +62,33 @@ public class UserBalanceLogController extends BaseController { @ApiOperation("添加用户余额变动明细表") @PostMapping() public ApiResult save(@RequestBody UserBalanceLog userBalanceLog) { - // 记录当前登录用户id + if (userBalanceLog.getUserId() == null) { + return fail("用户ID不能为空"); + } + if (userBalanceLog.getMoney() == null || userBalanceLog.getMoney().compareTo(BigDecimal.ZERO) <= 0) { + return fail("充值金额必须大于0"); + } + User user = userService.addBalanceInner(userBalanceLog.getUserId(), userBalanceLog.getMoney()); + if (user == null) { + return fail("用户不存在"); + } User loginUser = getLoginUser(); - if (loginUser != null) { - userBalanceLog.setUserId(loginUser.getUserId()); + if (userBalanceLog.getScene() == null) { + userBalanceLog.setScene(BALANCE_ADMIN); + } + userBalanceLog.setBalance(user.getBalance()); + if (loginUser != null && userBalanceLog.getAdminId() == null) { + userBalanceLog.setAdminId(loginUser.getUserId()); + } + if ((userBalanceLog.getComments() == null || userBalanceLog.getComments().trim().isEmpty()) + && userBalanceLog.getRemark() != null) { + userBalanceLog.setComments(userBalanceLog.getRemark()); + } + if (userBalanceLog.getStatus() == null) { + userBalanceLog.setStatus(0); + } + if (userBalanceLog.getDeleted() == null) { + userBalanceLog.setDeleted(0); } if (userBalanceLogService.save(userBalanceLog)) { return success("添加成功"); diff --git a/src/main/java/com/gxwebsoft/shop/entity/BalanceChargeLog.java b/src/main/java/com/gxwebsoft/shop/entity/BalanceChargeLog.java new file mode 100644 index 0000000..8c22561 --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/entity/BalanceChargeLog.java @@ -0,0 +1,57 @@ +package com.gxwebsoft.shop.entity; + +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableField; +import java.time.LocalDateTime; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * + * + * @author LX + * @since 2026-05-07 14:57:22 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "BalanceChargeLog对象", description = "") +@TableName("shop_balance_charge_log") +public class BalanceChargeLog implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + private BigDecimal amount; + + private String orderNo; + + @ApiModelProperty(value = "0未支付,1已支付,2已退款") + private Integer isPaid; + + private String paidNumber; + + private Integer userId; + + @ApiModelProperty(value = "手机号") + @TableField(exist = false) + private String phone; + + @ApiModelProperty(value = "商城ID") + private Integer tenantId; + + @ApiModelProperty(value = "创建时间") + private LocalDateTime createTime; + + @ApiModelProperty(value = "修改时间") + private LocalDateTime updateTime; + + private String remark; + +} diff --git a/src/main/java/com/gxwebsoft/shop/entity/RechargeOrder.java b/src/main/java/com/gxwebsoft/shop/entity/RechargeOrder.java deleted file mode 100644 index fde3d45..0000000 --- a/src/main/java/com/gxwebsoft/shop/entity/RechargeOrder.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.gxwebsoft.shop.entity; - -import java.math.BigDecimal; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import java.time.LocalDateTime; -import com.baomidou.mybatisplus.annotation.TableLogic; -import java.io.Serializable; -import java.util.Date; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 会员充值订单表 - * - * @author 科技小王子 - * @since 2024-07-26 23:18:48 - */ -@Data -@EqualsAndHashCode(callSuper = false) -@ApiModel(value = "RechargeOrder对象", description = "会员充值订单表") -@TableName("shop_recharge_order") -public class RechargeOrder implements Serializable { - private static final long serialVersionUID = 1L; - - @ApiModelProperty(value = "订单ID") - @TableId(value = "order_id", type = IdType.AUTO) - private Integer orderId; - - @ApiModelProperty(value = "订单号") - private String orderNo; - - @ApiModelProperty(value = "用户ID") - private Integer userId; - - @ApiModelProperty(value = "充值方式(10自定义金额 20套餐充值)") - private Integer rechargeType; - - @ApiModelProperty(value = "机构id") - private Integer organizationId; - - @ApiModelProperty(value = "充值套餐ID") - private Integer planId; - - @ApiModelProperty(value = "用户支付金额") - private BigDecimal payPrice; - - @ApiModelProperty(value = "赠送金额") - private BigDecimal giftMoney; - - @ApiModelProperty(value = "实际到账金额") - private BigDecimal actualMoney; - - @ApiModelProperty(value = "用户可用余额") - private BigDecimal balance; - - @ApiModelProperty(value = "支付方式(微信/支付宝)") - private String payMethod; - - @ApiModelProperty(value = "支付状态(10待支付 20已支付)") - private Integer payStatus; - - @ApiModelProperty(value = "付款时间") - private Integer payTime; - - @ApiModelProperty(value = "第三方交易记录ID") - private Integer tradeId; - - @ApiModelProperty(value = "来源客户端 (APP、H5、小程序等)") - private String platform; - - @ApiModelProperty(value = "所属门店ID") - private Integer shopId; - - @ApiModelProperty(value = "排序(数字越小越靠前)") - private Integer sortNumber; - - @ApiModelProperty(value = "备注") - private String comments; - - @ApiModelProperty(value = "状态, 0正常, 1冻结") - private Integer status; - - @ApiModelProperty(value = "是否删除, 0否, 1是") - @TableLogic - private Integer deleted; - - @ApiModelProperty(value = "商户编码") - private String merchantCode; - - @ApiModelProperty(value = "租户id") - private Integer tenantId; - - @ApiModelProperty(value = "注册时间") - private Date createTime; - - @ApiModelProperty(value = "修改时间") - private Date updateTime; - -} diff --git a/src/main/java/com/gxwebsoft/shop/entity/UserBalanceLog.java b/src/main/java/com/gxwebsoft/shop/entity/UserBalanceLog.java index 181bdfa..7079933 100644 --- a/src/main/java/com/gxwebsoft/shop/entity/UserBalanceLog.java +++ b/src/main/java/com/gxwebsoft/shop/entity/UserBalanceLog.java @@ -7,8 +7,6 @@ import com.baomidou.mybatisplus.annotation.TableId; import java.time.LocalDateTime; import com.baomidou.mybatisplus.annotation.TableLogic; import java.io.Serializable; -import java.util.Date; - import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -17,8 +15,8 @@ import lombok.EqualsAndHashCode; /** * 用户余额变动明细表 * - * @author 科技小王子 - * @since 2024-05-29 15:57:44 + * @author LX + * @since 2026-05-07 14:57:22 */ @Data @EqualsAndHashCode(callSuper = false) @@ -34,7 +32,7 @@ public class UserBalanceLog implements Serializable { @ApiModelProperty(value = "用户ID") private Integer userId; - @ApiModelProperty(value = "余额变动场景(10用户充值 20用户消费 30管理员操作 40订单退款)") + @ApiModelProperty(value = "余额变动场景(0 用户充值 1用户消费 2管理员操作 3订单退款)") private Integer scene; @ApiModelProperty(value = "变动金额") @@ -46,15 +44,11 @@ public class UserBalanceLog implements Serializable { @ApiModelProperty(value = "管理员备注") private String remark; + private Integer orderId; + @ApiModelProperty(value = "操作人ID") private Integer adminId; - @ApiModelProperty(value = "订单编号") - private String orderNo; - - @ApiModelProperty(value = "商户ID") - private Integer merchantId; - @ApiModelProperty(value = "排序(数字越小越靠前)") private Integer sortNumber; @@ -68,16 +62,13 @@ public class UserBalanceLog implements Serializable { @TableLogic private Integer deleted; - @ApiModelProperty(value = "商户编码") - private String merchantCode; - @ApiModelProperty(value = "租户id") private Integer tenantId; @ApiModelProperty(value = "注册时间") - private Date createTime; + private LocalDateTime createTime; @ApiModelProperty(value = "修改时间") - private Date updateTime; + private LocalDateTime updateTime; } diff --git a/src/main/java/com/gxwebsoft/shop/mapper/BalanceChargeLogMapper.java b/src/main/java/com/gxwebsoft/shop/mapper/BalanceChargeLogMapper.java new file mode 100644 index 0000000..e8d0640 --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/mapper/BalanceChargeLogMapper.java @@ -0,0 +1,37 @@ +package com.gxwebsoft.shop.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.gxwebsoft.shop.entity.BalanceChargeLog; +import com.gxwebsoft.shop.param.BalanceChargeLogParam; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * Mapper + * + * @author LX + * @since 2026-05-07 14:57:22 + */ +public interface BalanceChargeLogMapper extends BaseMapper { + + /** + * 分页查询 + * + * @param page 分页对象 + * @param param 查询参数 + * @return List + */ + List selectPageRel(@Param("page") IPage page, + @Param("param") BalanceChargeLogParam param); + + /** + * 查询全部 + * + * @param param 查询参数 + * @return List + */ + List selectListRel(@Param("param") BalanceChargeLogParam param); + +} diff --git a/src/main/java/com/gxwebsoft/shop/mapper/RechargeOrderMapper.java b/src/main/java/com/gxwebsoft/shop/mapper/RechargeOrderMapper.java deleted file mode 100644 index c27a982..0000000 --- a/src/main/java/com/gxwebsoft/shop/mapper/RechargeOrderMapper.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gxwebsoft.shop.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.gxwebsoft.shop.entity.RechargeOrder; -import com.gxwebsoft.shop.param.RechargeOrderParam; -import org.apache.ibatis.annotations.Param; - -import java.util.List; - -/** - * 会员充值订单表Mapper - * - * @author 科技小王子 - * @since 2024-07-26 23:18:48 - */ -public interface RechargeOrderMapper extends BaseMapper { - - /** - * 分页查询 - * - * @param page 分页对象 - * @param param 查询参数 - * @return List - */ - List selectPageRel(@Param("page") IPage page, - @Param("param") RechargeOrderParam param); - - /** - * 查询全部 - * - * @param param 查询参数 - * @return List - */ - List selectListRel(@Param("param") RechargeOrderParam param); - -} diff --git a/src/main/java/com/gxwebsoft/shop/mapper/UserBalanceLogMapper.java b/src/main/java/com/gxwebsoft/shop/mapper/UserBalanceLogMapper.java index bba2131..bf8c9af 100644 --- a/src/main/java/com/gxwebsoft/shop/mapper/UserBalanceLogMapper.java +++ b/src/main/java/com/gxwebsoft/shop/mapper/UserBalanceLogMapper.java @@ -11,8 +11,8 @@ import java.util.List; /** * 用户余额变动明细表Mapper * - * @author 科技小王子 - * @since 2024-05-29 15:57:44 + * @author LX + * @since 2026-05-07 14:57:22 */ public interface UserBalanceLogMapper extends BaseMapper { diff --git a/src/main/java/com/gxwebsoft/shop/mapper/xml/BalanceChargeLogMapper.xml b/src/main/java/com/gxwebsoft/shop/mapper/xml/BalanceChargeLogMapper.xml new file mode 100644 index 0000000..40d5b61 --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/mapper/xml/BalanceChargeLogMapper.xml @@ -0,0 +1,60 @@ + + + + + + + SELECT a.* + FROM shop_balance_charge_log a + + + AND a.id = #{param.id} + + + AND a.amount = #{param.amount} + + + AND a.order_no LIKE CONCAT('%', #{param.orderNo}, '%') + + + AND a.is_paid = #{param.isPaid} + + + AND a.paid_number LIKE CONCAT('%', #{param.paidNumber}, '%') + + + AND a.user_id = #{param.userId} + + + AND a.user_id IN + + #{userId} + + + + AND a.create_time >= #{param.createTimeStart} + + + AND a.create_time <= #{param.createTimeEnd} + + + AND a.remark LIKE CONCAT('%', #{param.remark}, '%') + + + AND (a.order_no LIKE CONCAT('%', #{param.keywords}, '%') + ) + + + + + + + + + + + diff --git a/src/main/java/com/gxwebsoft/shop/mapper/xml/RechargeOrderMapper.xml b/src/main/java/com/gxwebsoft/shop/mapper/xml/RechargeOrderMapper.xml deleted file mode 100644 index 24c88e3..0000000 --- a/src/main/java/com/gxwebsoft/shop/mapper/xml/RechargeOrderMapper.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - SELECT a.* - FROM shop_recharge_order a - - - AND a.order_id = #{param.orderId} - - - AND a.order_no LIKE CONCAT('%', #{param.orderNo}, '%') - - - AND a.user_id = #{param.userId} - - - AND a.recharge_type = #{param.rechargeType} - - - AND a.organization_id = #{param.organizationId} - - - AND a.plan_id = #{param.planId} - - - AND a.pay_price = #{param.payPrice} - - - AND a.gift_money = #{param.giftMoney} - - - AND a.actual_money = #{param.actualMoney} - - - AND a.balance = #{param.balance} - - - AND a.pay_method LIKE CONCAT('%', #{param.payMethod}, '%') - - - AND a.pay_status = #{param.payStatus} - - - AND a.pay_time = #{param.payTime} - - - AND a.trade_id = #{param.tradeId} - - - AND a.platform LIKE CONCAT('%', #{param.platform}, '%') - - - AND a.shop_id = #{param.shopId} - - - AND a.sort_number = #{param.sortNumber} - - - AND a.comments LIKE CONCAT('%', #{param.comments}, '%') - - - AND a.status = #{param.status} - - - AND a.deleted = #{param.deleted} - - - AND a.deleted = 0 - - - AND a.merchant_code LIKE CONCAT('%', #{param.merchantCode}, '%') - - - AND a.create_time >= #{param.createTimeStart} - - - AND a.create_time <= #{param.createTimeEnd} - - - AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') - ) - - - - - - - - - - - diff --git a/src/main/java/com/gxwebsoft/shop/mapper/xml/UserBalanceLogMapper.xml b/src/main/java/com/gxwebsoft/shop/mapper/xml/UserBalanceLogMapper.xml index 3bd2500..9901a82 100644 --- a/src/main/java/com/gxwebsoft/shop/mapper/xml/UserBalanceLogMapper.xml +++ b/src/main/java/com/gxwebsoft/shop/mapper/xml/UserBalanceLogMapper.xml @@ -25,6 +25,12 @@ AND a.remark LIKE CONCAT('%', #{param.remark}, '%') + + AND a.order_id = #{param.orderId} + + + AND a.admin_id = #{param.adminId} + AND a.sort_number = #{param.sortNumber} @@ -40,9 +46,6 @@ AND a.deleted = 0 - - AND a.merchant_code LIKE CONCAT('%', #{param.merchantCode}, '%') - AND a.create_time >= #{param.createTimeStart} diff --git a/src/main/java/com/gxwebsoft/shop/param/BalanceChargeLogParam.java b/src/main/java/com/gxwebsoft/shop/param/BalanceChargeLogParam.java new file mode 100644 index 0000000..75ec5cf --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/param/BalanceChargeLogParam.java @@ -0,0 +1,49 @@ +package com.gxwebsoft.shop.param; + +import java.math.BigDecimal; +import java.util.List; +import com.gxwebsoft.common.core.annotation.QueryField; +import com.gxwebsoft.common.core.annotation.QueryType; +import com.gxwebsoft.common.core.web.BaseParam; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 查询参数 + * + * @author LX + * @since 2026-05-07 14:57:22 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@JsonInclude(JsonInclude.Include.NON_NULL) +@ApiModel(value = "BalanceChargeLogParam对象", description = "查询参数") +public class BalanceChargeLogParam extends BaseParam { + private static final long serialVersionUID = 1L; + + @QueryField(type = QueryType.EQ) + private Integer id; + + @QueryField(type = QueryType.EQ) + private BigDecimal amount; + + private String orderNo; + + @QueryField(type = QueryType.EQ) + private Integer isPaid; + + private String paidNumber; + + @QueryField(type = QueryType.EQ) + private Integer userId; + + private String phone; + + private List userIds; + + private String remark; + +} diff --git a/src/main/java/com/gxwebsoft/shop/param/RechargeOrderParam.java b/src/main/java/com/gxwebsoft/shop/param/RechargeOrderParam.java deleted file mode 100644 index a16ead4..0000000 --- a/src/main/java/com/gxwebsoft/shop/param/RechargeOrderParam.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.gxwebsoft.shop.param; - -import java.math.BigDecimal; -import com.gxwebsoft.common.core.annotation.QueryField; -import com.gxwebsoft.common.core.annotation.QueryType; -import com.gxwebsoft.common.core.web.BaseParam; -import com.fasterxml.jackson.annotation.JsonInclude; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 会员充值订单表查询参数 - * - * @author 科技小王子 - * @since 2024-07-26 23:18:48 - */ -@Data -@EqualsAndHashCode(callSuper = false) -@JsonInclude(JsonInclude.Include.NON_NULL) -@ApiModel(value = "RechargeOrderParam对象", description = "会员充值订单表查询参数") -public class RechargeOrderParam extends BaseParam { - private static final long serialVersionUID = 1L; - - @ApiModelProperty(value = "订单ID") - @QueryField(type = QueryType.EQ) - private Integer orderId; - - @ApiModelProperty(value = "订单号") - private String orderNo; - - @ApiModelProperty(value = "用户ID") - @QueryField(type = QueryType.EQ) - private Integer userId; - - @ApiModelProperty(value = "充值方式(10自定义金额 20套餐充值)") - @QueryField(type = QueryType.EQ) - private Integer rechargeType; - - @ApiModelProperty(value = "机构id") - @QueryField(type = QueryType.EQ) - private Integer organizationId; - - @ApiModelProperty(value = "充值套餐ID") - @QueryField(type = QueryType.EQ) - private Integer planId; - - @ApiModelProperty(value = "用户支付金额") - @QueryField(type = QueryType.EQ) - private BigDecimal payPrice; - - @ApiModelProperty(value = "赠送金额") - @QueryField(type = QueryType.EQ) - private BigDecimal giftMoney; - - @ApiModelProperty(value = "实际到账金额") - @QueryField(type = QueryType.EQ) - private BigDecimal actualMoney; - - @ApiModelProperty(value = "用户可用余额") - @QueryField(type = QueryType.EQ) - private BigDecimal balance; - - @ApiModelProperty(value = "支付方式(微信/支付宝)") - private String payMethod; - - @ApiModelProperty(value = "支付状态(10待支付 20已支付)") - @QueryField(type = QueryType.EQ) - private Integer payStatus; - - @ApiModelProperty(value = "付款时间") - @QueryField(type = QueryType.EQ) - private Integer payTime; - - @ApiModelProperty(value = "第三方交易记录ID") - @QueryField(type = QueryType.EQ) - private Integer tradeId; - - @ApiModelProperty(value = "来源客户端 (APP、H5、小程序等)") - private String platform; - - @ApiModelProperty(value = "所属门店ID") - @QueryField(type = QueryType.EQ) - private Integer shopId; - - @ApiModelProperty(value = "排序(数字越小越靠前)") - @QueryField(type = QueryType.EQ) - private Integer sortNumber; - - @ApiModelProperty(value = "备注") - private String comments; - - @ApiModelProperty(value = "状态, 0正常, 1冻结") - @QueryField(type = QueryType.EQ) - private Integer status; - - @ApiModelProperty(value = "是否删除, 0否, 1是") - @QueryField(type = QueryType.EQ) - private Integer deleted; - - @ApiModelProperty(value = "商户编码") - private String merchantCode; - -} diff --git a/src/main/java/com/gxwebsoft/shop/param/UserBalanceLogParam.java b/src/main/java/com/gxwebsoft/shop/param/UserBalanceLogParam.java index 22c12ed..c7e3e4f 100644 --- a/src/main/java/com/gxwebsoft/shop/param/UserBalanceLogParam.java +++ b/src/main/java/com/gxwebsoft/shop/param/UserBalanceLogParam.java @@ -13,8 +13,8 @@ import lombok.EqualsAndHashCode; /** * 用户余额变动明细表查询参数 * - * @author 科技小王子 - * @since 2024-05-29 15:57:44 + * @author LX + * @since 2026-05-07 14:57:22 */ @Data @EqualsAndHashCode(callSuper = false) @@ -31,7 +31,7 @@ public class UserBalanceLogParam extends BaseParam { @QueryField(type = QueryType.EQ) private Integer userId; - @ApiModelProperty(value = "余额变动场景(10用户充值 20用户消费 30管理员操作 40订单退款)") + @ApiModelProperty(value = "余额变动场景(0 用户充值 1用户消费 2管理员操作 3订单退款)") @QueryField(type = QueryType.EQ) private Integer scene; @@ -46,6 +46,13 @@ public class UserBalanceLogParam extends BaseParam { @ApiModelProperty(value = "管理员备注") private String remark; + @QueryField(type = QueryType.EQ) + private Integer orderId; + + @ApiModelProperty(value = "操作人ID") + @QueryField(type = QueryType.EQ) + private Integer adminId; + @ApiModelProperty(value = "排序(数字越小越靠前)") @QueryField(type = QueryType.EQ) private Integer sortNumber; @@ -61,7 +68,4 @@ public class UserBalanceLogParam extends BaseParam { @QueryField(type = QueryType.EQ) private Integer deleted; - @ApiModelProperty(value = "商户编码") - private String merchantCode; - } diff --git a/src/main/java/com/gxwebsoft/shop/service/BalanceChargeLogService.java b/src/main/java/com/gxwebsoft/shop/service/BalanceChargeLogService.java new file mode 100644 index 0000000..967409b --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/service/BalanceChargeLogService.java @@ -0,0 +1,42 @@ +package com.gxwebsoft.shop.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.shop.entity.BalanceChargeLog; +import com.gxwebsoft.shop.param.BalanceChargeLogParam; + +import java.util.List; + +/** + * Service + * + * @author LX + * @since 2026-05-07 14:57:22 + */ +public interface BalanceChargeLogService extends IService { + + /** + * 分页关联查询 + * + * @param param 查询参数 + * @return PageResult + */ + PageResult pageRel(BalanceChargeLogParam param); + + /** + * 关联查询全部 + * + * @param param 查询参数 + * @return List + */ + List listRel(BalanceChargeLogParam param); + + /** + * 根据id查询 + * + * @param id + * @return BalanceChargeLog + */ + BalanceChargeLog getByIdRel(Integer id); + +} diff --git a/src/main/java/com/gxwebsoft/shop/service/RechargeOrderService.java b/src/main/java/com/gxwebsoft/shop/service/RechargeOrderService.java deleted file mode 100644 index 94a7dc2..0000000 --- a/src/main/java/com/gxwebsoft/shop/service/RechargeOrderService.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.gxwebsoft.shop.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.gxwebsoft.common.core.web.PageResult; -import com.gxwebsoft.shop.entity.RechargeOrder; -import com.gxwebsoft.shop.param.RechargeOrderParam; - -import java.util.List; - -/** - * 会员充值订单表Service - * - * @author 科技小王子 - * @since 2024-07-26 23:18:48 - */ -public interface RechargeOrderService extends IService { - - /** - * 分页关联查询 - * - * @param param 查询参数 - * @return PageResult - */ - PageResult pageRel(RechargeOrderParam param); - - /** - * 关联查询全部 - * - * @param param 查询参数 - * @return List - */ - List listRel(RechargeOrderParam param); - - /** - * 根据id查询 - * - * @param orderId 订单ID - * @return RechargeOrder - */ - RechargeOrder getByIdRel(Integer orderId); - -} diff --git a/src/main/java/com/gxwebsoft/shop/service/UserBalanceLogService.java b/src/main/java/com/gxwebsoft/shop/service/UserBalanceLogService.java index 69adec2..cbcb37c 100644 --- a/src/main/java/com/gxwebsoft/shop/service/UserBalanceLogService.java +++ b/src/main/java/com/gxwebsoft/shop/service/UserBalanceLogService.java @@ -10,8 +10,8 @@ import java.util.List; /** * 用户余额变动明细表Service * - * @author 科技小王子 - * @since 2024-05-29 15:57:44 + * @author LX + * @since 2026-05-07 14:57:22 */ public interface UserBalanceLogService extends IService { diff --git a/src/main/java/com/gxwebsoft/shop/service/impl/BalanceChargeLogServiceImpl.java b/src/main/java/com/gxwebsoft/shop/service/impl/BalanceChargeLogServiceImpl.java new file mode 100644 index 0000000..59c8d90 --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/service/impl/BalanceChargeLogServiceImpl.java @@ -0,0 +1,94 @@ +package com.gxwebsoft.shop.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.common.system.service.UserService; +import com.gxwebsoft.shop.mapper.BalanceChargeLogMapper; +import com.gxwebsoft.shop.service.BalanceChargeLogService; +import com.gxwebsoft.shop.entity.BalanceChargeLog; +import com.gxwebsoft.shop.param.BalanceChargeLogParam; +import com.gxwebsoft.common.core.web.PageParam; +import com.gxwebsoft.common.core.web.PageResult; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import javax.annotation.Resource; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * Service实现 + * + * @author LX + * @since 2026-05-07 14:57:22 + */ +@Service +public class BalanceChargeLogServiceImpl extends ServiceImpl implements BalanceChargeLogService { + @Resource + private UserService userService; + + @Override + public PageResult pageRel(BalanceChargeLogParam param) { + if (!setUserIdsByPhone(param)) { + return new PageResult<>(Collections.emptyList(), 0L); + } + PageParam page = new PageParam<>(param); + page.setDefaultOrder("create_time desc"); + List list = baseMapper.selectPageRel(page, param); + setUserPhones(list); + return new PageResult<>(list, page.getTotal()); + } + + @Override + public List listRel(BalanceChargeLogParam param) { + if (!setUserIdsByPhone(param)) { + return Collections.emptyList(); + } + List list = baseMapper.selectListRel(param); + setUserPhones(list); + // 排序 + PageParam page = new PageParam<>(); + page.setDefaultOrder("create_time desc"); + return page.sortRecords(list); + } + + @Override + public BalanceChargeLog getByIdRel(Integer id) { + BalanceChargeLogParam param = new BalanceChargeLogParam(); + param.setId(id); + return param.getOne(baseMapper.selectListRel(param)); + } + + private boolean setUserIdsByPhone(BalanceChargeLogParam param) { + if (param.getPhone() == null || param.getPhone().trim().isEmpty()) { + return true; + } + List users = userService.listByPhoneInner(param.getPhone().trim()); + if (CollectionUtils.isEmpty(users)) { + return false; + } + param.setUserIds(users.stream().map(User::getUserId).collect(Collectors.toList())); + return true; + } + + private void setUserPhones(List list) { + if (CollectionUtils.isEmpty(list)) { + return; + } + List userIds = list.stream() + .map(BalanceChargeLog::getUserId) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(userIds)) { + return; + } + Map userPhoneMap = userService.listByIdsInner(userIds).stream() + .collect(Collectors.toMap(User::getUserId, User::getPhone, (a, b) -> a)); + list.forEach(d -> d.setPhone(userPhoneMap.get(d.getUserId()))); + } + +} diff --git a/src/main/java/com/gxwebsoft/shop/service/impl/RechargeOrderServiceImpl.java b/src/main/java/com/gxwebsoft/shop/service/impl/RechargeOrderServiceImpl.java deleted file mode 100644 index b7fefd3..0000000 --- a/src/main/java/com/gxwebsoft/shop/service/impl/RechargeOrderServiceImpl.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.gxwebsoft.shop.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.gxwebsoft.shop.mapper.RechargeOrderMapper; -import com.gxwebsoft.shop.service.RechargeOrderService; -import com.gxwebsoft.shop.entity.RechargeOrder; -import com.gxwebsoft.shop.param.RechargeOrderParam; -import com.gxwebsoft.common.core.web.PageParam; -import com.gxwebsoft.common.core.web.PageResult; -import org.springframework.stereotype.Service; - -import java.util.List; - -/** - * 会员充值订单表Service实现 - * - * @author 科技小王子 - * @since 2024-07-26 23:18:48 - */ -@Service -public class RechargeOrderServiceImpl extends ServiceImpl implements RechargeOrderService { - - @Override - public PageResult pageRel(RechargeOrderParam param) { - PageParam page = new PageParam<>(param); - page.setDefaultOrder("sort_number asc, create_time desc"); - List list = baseMapper.selectPageRel(page, param); - return new PageResult<>(list, page.getTotal()); - } - - @Override - public List listRel(RechargeOrderParam param) { - List list = baseMapper.selectListRel(param); - // 排序 - PageParam page = new PageParam<>(); - page.setDefaultOrder("sort_number asc, create_time desc"); - return page.sortRecords(list); - } - - @Override - public RechargeOrder getByIdRel(Integer orderId) { - RechargeOrderParam param = new RechargeOrderParam(); - param.setOrderId(orderId); - return param.getOne(baseMapper.selectListRel(param)); - } - -} diff --git a/src/main/java/com/gxwebsoft/shop/service/impl/UserBalanceLogServiceImpl.java b/src/main/java/com/gxwebsoft/shop/service/impl/UserBalanceLogServiceImpl.java index ec4ecb8..4576d29 100644 --- a/src/main/java/com/gxwebsoft/shop/service/impl/UserBalanceLogServiceImpl.java +++ b/src/main/java/com/gxwebsoft/shop/service/impl/UserBalanceLogServiceImpl.java @@ -14,8 +14,8 @@ import java.util.List; /** * 用户余额变动明细表Service实现 * - * @author 科技小王子 - * @since 2024-05-29 15:57:44 + * @author LX + * @since 2026-05-07 14:57:22 */ @Service public class UserBalanceLogServiceImpl extends ServiceImpl implements UserBalanceLogService { @@ -23,7 +23,7 @@ public class UserBalanceLogServiceImpl extends ServiceImpl pageRel(UserBalanceLogParam param) { PageParam page = new PageParam<>(param); - page.setDefaultOrder("sort_number asc, create_time desc"); + page.setDefaultOrder("create_time desc"); List list = baseMapper.selectPageRel(page, param); return new PageResult<>(list, page.getTotal()); } @@ -33,7 +33,7 @@ public class UserBalanceLogServiceImpl extends ServiceImpl list = baseMapper.selectListRel(param); // 排序 PageParam page = new PageParam<>(); - page.setDefaultOrder("sort_number asc, create_time desc"); + page.setDefaultOrder("create_time desc"); return page.sortRecords(list); } diff --git a/src/main/java/com/gxwebsoft/think/controller/PrinterController.java b/src/main/java/com/gxwebsoft/think/controller/PrinterController.java index 1151d78..0024228 100644 --- a/src/main/java/com/gxwebsoft/think/controller/PrinterController.java +++ b/src/main/java/com/gxwebsoft/think/controller/PrinterController.java @@ -25,6 +25,7 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.math.BigDecimal; import java.util.*; +import java.util.concurrent.TimeUnit; @Api(tags = "打印") @RestController diff --git a/src/main/java/com/gxwebsoft/think/controller/SchedulingController.java b/src/main/java/com/gxwebsoft/think/controller/SchedulingController.java index a89ef69..2b908a3 100644 --- a/src/main/java/com/gxwebsoft/think/controller/SchedulingController.java +++ b/src/main/java/com/gxwebsoft/think/controller/SchedulingController.java @@ -56,7 +56,7 @@ public class SchedulingController extends BaseController { public void task() { String newTime = DateUtil.format(LocalDateTime.now(), "HH:mm"); if ((newTime.equals("21:30") || newTime.equals("21:45")) && redisUtil.get("swimmingCheck") == null) { - redisUtil.set("swimmingCheck", 1, 3L, TimeUnit.HOURS); + redisUtil.set("swimmingCheck", 1, 3L, TimeUnit.MINUTES); // 每天21:30后核销游泳馆订单 List swimmingOrderList = thinkOrderService.list( new LambdaQueryWrapper() @@ -73,139 +73,149 @@ public class SchedulingController extends BaseController { .set(ThinkOrder::getUpdateTime, DateUtil.currentSeconds()) ); } - } else { - // 2分钟取消订单 - List orderList = thinkOrderService.list( - new LambdaUpdateWrapper() - .eq(ThinkOrder::getPayStatus, 2) - .eq(ThinkOrder::getOrderStatus, 2) - .apply("UNIX_TIMESTAMP() > `create_time` + " + (2 * 60)) + } + // 游泳馆年卡月卡当天使用多次的退掉 +// List swimCardOrderList = thinkOrderService.list( +// new LambdaUpdateWrapper() +// .eq(ThinkOrder::getPayStatus, 1) +// .isNotNull(ThinkOrder::getCid) +// .apply("UNIX_TIMESTAMP() > `create_time` + " + (2 * 60)) +// ); + // 2分钟取消订单 + List orderList = thinkOrderService.list( + new LambdaUpdateWrapper() + .eq(ThinkOrder::getPayStatus, 2) + .eq(ThinkOrder::getOrderStatus, 2) + .apply("UNIX_TIMESTAMP() > `create_time` + " + (2 * 60)) + ); + if (!orderList.isEmpty()) { + List orderInfoList = new ArrayList<>(); + for (ThinkOrder thinkOrder : orderList) { + thinkOrder.setOrderStatus(3); + List orderInfoListTmp = thinkOrderInfoService.listInOrder(thinkOrder.getId()); + orderInfoList.addAll(orderInfoListTmp); + thinkOrder.setUpdateTime(System.currentTimeMillis() / 1000); + } + for (ThinkOrderInfo thinkOrderInfo : orderInfoList) { + thinkOrderInfo.setPayStatus(0); + redisUtil.delete(thinkOrderInfo.getStartTime().toString() + thinkOrderInfo.getFid().toString()); + } + thinkOrderService.updateBatchById(orderList); + thinkOrderInfoService.updateBatchById(orderInfoList); + } + + // 清除占场redis + List cancelOrderList = thinkOrderService.list( + new LambdaUpdateWrapper() + .in(ThinkOrder::getOrderStatus, 3, 4, 5, 6) + .between(ThinkOrder::getCreateTime, DateUtil.beginOfDay(DateUtil.date()).getTime() / 1000, (int) (System.currentTimeMillis() / 1000)) + ); + if (!cancelOrderList.isEmpty()) { + List orderIdList = cancelOrderList.stream().map(ThinkOrder::getId).toList(); + List orderInfoListTmp = thinkOrderInfoService.listByOrderIds(orderIdList); + for (ThinkOrderInfo thinkOrderInfo : orderInfoListTmp) { + redisUtil.delete(thinkOrderInfo.getStartTime().toString() + thinkOrderInfo.getFid().toString()); + } + } + + //每天0点清空人数 + if (DateUtil.format(LocalDateTime.now(), "HH:mm:ss").equals("00:00:00")) { + thinkSiteService.update( + new LambdaUpdateWrapper() + .set(ThinkSite::getDailyNum, 0) ); - if (!orderList.isEmpty()) { - List orderInfoList = new ArrayList<>(); - for (ThinkOrder thinkOrder : orderList) { - thinkOrder.setOrderStatus(3); - List orderInfoListTmp = thinkOrderInfoService.listInOrder(thinkOrder.getId()); - orderInfoList.addAll(orderInfoListTmp); - thinkOrder.setUpdateTime(System.currentTimeMillis() / 1000); - } - for (ThinkOrderInfo thinkOrderInfo : orderInfoList) { - thinkOrderInfo.setPayStatus(0); - redisUtil.delete(thinkOrderInfo.getStartTime().toString() + thinkOrderInfo.getFid().toString()); - } - thinkOrderService.updateBatchById(orderList); - thinkOrderInfoService.updateBatchById(orderInfoList); - } + } - // 清除占场redis - List cancelOrderList = thinkOrderService.list( - new LambdaUpdateWrapper() - .in(ThinkOrder::getOrderStatus, 3, 4, 5, 6) - .between(ThinkOrder::getCreateTime, DateUtil.beginOfDay(DateUtil.date()).getTime() / 1000, (int) (System.currentTimeMillis() / 1000)) + // 核销订单 + List otherOrderList = thinkOrderService.list( + new LambdaUpdateWrapper() + .ne(ThinkOrder::getSid, 37) + .eq(ThinkOrder::getPayStatus, 1) + .eq(ThinkOrder::getOrderStatus, 2) + ); + for (ThinkOrder thinkOrder : otherOrderList) { + List orderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId()); + ThinkOrderInfo lastOne = orderInfoList.get(orderInfoList.size() - 1); + if ((int) (System.currentTimeMillis() / 1000) > lastOne.getStartTime()) { + thinkOrder.setOrderStatus(1); + thinkOrder.setCheckBy(1); + thinkOrder.setCheckTime(new Date()); + thinkOrderService.updateById(thinkOrder); + } + } + + // 查询开票 + String invoiceFlag = redisUtil.get("invoiceFlag"); + if (invoiceFlag == null) { + redisUtil.set("invoiceFlag", "1", 3L, TimeUnit.MINUTES); + ThinkInvoice thinkInvoice = thinkInvoiceService.getOne( + new LambdaUpdateWrapper() + .gt(ThinkInvoice::getId, 5481) + .eq(ThinkInvoice::getIsOpen, 2) + .eq(ThinkInvoice::getType, 2) + .eq(ThinkInvoice::getDeleted, 0) + .groupBy(ThinkInvoice::getIncoiveNum) + .last("order by RAND() limit 1") ); - if (!cancelOrderList.isEmpty()) { - List orderIdList = cancelOrderList.stream().map(ThinkOrder::getId).toList(); - List orderInfoListTmp = thinkOrderInfoService.listByOrderIds(orderIdList); - for (ThinkOrderInfo thinkOrderInfo : orderInfoListTmp) { - redisUtil.delete(thinkOrderInfo.getStartTime().toString() + thinkOrderInfo.getFid().toString()); - } - } - - //每天0点清空人数 - if (DateUtil.format(LocalDateTime.now(), "HH:mm:ss").equals("00:00:00")) { - thinkSiteService.update( - new LambdaUpdateWrapper() - .set(ThinkSite::getDailyNum, 0) - ); - } - - // 核销订单 - List otherOrderList = thinkOrderService.list( - new LambdaUpdateWrapper() - .ne(ThinkOrder::getSid, 37) - .eq(ThinkOrder::getPayStatus, 1) - .eq(ThinkOrder::getOrderStatus, 2) - ); - for (ThinkOrder thinkOrder : otherOrderList) { - List orderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId()); - ThinkOrderInfo lastOne = orderInfoList.get(orderInfoList.size() - 1); - if ((int) (System.currentTimeMillis() / 1000) > (lastOne.getStartTime() + 1800)) { - thinkOrder.setOrderStatus(1); - thinkOrder.setCheckBy(1); - thinkOrder.setCheckTime(new Date()); - thinkOrderService.updateById(thinkOrder); - } - } - - // 查询开票 - String invoiceFlag = redisUtil.get("invoiceFlag"); - if (invoiceFlag == null) { - redisUtil.set("invoiceFlag", "1", 3L, TimeUnit.MINUTES); - ThinkInvoice thinkInvoice = thinkInvoiceService.getOne( - new LambdaUpdateWrapper() - .gt(ThinkInvoice::getId, 5481) - .eq(ThinkInvoice::getIsOpen, 2) - .eq(ThinkInvoice::getType, 2) - .eq(ThinkInvoice::getDeleted, 0) - .groupBy(ThinkInvoice::getIncoiveNum) - .last("order by RAND() limit 1") - ); // for (ThinkInvoice thinkInvoice : invoiceList) { - if (thinkInvoice != null) - thinkInvoiceController.getRes(thinkInvoice.getId()); + if (thinkInvoice != null) + thinkInvoiceController.getRes(thinkInvoice.getId()); // } - } + } - // 每2分钟检测撞场 - if (redisUtil.get("sameOrderCheck") == null) { - redisUtil.set("sameOrderCheck", 1, 2L, TimeUnit.MINUTES); - List checkOrderList = thinkOrderService.list( - new LambdaQueryWrapper() - .ne(ThinkOrder::getSid, 37) - .in(ThinkOrder::getOrderStatus, 1, 2) - .eq(ThinkOrder::getPayStatus, 1) - .gt(ThinkOrder::getCreateTime, 1748707200) - .orderByAsc(ThinkOrder::getCreateTime) - ); - Set refundOrderIdList = new HashSet<>(); - if (!checkOrderList.isEmpty()) { - for (ThinkOrder thinkOrder : checkOrderList) { - List thinkOrderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId()); + // 每2分钟检测撞场 + if (redisUtil.get("sameOrderCheck") == null) { + redisUtil.set("sameOrderCheck", 1, 2L, TimeUnit.MINUTES); + List checkOrderList = thinkOrderService.list( + new LambdaQueryWrapper() + .ne(ThinkOrder::getSid, 37) + .in(ThinkOrder::getOrderStatus, 1, 2) + .eq(ThinkOrder::getPayStatus, 1) + .gt(ThinkOrder::getCreateTime, 1748707200) + .orderByAsc(ThinkOrder::getCreateTime) + ); + Set refundOrderIdList = new HashSet<>(); + Map bookedSlotOrderMap = new HashMap<>(); + if (!checkOrderList.isEmpty()) { + checkOrderList.sort(Comparator + .comparing(ThinkOrder::getCreateTime) + .thenComparing(ThinkOrder::getId)); + for (ThinkOrder thinkOrder : checkOrderList) { + if (refundOrderIdList.contains(thinkOrder.getId())) { + continue; + } + List thinkOrderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId()); + boolean hasConflict = false; + for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) { + String slotKey = thinkOrderInfo.getSid() + "_" + thinkOrderInfo.getFid() + "_" + thinkOrderInfo.getStartTime(); + Integer bookedOrderId = bookedSlotOrderMap.get(slotKey); + if (bookedOrderId != null && !bookedOrderId.equals(thinkOrder.getId())) { + refundOrderIdList.add(thinkOrder.getId()); + hasConflict = true; + break; + } + } + if (!hasConflict) { for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) { - List checkThinkOrderInfoList = thinkOrderInfoService.list( - new LambdaQueryWrapper() - .ne(ThinkOrderInfo::getOid, thinkOrder.getId()) - .eq(ThinkOrderInfo::getFid, thinkOrderInfo.getFid()) - .eq(ThinkOrderInfo::getSid, thinkOrderInfo.getSid()) - .eq(ThinkOrderInfo::getStartTime, thinkOrderInfo.getStartTime()) - ); - if (!checkThinkOrderInfoList.isEmpty()) { - for (ThinkOrderInfo checkThinkOrderInfo : checkThinkOrderInfoList) { - ThinkOrder sameOrder = thinkOrderService.getOne( - new LambdaQueryWrapper() - .eq(ThinkOrder::getId, checkThinkOrderInfo.getOid()) - ); - if (sameOrder.getPayStatus().equals(1) && (sameOrder.getOrderStatus().equals(1) || sameOrder.getOrderStatus().equals(2))) { - refundOrderIdList.add(sameOrder.getId()); - } - } - } + String slotKey = thinkOrderInfo.getSid() + "_" + thinkOrderInfo.getFid() + "_" + thinkOrderInfo.getStartTime(); + bookedSlotOrderMap.putIfAbsent(slotKey, thinkOrder.getId()); } } } - if (!refundOrderIdList.isEmpty()) { - List doCancelOrderList = thinkOrderService.listByIds(refundOrderIdList.stream().toList()); - for (ThinkOrder refundOrder : doCancelOrderList) { - System.out.println("撞场订单: " + refundOrder.getOrderNum()); - thinkOrderService.cancelOrder(refundOrder, true, 2); - refundOrder.setOrderStatus(6); - refundOrder.setRefundTime((int) (System.currentTimeMillis() / 1000)); - thinkOrderService.updateById(refundOrder); - } + } + if (!refundOrderIdList.isEmpty()) { + List doCancelOrderList = thinkOrderService.listByIds(refundOrderIdList.stream().toList()); + for (ThinkOrder refundOrder : doCancelOrderList) { + System.out.println("撞场订单: " + refundOrder.getOrderNum()); + thinkOrderService.cancelOrder(refundOrder, true, 2); + refundOrder.setOrderStatus(6); + refundOrder.setRefundTime((int) (System.currentTimeMillis() / 1000)); + thinkOrderService.updateById(refundOrder); } } } + } } diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkCardController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkCardController.java index c2b739f..b9eabbf 100644 --- a/src/main/java/com/gxwebsoft/think/controller/ThinkCardController.java +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkCardController.java @@ -266,6 +266,7 @@ public class ThinkCardController extends BaseController { thinkLog.setLogType(0); thinkLog.setOperateType(4); } + thinkCard.setUpdateTime(DateUtil.currentSeconds()); if (thinkCardService.updateById(thinkCard)) { thinkVipCardsBillsService.setCardUid(thinkCard.getId(), thinkCard.getUid()); if (thinkLog != null) { @@ -281,6 +282,29 @@ public class ThinkCardController extends BaseController { return fail("修改失败"); } + /** 管理端单独修改卡片剩余金额或剩余次数,避免覆盖其他字段。 */ + @ApiOperation("修改剩余金额/次数") + @PreAuthorize("hasAuthority('think:thinkCard:changeRemain')") + @PutMapping("/remaining") + public ApiResult updateRemaining(@RequestBody ThinkCard thinkCard) { + if (thinkCard.getId() == null) return fail("卡片ID不能为空"); + if (thinkCard.getNum() == null && thinkCard.getRemainingMoney() == null) { + return fail("剩余金额或剩余次数不能为空"); + } + if (thinkCard.getNum() != null && thinkCard.getNum() < 0) return fail("剩余次数不能为负数"); + if (thinkCard.getRemainingMoney() != null && thinkCard.getRemainingMoney().compareTo(BigDecimal.ZERO) < 0) { + return fail("剩余金额不能为负数"); + } + ThinkCard current = thinkCardService.getById(thinkCard.getId()); + if (current == null) return fail("卡片不存在"); + ThinkCard update = new ThinkCard(); + update.setId(thinkCard.getId()); + update.setNum(thinkCard.getNum()); + update.setRemainingMoney(thinkCard.getRemainingMoney()); + update.setUpdateTime(DateUtil.currentSeconds()); + return thinkCardService.updateById(update) ? success("修改成功") : fail("修改失败"); + } + @ApiOperation("删除") @DeleteMapping("/{id}") public ApiResult remove(@PathVariable("id") Integer id) { diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkCardLogController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkCardLogController.java index 1dc44bf..f21b410 100644 --- a/src/main/java/com/gxwebsoft/think/controller/ThinkCardLogController.java +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkCardLogController.java @@ -84,7 +84,7 @@ public class ThinkCardLogController extends BaseController { thinkCardLog.setAid(getLoginUserId()); if (thinkCardLogService.save(thinkCardLog)) { ThinkCard thinkCard = thinkCardService.getByCode(thinkCardLog.getCode()); - ThinkVip thinkVip = thinkVipService.getById(thinkCard.getVid()); + ThinkVip thinkVip = thinkVipService.getById(thinkCardLog.getVid()); if (thinkCard.getExpireTime() < DateUtil.currentSeconds()) { thinkCard.setExpireTime((DateUtil.currentSeconds()) + (thinkVip.getTerm() * 86400 * 365) + (thinkVip.getMonth() * 86400 * 30) + (thinkVip.getDay() * 86400)); @@ -122,6 +122,19 @@ public class ThinkCardLogController extends BaseController { } // thinkCard.setNum(thinkCard.getCount() + thinkCard.getCount()); } + thinkCard.setVid(thinkVip.getId()); + thinkCard.setSid(thinkVip.getSid()); + thinkCard.setName(thinkVip.getName()); + thinkCard.setDesc(thinkVip.getDesc()); + thinkCard.setInfo(thinkVip.getInfo()); + thinkCard.setDiscount(thinkVip.getDiscount()); + thinkCard.setTerm(thinkVip.getTerm()); + thinkCard.setMonth(thinkVip.getMonth()); + thinkCard.setType(thinkVip.getType()); + thinkCard.setCardType(thinkVip.getCardType()); + thinkCard.setVipType(thinkVip.getVipType()); + thinkCard.setPrice(thinkVip.getPrice()); + thinkCard.setNumber(thinkCard.getNumber() + 1); thinkCard.setCount(thinkCard.getCount() + thinkCardLog.getCount()); thinkCardService.updateById(thinkCard); diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkGateControlController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkGateControlController.java new file mode 100644 index 0000000..426521f --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkGateControlController.java @@ -0,0 +1,127 @@ +package com.gxwebsoft.think.controller; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.think.service.ThinkGateControlService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 闸机控制 + * + * @author WebSoft + * @since 2026-03-11 + */ +@Api(tags = "闸机控制") +@RestController +@RequestMapping("/api/think/gate-control") +public class ThinkGateControlController extends BaseController { + @Resource + private ThinkGateControlService thinkGateControlService; + + @ApiOperation("获取权限组集合") + @GetMapping("/accLevelList") + public ApiResult accLevelList(@RequestParam("pageNo") Integer pageNo, + @RequestParam("pageSize") Integer pageSize) { + try { + return success(thinkGateControlService.accLevelList(pageNo, pageSize)); + } catch (Exception e) { + return fail("请求权限组集合失败: " + e.getMessage()); + } + } + + @ApiOperation("同步人员权限") + @PostMapping("/syncPerson") + public ApiResult syncPerson(@RequestParam("pin") String pin, + @RequestParam("levelIds") String levelIds) { + try { + return success(thinkGateControlService.syncPerson(pin, levelIds)); + } catch (Exception e) { + return fail("同步人员权限失败: " + e.getMessage()); + } + } + + @ApiOperation("检测人脸是否可用") + @PostMapping("/detectFace") + public ApiResult detectFace(@RequestBody Map params) { + try { + return success(thinkGateControlService.detectFace(params)); + } catch (Exception e) { + return fail("检测人脸失败: " + e.getMessage()); + } + } + + @ApiOperation("通过pin批量删除人员") + @PostMapping("/deleteByPins") + public ApiResult deleteByPins(@RequestParam("pins") String pins) { + try { + return success(thinkGateControlService.deleteByPins(pins)); + } catch (Exception e) { + return fail("批量删除人员失败: " + e.getMessage()); + } + } + + @ApiOperation("批量新增/编辑人员信息") + @PostMapping("/addPersons") + public ApiResult addPersons(@RequestBody List> personList) { + try { + thinkGateControlService.addPersons(personList); + return success(); + } catch (Exception e) { + return fail("批量新增/编辑人员信息失败: " + e.getMessage()); + } + } + + @ApiOperation("批量新增/编辑人员信息-测试") + @PostMapping("/addPersons/test") + public ApiResult addPersonsTest(@RequestBody Map params) { + String pin = params.get("pin") == null ? null : params.get("pin").toString(); + String personPhoto = params.get("personPhoto") == null ? null : params.get("personPhoto").toString(); + if (StrUtil.isBlank(pin)) { + return fail("pin不能为空"); + } + if (StrUtil.isBlank(personPhoto)) { + return fail("personPhoto不能为空"); + } + String name = params.get("name") == null ? null : params.get("name").toString(); + String mobilePhone = params.get("mobilePhone") == null ? null : params.get("mobilePhone").toString(); + String day = DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd"); + String accStartTime = params.get("accStartTime") == null ? day + " 05:00:00" : params.get("accStartTime").toString(); + String accEndTime = params.get("accEndTime") == null ? day + " 22:00:00" : params.get("accEndTime").toString(); + String accLevelIds = params.get("accLevelIds") == null ? thinkGateControlService.getLevelId() : params.get("accLevelIds").toString(); + + Map person = new HashMap<>(); + person.put("pin", pin); + person.put("mobilePhone", mobilePhone); + person.put("name", StrUtil.blankToDefault(name, pin)); + person.put("personPhoto", personPhoto); + person.put("accEndTime", accEndTime); + person.put("accLevelIds", accLevelIds); + person.put("accStartTime", accStartTime); + + List> personList = new ArrayList<>(); + personList.add(person); + String res = thinkGateControlService.addPersons(personList); + return success(res); + } + + @ApiOperation("获取门禁事件记录") + @PostMapping("/transactionList") + public ApiResult transactionList() { + try { + return success(thinkGateControlService.transactionList()); + } catch (Exception e) { + return fail("获取门禁事件记录信息失败: " + e.getMessage()); + } + } +} diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkInvoiceController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkInvoiceController.java index dd2e51e..4d5db06 100644 --- a/src/main/java/com/gxwebsoft/think/controller/ThinkInvoiceController.java +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkInvoiceController.java @@ -14,6 +14,7 @@ import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.core.web.BatchParam; import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.think.entity.*; import com.gxwebsoft.think.param.ThinkInvoiceParam; import com.gxwebsoft.think.service.*; @@ -74,6 +75,7 @@ public class ThinkInvoiceController extends BaseController { private final String url = "https://sdk.nuonuo.com/open/v1/services"; private final String clerk = "刘绍仪"; private final String extensionNumber = "6192"; + private final Long invoiceDebounceSeconds = 10L; // private final String clerk = "赵裕璐"; // private final String extensionNumber = "7426"; @@ -111,10 +113,20 @@ public class ThinkInvoiceController extends BaseController { @ApiOperation("添加") @PostMapping() public ApiResult save(@RequestBody ThinkInvoice thinkInvoice) { + User loginUser = getLoginUser(); if (thinkInvoice.getCode() == null || thinkInvoice.getCode().isEmpty()) return fail("请输入税号"); + if (thinkInvoice.getPhone() == null || thinkInvoice.getPhone().isEmpty()) + return fail("请输入手机号"); + if (thinkInvoice.getName() == null || thinkInvoice.getName().isEmpty()) + return fail("请输入名称"); + if (thinkInvoice.getPhone().length() > 11) + return fail("手机号长度不能超过11位"); + + if (isDebounced(buildInvoiceDebounceKey("save", thinkInvoice, loginUser))) return fail("请勿频繁操作"); + thinkInvoice.setIncoiveNum(""); - thinkInvoice.setUid(getLoginUser().getUid()); + thinkInvoice.setUid(loginUser.getUid()); // thinkInvoice.setCode(thinkInvoice.getIncoiveCode()); thinkInvoice.setIncoiveNum(RandomUtil.randomString(20)); if (!thinkInvoice.getIsOpen().equals(1)) thinkInvoice.setIsOpen(2); @@ -193,6 +205,8 @@ public class ThinkInvoiceController extends BaseController { if (thinkInvoice.getCode() == null) return fail("请输入税号"); String taxCode = thinkInvoice.getCode().replaceAll(" ", ""); thinkInvoice.setCode(taxCode); + if (isDebounced(buildInvoiceDebounceKey("doInvoiceByList", thinkInvoice, getLoginUser()))) + return fail("请勿频繁操作"); List thinkInvoiceList = new ArrayList<>(); List thinkOrderList = thinkOrderService.listByIds(thinkInvoice.getOrderIdList()); List thinkOrderInfoList = thinkOrderInfoService.listByOrderIds(thinkInvoice.getOrderIdList()); @@ -209,7 +223,7 @@ public class ThinkInvoiceController extends BaseController { if (thinkOrder != null) { ThinkInvoice thinkInvoice1 = new ThinkInvoice(); thinkInvoice1.setIncoiveNum(invoiceNum); - thinkInvoice1.setIncoiveCode("91450100737617400R"); + thinkInvoice1.setIncoiveCode(taxnum); thinkInvoice1.setOid(orderId); thinkInvoice1.setOrderNum(thinkOrder.getOrderNum()); thinkInvoice1.setUid(thinkOrder.getUid()); @@ -259,9 +273,9 @@ public class ThinkInvoiceController extends BaseController { order.setInvoiceType("1"); order.setInvoiceLine(thinkInvoice.getInvoicetype().equals(1) ? "pc" : "bs"); final NuoNuoGoods goods = new NuoNuoGoods(); - goods.setGoodsName("*经营租赁*场地费"); + goods.setGoodsName("*生产生活服务*场地费"); - goods.setGoodsCode("3040502029902"); + goods.setGoodsCode("3040502029902000000"); // goods.setPrice(thinkInvoice.getPrice().toString()); goods.setNum(thinkSite.getSize().toString()); goods.setWithTaxFlag("0"); @@ -295,6 +309,8 @@ public class ThinkInvoiceController extends BaseController { order.setRealPropertyRentInfo(nuoNuoRealPropertyRentInfo); order.setSpecificFactor("6"); order.setExtensionNumber(extensionNumber); + if (thinkInvoice.getRemark() != null) + order.setRemark(thinkInvoice.getRemark()); nuoNuo.setOrder(order); @@ -334,6 +350,8 @@ public class ThinkInvoiceController extends BaseController { String code = thinkInvoice.getCode().replaceAll(" ", ""); thinkInvoice.setCode(code); } + if (isDebounced(buildInvoiceDebounceKey("doInvoice", thinkInvoice, getLoginUser()))) + return fail("请勿频繁操作"); thinkInvoice.setStatus(1); if (thinkInvoice.getId() != null) thinkInvoiceService.updateById(thinkInvoice); else { @@ -342,7 +360,7 @@ public class ThinkInvoiceController extends BaseController { if (thinkInvoice.getItype() == null) return fail("非法请求"); ThinkInvoice check = thinkInvoiceService.getByOidNType(thinkInvoice.getOid(), thinkInvoice.getItype()); if (check != null) return fail("该订单已开过发票"); - thinkInvoice.setIncoiveCode("91450100737617400R"); + thinkInvoice.setIncoiveCode(taxnum); thinkInvoice.setCreateTime(System.currentTimeMillis() / 1000); if (thinkInvoice.getCode() == null) thinkInvoice.setCode(""); if (thinkInvoice.getIncoiveNum() == null) thinkInvoice.setIncoiveNum(""); @@ -387,6 +405,8 @@ public class ThinkInvoiceController extends BaseController { String method = "nuonuo.OpeMplatform.queryInvoiceResult";//API方法名 String token = getInvoiceToken(); HashMap map = new HashMap<>(); +// if (!thinkInvoice.getOrderNum().isEmpty()) map.put("orderNos", thinkInvoice.getOrderNum()); +// else map.put("serialNos", thinkInvoice.getIncoiveNum()); if (!thinkInvoice.getIncoiveNum().isEmpty()) map.put("serialNos", thinkInvoice.getIncoiveNum()); else map.put("orderNos", thinkInvoice.getOrderNum()); String content = JSONUtil.toJSONString(map);//API私有请求参数 @@ -421,7 +441,7 @@ public class ThinkInvoiceController extends BaseController { } return body; } else if (code.equals("E9500")) { - newInvoice(thinkInvoice); +// newInvoice(thinkInvoice); } return result; } @@ -469,7 +489,7 @@ public class ThinkInvoiceController extends BaseController { order.setInvoiceLine(thinkInvoice.getInvoicetype().equals(1) ? "pc" : "bs"); final NuoNuoGoods goods = new NuoNuoGoods(); if (thinkInvoice.getItype().equals(1)) { - goods.setGoodsName("*经营租赁*场地费"); + goods.setGoodsName("*生产生活服务*场地费"); } else { goods.setGoodsName("*预付卡销售*预付卡"); } @@ -497,7 +517,7 @@ public class ThinkInvoiceController extends BaseController { goods.setTax(tax.toString()); goods.setTaxIncludedAmount(thinkInvoice.getPrice().toString()); goods.setTaxExcludedAmount(thinkInvoice.getPrice().subtract(tax).toString()); - goods.setGoodsCode("3040502029902"); + goods.setGoodsCode("3040502029902000000"); NuoNuoRealPropertyRentInfo nuoNuoRealPropertyRentInfo = new NuoNuoRealPropertyRentInfo(); goods.setNum(thinkSite.getSize().toString()); nuoNuoRealPropertyRentInfo.setRealPropertyAddress(thinkSite.getProvince() + thinkSite.getCity() + thinkSite.getRegion()); @@ -522,6 +542,8 @@ public class ThinkInvoiceController extends BaseController { } order.setInvoiceDetail(goods); order.setExtensionNumber(extensionNumber); // 13807717477 + if (thinkInvoice.getRemark() != null) + order.setRemark(thinkInvoice.getRemark()); nuoNuo.setOrder(order); @@ -534,6 +556,7 @@ public class ThinkInvoiceController extends BaseController { final JSONObject jsonObject = JSONObject.parseObject(json); final String code = jsonObject.getString("code"); final String result = jsonObject.getString("result"); + System.out.println("invoice post data = " + content); System.out.println("invoice jsonObject = " + jsonObject); if (code.equals("E0000")) { final JSONObject resNo = JSONObject.parseObject(result); @@ -562,6 +585,49 @@ public class ThinkInvoiceController extends BaseController { return ""; } + private boolean isDebounced(String key) { + return !redisUtil.setIfAbsent( + key, + String.valueOf(DateUtil.currentSeconds()), + invoiceDebounceSeconds, + TimeUnit.SECONDS + ); + } + + private String buildInvoiceDebounceKey(String action, ThinkInvoice thinkInvoice, User loginUser) { + StringBuilder key = new StringBuilder("think:invoice:debounce:") + .append(action) + .append(":") + .append(getInvoiceDebounceUserKey(thinkInvoice, loginUser)); + if ("doInvoiceByList".equals(action)) { + key.append(":orders:").append(getOrderIdsKey(thinkInvoice.getOrderIdList())); + } else { + key.append(":id:").append(nullToEmpty(thinkInvoice.getId())) + .append(":oid:").append(nullToEmpty(thinkInvoice.getOid())) + .append(":itype:").append(nullToEmpty(thinkInvoice.getItype())) + .append(":orderNum:").append(nullToEmpty(thinkInvoice.getOrderNum())); + } + key.append(":code:").append(nullToEmpty(thinkInvoice.getCode())) + .append(":phone:").append(nullToEmpty(thinkInvoice.getPhone())) + .append(":price:").append(nullToEmpty(thinkInvoice.getPrice())); + return key.toString(); + } + + private String getInvoiceDebounceUserKey(ThinkInvoice thinkInvoice, User loginUser) { + if (loginUser != null && loginUser.getUid() != null) return loginUser.getUid().toString(); + if (thinkInvoice.getUid() != null) return thinkInvoice.getUid().toString(); + return "anonymous"; + } + + private String getOrderIdsKey(List orderIdList) { + if (orderIdList == null || orderIdList.isEmpty()) return ""; + return orderIdList.stream().sorted().map(String::valueOf).collect(Collectors.joining(",")); + } + + private String nullToEmpty(Object value) { + return value == null ? "" : value.toString(); + } + private String getInvoiceToken() { String tokenInRedis = redisUtil.get("invoiceToken"); if (StrUtil.isNotBlank(tokenInRedis)) { diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkMachineOpenLogController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkMachineOpenLogController.java index da94895..3626eac 100644 --- a/src/main/java/com/gxwebsoft/think/controller/ThinkMachineOpenLogController.java +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkMachineOpenLogController.java @@ -72,6 +72,7 @@ public class ThinkMachineOpenLogController extends BaseController { ThinkMachineOpenLog openLog = thinkMachineOpenLogService.getByOrderId(thinkOrder.getId()); if (openLog == null) { thinkMachineOpenLog.setOrderId(thinkOrder.getId()); +// thinkMachineOpenLog.setQrCode(thinkOrder.getQrcode()); thinkMachineOpenLogService.save(thinkMachineOpenLog); } } diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkOrderController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkOrderController.java index 5d904ce..252f1d2 100644 --- a/src/main/java/com/gxwebsoft/think/controller/ThinkOrderController.java +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkOrderController.java @@ -10,6 +10,9 @@ import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.github.yulichang.query.MPJQueryWrapper; +import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.gxwebsoft.common.core.config.ConfigProperties; import com.gxwebsoft.common.core.security.JwtUtil; import com.gxwebsoft.common.core.utils.RedisUtil; @@ -19,10 +22,14 @@ import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.core.web.BatchParam; import com.gxwebsoft.common.system.entity.FileRecord; import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.common.system.service.UserService; +import com.gxwebsoft.shop.entity.UserBalanceLog; +import com.gxwebsoft.shop.service.UserBalanceLogService; import com.gxwebsoft.think.entity.*; import com.gxwebsoft.think.param.ThinkOrderParam; import com.gxwebsoft.think.param.ThinkVipParam; import com.gxwebsoft.think.service.*; +import com.gxwebsoft.think.task.ThinkFaceAccessTask; import com.wechat.pay.java.core.notification.NotificationConfig; import com.wechat.pay.java.core.notification.NotificationParser; import com.wechat.pay.java.core.notification.RequestParam; @@ -94,6 +101,20 @@ public class ThinkOrderController extends BaseController { private ThinkOrderOffCheckService thinkOrderOffCheckService; @Resource private ThinkCardBalanceService thinkCardBalanceService; + @Resource + private ThinkUsersService thinkUsersService; + @Resource + private ThinkUserInAccessService thinkUserInAccessService; + @Resource + private ThinkGateControlService thinkGateControlService; + @Resource + private ThinkTrainingInstitutionService thinkTrainingInstitutionService; + @Resource + private ThinkUsersBlackService thinkUsersBlackService; + @Resource + private UserService userService; + @Resource + private UserBalanceLogService userBalanceLogService; @Autowired private RedisUtil redisUtil; @@ -180,200 +201,245 @@ public class ThinkOrderController extends BaseController { } public void updatePay(ThinkOrder order, String transactionId, Integer payAmount) { - order.setPayStatus(1); - order.setWechatOrder(transactionId); -// order.setPayPrice(new BigDecimal(NumberUtil.decimalFormat("0.00", transaction.getAmount().getPayerTotal() * 0.01))); - order.setPrice(new BigDecimal(NumberUtil.decimalFormat("0.00", payAmount * 0.01))); - order.setPayTime((int) DateUtil.currentSeconds()); - order.setQrcode("qrcode/" + LocalDateTimeUtil.format(LocalDateTime.now(), "yyyyMMdd") + "/" + IdUtil.getSnowflake().nextIdStr() + ".png"); - thinkOrderService.updateById(order); - // 更新订单商品的支付状态 - int num = 0; - List orderInfoList = thinkOrderInfoService.listInOrder(order.getId()); -// if (order.getType().equals(0)) { - if (!orderInfoList.isEmpty()) { - for (ThinkOrderInfo thinkOrderInfo : orderInfoList) { - thinkOrderInfo.setPayStatus(1); - num += thinkOrderInfo.getAdultNum() + thinkOrderInfo.getChildrenNum(); - } - thinkOrderInfoService.updateBatchById(orderInfoList); - } -// } - // 游泳馆限制人数 - if (order.getSid() != null && order.getSid().equals(37)) { - ThinkSite thinkSite = thinkSiteService.getById(order.getSid()); - thinkSite.setDailyNum(thinkSite.getDailyNum() + 1); - thinkSiteService.updateById(thinkSite); - } - - // 使用记录 - boolean saveBill = false; - ThinkVipCardsBills thinkVipCardsBills = new ThinkVipCardsBills(); - thinkVipCardsBills.setOid(order.getId()); - thinkVipCardsBills.setUid(order.getUid()); - thinkVipCardsBills.setUsed(1); - thinkVipCardsBills.setDate(DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd")); - // VIP卡 - if (order.getVid() != null && !order.getVid().equals(0)) { + boolean doUpdate = true; + if (order.getVid() != null) { ThinkUsersVip usersVip = thinkUsersVipService.getById(order.getVid()); - ThinkCardBalance thinkCardBalance = thinkCardBalanceService.getByVid(usersVip.getId()); - if (thinkCardBalance != null) { - if (!thinkCardBalance.getType().equals(5)) { - BigDecimal payPrice = thinkCardBalance.getReduceEach().multiply(BigDecimal.valueOf(num)); - order.setPayPrice(payPrice); - order.setReducePrice(order.getTotalPrice().subtract(payPrice)); + if (usersVip != null && usersVip.getType() != 5 && usersVip.getType() != 2) { + if (redisUtil.get(usersVip.getId() + "_" + DateUtil.today()) != null) { + doUpdate = false; + order.setOrderStatus(3); + order.setRefundBy(2); thinkOrderService.updateById(order); } - thinkCardBalance.setBalance(thinkCardBalance.getBalance().subtract(order.getPayPrice())); - thinkCardBalanceService.updateById(thinkCardBalance); - } else { - ThinkVip thinkVip = thinkVipService.getById(usersVip.getVid()); - BigDecimal reduceEach = thinkCardBalanceService.getThinkCardBalance(thinkVip); - - ThinkCardBalance thinkCardBalance1 = new ThinkCardBalance(); - thinkCardBalance1.setVid(usersVip.getId()); - thinkCardBalance1.setUid(usersVip.getUid()); - thinkCardBalance1.setBalance(usersVip.getRemainingMoney().subtract(reduceEach)); - thinkCardBalance1.setReduceEach(reduceEach); - thinkCardBalance1.setType(usersVip.getType()); - thinkCardBalance1.setDiscount(usersVip.getDiscount()); - thinkCardBalance1.setVipId(usersVip.getVid()); - thinkCardBalance1.setUpdateTime(DateUtil.currentSeconds()); - thinkCardBalance1.setCreateTime(DateUtil.currentSeconds()); - thinkCardBalanceService.save(thinkCardBalance1); - if (!thinkCardBalance1.getType().equals(5)) { - BigDecimal payPrice = thinkCardBalance1.getReduceEach().multiply(BigDecimal.valueOf(num)); - order.setPayPrice(payPrice); - order.setReducePrice(order.getTotalPrice().subtract(payPrice)); - } - thinkOrderService.updateById(order); } - if (usersVip.getType().equals(5)) { - BigDecimal newBalance = usersVip.getRemainingMoney().subtract(order.getPayPrice()); - usersVip.setRemainingMoney(newBalance); - thinkVipCardsBills.setAmount(order.getPayPrice()); - } else { - int remainNum = usersVip.getNum() - num; - if (remainNum < 0) remainNum = 0; - usersVip.setNum(remainNum); - if (usersVip.getCount() > 0) { - thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(usersVip.getCount()), RoundingMode.HALF_UP)); - } else if (usersVip.getCount() == 0) { - if (usersVip.getMode().equals(0)) { - if (usersVip.getMonth() > 0) { - thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(usersVip.getMonth() * 30), RoundingMode.HALF_UP)); - } else { - if (usersVip.getTerm() > 0) { - thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(usersVip.getTerm() * 365L), RoundingMode.HALF_UP)); - } - } - } else { - long remainDay = DateUtil.betweenDay(new Date(), DateUtil.date(usersVip.getExpireTime() * 1000), false); - if (remainDay > 0) { - thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(remainDay), RoundingMode.HALF_UP)); - } - } - thinkVipCardsBills.setAmount(BigDecimal.ZERO); - } else { - thinkVipCardsBills.setAmount(usersVip.getEachMoney()); - } - } - // 更新会员卡使用时间 - usersVip.setUseTime(DateUtil.parse(DateUtil.today() + " 00:00:00").getTime() / 1000); - thinkUsersVipService.updateById(usersVip); - - thinkVipCardsBills.setVid(order.getVid()); - saveBill = true; } - // IC卡 - ThinkCard card = null; + ThinkCard cardTmp = null; if (order.getCode() != null) { - card = thinkCardService.getByCode(order.getCode()); + cardTmp = thinkCardService.getByCode(order.getCode()); } else { if (order.getCid() != null) { - card = thinkCardService.getById(order.getCid()); + cardTmp = thinkCardService.getById(order.getCid()); } } - if (card != null) { - ThinkVip usersVip = thinkVipService.getById(card.getVid()); - ThinkCardBalance thinkCardBalance = thinkCardBalanceService.getByCid(card.getId()); - if (thinkCardBalance != null) { - if (!thinkCardBalance.getType().equals(5)) { - BigDecimal payPrice = thinkCardBalance.getReduceEach().multiply(BigDecimal.valueOf(num)); - order.setPayPrice(payPrice); - order.setReducePrice(order.getTotalPrice().subtract(payPrice)); + if (cardTmp != null) { + if (cardTmp.getType() != 5 && cardTmp.getType() != 2) { + if (redisUtil.get(cardTmp.getId() + "_" + DateUtil.today()) != null) { + doUpdate = false; + order.setOrderStatus(3); + order.setRefundBy(2); thinkOrderService.updateById(order); } - thinkCardBalance.setBalance(thinkCardBalance.getBalance().subtract(order.getPayPrice())); - thinkCardBalanceService.updateById(thinkCardBalance); - } else { - BigDecimal reduceEach = thinkCardBalanceService.getThinkCardBalance(usersVip); - ThinkCardBalance thinkCardBalance1 = new ThinkCardBalance(); - thinkCardBalance1.setCid(card.getId()); - thinkCardBalance1.setUid(card.getUid()); - thinkCardBalance1.setBalance(card.getRemainingMoney().subtract(reduceEach)); - thinkCardBalance1.setReduceEach(reduceEach); - thinkCardBalance1.setType(usersVip.getType()); - thinkCardBalance1.setDiscount(usersVip.getDiscount()); - thinkCardBalance1.setVipId(card.getVid()); - thinkCardBalance1.setUpdateTime(DateUtil.currentSeconds()); - thinkCardBalance1.setCreateTime(DateUtil.currentSeconds()); - thinkCardBalanceService.save(thinkCardBalance1); - - if (!thinkCardBalance1.getType().equals(5)) { - BigDecimal payPrice = thinkCardBalance1.getReduceEach().multiply(BigDecimal.valueOf(num)); - order.setPayPrice(payPrice); - order.setReducePrice(order.getTotalPrice().subtract(payPrice)); + } + } + if (doUpdate) { + order.setPayStatus(1); + order.setWechatOrder(transactionId); +// order.setPayPrice(new BigDecimal(NumberUtil.decimalFormat("0.00", transaction.getAmount().getPayerTotal() * 0.01))); + order.setPrice(new BigDecimal(NumberUtil.decimalFormat("0.00", payAmount * 0.01))); + order.setPayTime((int) DateUtil.currentSeconds()); + order.setQrcode("qrcode/" + LocalDateTimeUtil.format(LocalDateTime.now(), "yyyyMMdd") + "/" + IdUtil.getSnowflake().nextIdStr() + ".png"); + thinkOrderService.updateById(order); + // 更新订单商品的支付状态 + int num = 0; + List orderInfoList = thinkOrderInfoService.listInOrder(order.getId()); +// if (order.getType().equals(0)) { + if (!orderInfoList.isEmpty()) { + for (ThinkOrderInfo thinkOrderInfo : orderInfoList) { + thinkOrderInfo.setPayStatus(1); + num += thinkOrderInfo.getAdultNum() + thinkOrderInfo.getChildrenNum(); } - thinkOrderService.updateById(order); + thinkOrderInfoService.updateBatchById(orderInfoList); + } +// } + // 游泳馆限制人数 + if (order.getSid() != null && order.getSid().equals(37)) { + ThinkSite thinkSite = thinkSiteService.getById(order.getSid()); + thinkSite.setDailyNum(thinkSite.getDailyNum() + 1); + thinkSiteService.updateById(thinkSite); } - if (card.getType().equals(5) || card.getType().equals(4)) { - BigDecimal newBalance = card.getRemainingMoney().subtract(order.getPayPrice()); - thinkVipCardsBills.setAmount(order.getPayPrice()); - card.setRemainingMoney(newBalance); - } else if (card.getType().equals(2)) { - int remainNum = card.getNum() - num; - if (remainNum < 0) remainNum = 0; - card.setNum(remainNum); -// thinkVipCardsBills.setAmount(card.getPrice().divide(BigDecimal.valueOf(card.getCount()), RoundingMode.HALF_UP)); - if (usersVip.getCount() > 0) { - thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(usersVip.getCount()), RoundingMode.HALF_UP)); - } else if (usersVip.getCount() == 0) { - if (usersVip.getMode().equals(0)) { - if (usersVip.getMonth() > 0) { - thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(usersVip.getMonth() * 30), RoundingMode.HALF_UP)); + // 使用记录 + boolean saveBill = false; + ThinkVipCardsBills thinkVipCardsBills = new ThinkVipCardsBills(); + thinkVipCardsBills.setOid(order.getId()); + thinkVipCardsBills.setUid(order.getUid()); + thinkVipCardsBills.setUsed(1); + thinkVipCardsBills.setDate(DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd")); + // VIP卡 + if (order.getVid() != null && !order.getVid().equals(0)) { + ThinkUsersVip usersVip = thinkUsersVipService.getById(order.getVid()); + redisUtil.set(usersVip.getId() + "_" + DateUtil.today(), 1); + ThinkCardBalance thinkCardBalance = thinkCardBalanceService.getByVid(usersVip.getId()); + if (thinkCardBalance != null) { + if (!thinkCardBalance.getType().equals(5)) { + BigDecimal payPrice = order.getTotalPrice(); + if (thinkCardBalance.getReduceEach().compareTo(BigDecimal.ZERO) > 0) { + payPrice = thinkCardBalance.getReduceEach().multiply(BigDecimal.valueOf(num)); + order.setReducePrice(order.getTotalPrice().subtract(payPrice)); + } + order.setPayPrice(payPrice); + thinkOrderService.updateById(order); + } + thinkCardBalance.setBalance(thinkCardBalance.getBalance().subtract(order.getPayPrice())); + thinkCardBalanceService.updateById(thinkCardBalance); + } else { + ThinkVip thinkVip = thinkVipService.getById(usersVip.getVid()); + BigDecimal reduceEach = thinkCardBalanceService.getThinkCardBalance(thinkVip); + + ThinkCardBalance thinkCardBalance1 = new ThinkCardBalance(); + thinkCardBalance1.setVid(usersVip.getId()); + thinkCardBalance1.setUid(usersVip.getUid()); + thinkCardBalance1.setBalance(usersVip.getRemainingMoney().subtract(reduceEach)); + thinkCardBalance1.setReduceEach(reduceEach); + thinkCardBalance1.setType(usersVip.getType()); + thinkCardBalance1.setDiscount(usersVip.getDiscount()); + thinkCardBalance1.setVipId(usersVip.getVid()); + thinkCardBalance1.setUpdateTime(DateUtil.currentSeconds()); + thinkCardBalance1.setCreateTime(DateUtil.currentSeconds()); + thinkCardBalanceService.save(thinkCardBalance1); + if (!thinkCardBalance1.getType().equals(5)) { + BigDecimal payPrice = order.getTotalPrice(); + if (thinkCardBalance1.getReduceEach().compareTo(BigDecimal.ZERO) > 0) { + payPrice = thinkCardBalance1.getReduceEach().multiply(BigDecimal.valueOf(num)); + order.setReducePrice(order.getTotalPrice().subtract(payPrice)); + } + order.setPayPrice(payPrice); + } + thinkOrderService.updateById(order); + } + if (usersVip.getType().equals(5)) { + BigDecimal newBalance = usersVip.getRemainingMoney().subtract(order.getPayPrice()); + usersVip.setRemainingMoney(newBalance); + thinkVipCardsBills.setAmount(order.getPayPrice()); + } else { + int remainNum = usersVip.getNum() - num; + if (remainNum < 0) remainNum = 0; + usersVip.setNum(remainNum); + if (usersVip.getCount() > 0) { + thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(usersVip.getCount()), RoundingMode.HALF_UP)); + } else if (usersVip.getCount() == 0) { + if (usersVip.getMode().equals(0)) { + if (usersVip.getMonth() > 0) { + thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(usersVip.getMonth() * 30), RoundingMode.HALF_UP)); + } else { + if (usersVip.getTerm() > 0) { + thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(usersVip.getTerm() * 365L), RoundingMode.HALF_UP)); + } + } } else { - if (usersVip.getTerm() > 0) { - thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(usersVip.getTerm() * 365L), RoundingMode.HALF_UP)); + long remainDay = DateUtil.betweenDay(new Date(), DateUtil.date(usersVip.getExpireTime() * 1000), false); + if (remainDay > 0) { + thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(remainDay), RoundingMode.HALF_UP)); } } + thinkVipCardsBills.setAmount(BigDecimal.ZERO); } else { - long remainDay = DateUtil.betweenDay(new Date(), DateUtil.date(card.getExpireTime() * 1000), false); - if (remainDay > 0) { - thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(remainDay), RoundingMode.HALF_UP)); - } + thinkVipCardsBills.setAmount(usersVip.getEachMoney()); } - thinkVipCardsBills.setAmount(BigDecimal.ZERO); - } else { - thinkVipCardsBills.setAmount(usersVip.getEachMoney()); + } + // 更新会员卡使用时间 + usersVip.setUseTime(DateUtil.parse(DateUtil.today() + " 00:00:00").getTime() / 1000); + thinkUsersVipService.updateById(usersVip); + + thinkVipCardsBills.setVid(order.getVid()); + saveBill = true; + } + // IC卡 + ThinkCard card = null; + if (order.getCode() != null) { + card = thinkCardService.getByCode(order.getCode()); + } else { + if (order.getCid() != null) { + card = thinkCardService.getById(order.getCid()); } } - // 更新会员卡使用时间 - card.setUseTime(DateUtil.parse(DateUtil.today() + " 00:00:00").getTime() / 1000); - thinkCardService.updateById(card); + if (card != null) { + redisUtil.set(card.getId() + "_" + DateUtil.today(), 1); + ThinkVip usersVip = thinkVipService.getById(card.getVid()); + ThinkCardBalance thinkCardBalance = thinkCardBalanceService.getByCid(card.getId()); + if (thinkCardBalance != null) { + if (!thinkCardBalance.getType().equals(5)) { + BigDecimal payPrice = order.getTotalPrice(); + if (thinkCardBalance.getReduceEach().compareTo(BigDecimal.ZERO) > 0) { + payPrice = thinkCardBalance.getReduceEach().multiply(BigDecimal.valueOf(num)); + order.setReducePrice(order.getTotalPrice().subtract(payPrice)); + } + order.setPayPrice(payPrice); + thinkOrderService.updateById(order); + } + thinkCardBalance.setBalance(thinkCardBalance.getBalance().subtract(order.getPayPrice())); + thinkCardBalanceService.updateById(thinkCardBalance); + } else { + BigDecimal reduceEach = thinkCardBalanceService.getThinkCardBalance(usersVip); + ThinkCardBalance thinkCardBalance1 = new ThinkCardBalance(); + thinkCardBalance1.setCid(card.getId()); + thinkCardBalance1.setUid(card.getUid()); + thinkCardBalance1.setBalance(card.getRemainingMoney().subtract(reduceEach)); + thinkCardBalance1.setReduceEach(reduceEach); + thinkCardBalance1.setType(usersVip.getType()); + thinkCardBalance1.setDiscount(usersVip.getDiscount()); + thinkCardBalance1.setVipId(card.getVid()); + thinkCardBalance1.setUpdateTime(DateUtil.currentSeconds()); + thinkCardBalance1.setCreateTime(DateUtil.currentSeconds()); + thinkCardBalanceService.save(thinkCardBalance1); - thinkVipCardsBills.setCid(card.getId()); - saveBill = true; + if (!thinkCardBalance1.getType().equals(5)) { + BigDecimal payPrice = order.getTotalPrice(); + if (thinkCardBalance1.getReduceEach().compareTo(BigDecimal.ZERO) > 0) { + payPrice = thinkCardBalance1.getReduceEach().multiply(BigDecimal.valueOf(num)); + order.setReducePrice(order.getTotalPrice().subtract(payPrice)); + } + order.setPayPrice(payPrice); + } + thinkOrderService.updateById(order); + } + + if (card.getType().equals(5) || card.getType().equals(4)) { + BigDecimal newBalance = card.getRemainingMoney().subtract(order.getPayPrice()); + thinkVipCardsBills.setAmount(order.getPayPrice()); + card.setRemainingMoney(newBalance); + } else if (card.getType().equals(2)) { + int remainNum = card.getNum() - num; + if (remainNum < 0) remainNum = 0; + card.setNum(remainNum); +// thinkVipCardsBills.setAmount(card.getPrice().divide(BigDecimal.valueOf(card.getCount()), RoundingMode.HALF_UP)); + if (usersVip.getCount() > 0) { + thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(usersVip.getCount()), RoundingMode.HALF_UP)); + } else if (usersVip.getCount() == 0) { + if (usersVip.getMode().equals(0)) { + if (usersVip.getMonth() > 0) { + thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(usersVip.getMonth() * 30), RoundingMode.HALF_UP)); + } else { + if (usersVip.getTerm() > 0) { + thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(usersVip.getTerm() * 365L), RoundingMode.HALF_UP)); + } + } + } else { + long remainDay = DateUtil.betweenDay(new Date(), DateUtil.date(card.getExpireTime() * 1000), false); + if (remainDay > 0) { + thinkVipCardsBills.setAmount(usersVip.getPrice().divide(BigDecimal.valueOf(remainDay), RoundingMode.HALF_UP)); + } + } + thinkVipCardsBills.setAmount(BigDecimal.ZERO); + } else { + thinkVipCardsBills.setAmount(usersVip.getEachMoney()); + } + } + // 更新会员卡使用时间 + card.setUseTime(DateUtil.parse(DateUtil.today() + " 00:00:00").getTime() / 1000); + thinkCardService.updateById(card); + + thinkVipCardsBills.setCid(card.getId()); + saveBill = true; + } + + if (order.getPayType().equals(12)) { + order.setPayPrice(BigDecimal.ZERO); + order.setReducePrice(order.getTotalPrice()); + thinkOrderService.updateById(order); + } + if (saveBill) thinkVipCardsBillsService.addLog(thinkVipCardsBills); } - - if (order.getPayType().equals(12)) { - order.setPayPrice(BigDecimal.ZERO); - order.setReducePrice(order.getTotalPrice()); - thinkOrderService.updateById(order); - } - - if (saveBill) thinkVipCardsBillsService.addLog(thinkVipCardsBills); } @ApiOperation("设置下单延时") @@ -515,9 +581,12 @@ public class ThinkOrderController extends BaseController { User admin = requestUtil.getByUserId(order.getAid()); if (admin != null) order.setAdminName(admin.getRealName()); } + long timestamp = (int) (System.currentTimeMillis() / 1000); + String qr = id + "_" + timestamp + "_none_forDevice"; String secretKey = redisUtil.get("secretKey_10150"); if (order.getPayStatus().equals(1) && order.getOrderStatus().equals(2)) { byte[] key = null; + if (secretKey == null) { key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded(); redisUtil.set("secretKey_10150", Base64.getEncoder().encodeToString(key)); @@ -525,8 +594,6 @@ public class ThinkOrderController extends BaseController { key = Base64.getDecoder().decode(secretKey); } SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key); - long timestamp = (int) (System.currentTimeMillis() / 1000); - String qr = id + "_" + timestamp + "_none_forDevice"; order.setQrcode(aes.encryptHex(qr)); order.setQrCodeTimestamp(String.valueOf(timestamp)); } @@ -552,6 +619,8 @@ public class ThinkOrderController extends BaseController { } for (int i = 0; i < num; i++) { byte[] key = null; + timestamp = (int) (System.currentTimeMillis() / 1000) + i; + qr = id + "_" + timestamp + "_none_forDevice"; if (secretKey == null) { key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded(); redisUtil.set("secretKey_10150", Base64.getEncoder().encodeToString(key)); @@ -559,8 +628,6 @@ public class ThinkOrderController extends BaseController { key = Base64.getDecoder().decode(secretKey); } SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key); - long timestamp = (int) (System.currentTimeMillis() / 1000) + i; - String qr = id + "_" + timestamp + "_none_forDevice"; qrCodeList.add(aes.encryptHex(qr)); } order.setQrCodeList(qrCodeList); @@ -575,6 +642,12 @@ public class ThinkOrderController extends BaseController { @PostMapping("/check-code") public ApiResult getByQrCode(@RequestBody ThinkOrder order) { if (order.getQrcode() == null || order.getQrcode().isEmpty()) return fail("二维码不能为空"); + if (order.getQrcode().equals("test_adult_uiastiyuqhkwejr12")) { + return success("核销成功", order.getQrcode(), "adult"); + } + if (order.getQrcode().equals("test_child_12uiykjdfbnui23")) { + return success("核销成功", order.getQrcode(), "child"); + } // 使用关联查询 Map res = thinkOrderService.getByQrCode(order.getQrcode()); if (!(Boolean) res.get("res")) return fail(res.get("msg")); @@ -633,143 +706,181 @@ public class ThinkOrderController extends BaseController { public ApiResult save(@RequestBody ThinkOrder thinkOrder, HttpServletRequest request) throws IOException, WxErrorException { User user = getLoginUser(); if (user == null) return fail("请先登录"); + if (user.getUid() == null) return fail("非法请求.code:-4"); + ThinkUsersBlack thinkUsersBlack = thinkUsersBlackService.getOne( + new LambdaQueryWrapper() + .eq(ThinkUsersBlack::getUid, user.getUid()) + .eq(ThinkUsersBlack::getStatus, 1) + .and(wrapper -> wrapper.isNull(ThinkUsersBlack::getExpireTime) + .or() + .gt(ThinkUsersBlack::getExpireTime, LocalDateTime.now())), + false + ); + if (thinkUsersBlack != null) return fail("无法下单,请联系管理员"); if (thinkOrder.getPostTime() == null) return fail("非法请求.code:-1"); if (thinkOrder.getSign() == null) return fail("非法请求.code:-1"); - if (redisUtil.get("think:order:setPause:" + user.getUid()) != null) return fail("请勿频繁操作.code:0"); - redisUtil.delete("think:order:setPause:" + user.getUid()); - if (redisUtil.get(thinkOrder.getSign()) != null) return fail("请勿重复提交"); - String sign = SecureUtil.md5(thinkOrder.getPostTime() + "wxd38cc38c54fa7370" + thinkOrder.getStartTime() + user.getUid()); - if (!Objects.equals(sign, thinkOrder.getSign())) return fail("非法请求.code:-2"); - if (thinkOrder.getThinkOrderInfos().get(0).getDateTime().contains(";") || thinkOrder.getThinkOrderInfos().get(0).getDateTime().contains(")") || thinkOrder.getThinkOrderInfos().get(0).getDateTime().contains("(")) - return fail("非法请求.code:-3"); - redisUtil.set(thinkOrder.getSign(), sign, 1L, TimeUnit.DAYS); - String lastSubmitTime = redisUtil.get(thinkOrder.getSign() + "_lastSubmitTime"); - if (lastSubmitTime != null) { - if (DateUtil.currentSeconds() - Integer.parseInt(lastSubmitTime) < 160) - return fail("请勿频繁操作.code:1"); - } - redisUtil.set(thinkOrder.getSign() + "_lastSubmitTime", DateUtil.currentSeconds(), 1L, TimeUnit.DAYS); - if (!thinkOrder.getSid().equals(37)) { - if (redisUtil.get(user.getUid() + "_lastPayOrderTime") != null) { - if (DateUtil.currentSeconds() - Integer.parseInt(redisUtil.get(user.getUid() + "_lastPayOrderTime")) < 180) + String submitLockKey = "think:order:setPause:" + user.getUid(); + String lastPayOrderTimeKey = user.getUid() + "_lastPayOrderTime"; + + boolean submitLocked = redisUtil.setIfAbsent( + submitLockKey, + String.valueOf(DateUtil.currentSeconds()), + 5L, + TimeUnit.SECONDS + ); + if (!submitLocked) return fail("请勿频繁操作.code:0"); + try { + if (thinkOrder.getSid().equals(37)) { + boolean swimLocked = redisUtil.setIfAbsent( + "think:order:setPauseSwim:" + user.getUid(), + "1", + 5L, + TimeUnit.SECONDS + ); + if (!swimLocked) { + return fail("请勿频繁操作.code:2"); + } + } + if (redisUtil.get(thinkOrder.getSign()) != null) return fail("请勿重复提交"); + String sign = SecureUtil.md5(thinkOrder.getPostTime() + "wxd38cc38c54fa7370" + thinkOrder.getStartTime() + user.getUid()); + if (!Objects.equals(sign, thinkOrder.getSign())) return fail("非法请求.code:-2"); + if (thinkOrder.getThinkOrderInfos().get(0).getDateTime().contains(";") || thinkOrder.getThinkOrderInfos().get(0).getDateTime().contains(")") || thinkOrder.getThinkOrderInfos().get(0).getDateTime().contains("(")) + return fail("非法请求.code:-3"); + redisUtil.set(thinkOrder.getSign(), sign, 1L, TimeUnit.DAYS); + String lastSubmitTime = redisUtil.get(thinkOrder.getSign() + "_lastSubmitTime"); + if (lastSubmitTime != null) { + if (DateUtil.currentSeconds() - Integer.parseInt(lastSubmitTime) < 160) + return fail("请勿频繁操作.code:1"); + } + redisUtil.set(thinkOrder.getSign() + "_lastSubmitTime", DateUtil.currentSeconds(), 1L, TimeUnit.DAYS); + if (!thinkOrder.getSid().equals(37)) { + boolean cooldownLocked = redisUtil.setIfAbsent( + lastPayOrderTimeKey, + String.valueOf(DateUtil.currentSeconds()), + 3L, + TimeUnit.MINUTES + ); + if (!cooldownLocked) { return fail("每次预订需间隔3分钟.code:1"); + } + } else { + redisUtil.set(lastPayOrderTimeKey, DateUtil.currentSeconds(), 3L, TimeUnit.MINUTES); } - } - redisUtil.set(user.getUid() + "_lastPayOrderTime", DateUtil.currentSeconds(), 3L, TimeUnit.MINUTES); - ThinkSite thinkSite = thinkSiteService.getById(thinkOrder.getSid()); - // 8:00 ~ 23:00 不能定 - String today = DateUtil.format(new Date(), "yyyy-MM-dd"); - if (LocalDateTimeUtil.now().isAfter(LocalDateTime.parse(today + " 23:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))) - || LocalDateTimeUtil.now().isBefore(LocalDateTime.parse(today + " 08:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))) { - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("场地预定时间为:8:00-23:00。"); - } - if (thinkOrder.getThinkOrderInfos().isEmpty()) { - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("非法请求.code:5"); - } - if (!thinkOrder.getSid().equals(37)) { - for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { - if (redisUtil.get(info.getStartTime().toString() + info.getFid().toString()) != null) { + ThinkSite thinkSite = thinkSiteService.getById(thinkOrder.getSid()); + if (thinkSite == null || thinkSite.getIsOn().equals(0)) { + return fail("非法请求.code:4"); + } + // 8:00 ~ 23:00 不能定 + String today = DateUtil.format(new Date(), "yyyy-MM-dd"); + if (getLoginUser().getUserId() != 26446) { + if (LocalDateTimeUtil.now().isAfter(LocalDateTime.parse(today + " 23:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))) + || LocalDateTimeUtil.now().isBefore(LocalDateTime.parse(today + " 08:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))) { redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("该场地已被预定.code:0"); - } else { - redisUtil.set(info.getStartTime().toString() + info.getFid().toString(), user.getUid(), 1L, TimeUnit.MINUTES); + return fail("场地预定时间为:8:00-23:00。"); } } - } - if (thinkOrder.getSid().equals(37)) { - // 只能定当天 - if (thinkSite.getDailyMaxNum() != null && thinkSite.getDailyMaxNum() > 0 && thinkSite.getDailyNum() >= thinkSite.getDailyMaxNum()) - return fail("已达上限,无法预定"); - } else { - // 只能定7天 - Date date = DateUtil.parse(thinkOrder.getThinkOrderInfos().get(0).getTimePeriod(), "yyyy-MM-dd"); - long secDiff = DateUtil.between(DateUtil.beginOfDay(DateUtil.date()), date, DateUnit.SECOND); - if (secDiff >= 604800 && !thinkOrder.getSid().equals(28)) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); + if (thinkOrder.getThinkOrderInfos().isEmpty()) { redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("只能预定7天内的场地"); + return fail("非法请求.code:5"); } - // 用户限制订单,单个用户(每个id)每个时段只能订两个场地,每次预订间隔要3分钟 - // 今天的订单 - ThinkOrder todayOrder = thinkOrderService.getTodayOrder(user.getUid()); - if (todayOrder != null) { - if ((System.currentTimeMillis() / 1000) - todayOrder.getCreateTime() < 180) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("每次预订需间隔3分钟"); + if (!thinkOrder.getSid().equals(37)) { + long nowSeconds = DateUtil.currentSeconds(); + for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { + if (info.getStartTime() == null || info.getStartTime() - nowSeconds < 5) { + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("已过开场时间不可预订"); + } } } - // 周末场地需要周四17点后才能预定 - if (DateUtil.dayOfWeek(date) == 6 || DateUtil.dayOfWeek(date) == 7 || DateUtil.dayOfWeek(date) == 1) { - int dayOfWeek = DateUtil.dayOfWeek(new Date()); - if (dayOfWeek == 5 && DateUtil.hour(new Date(), true) < 17) { + if (!thinkOrder.getSid().equals(37)) { + for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { + if (redisUtil.get(info.getStartTime().toString() + info.getFid().toString()) != null) { + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("该场地已被预定.code:0"); + } else { + redisUtil.set(info.getStartTime().toString() + info.getFid().toString(), user.getUid(), 1L, TimeUnit.MINUTES); + } + } + } + if (thinkOrder.getSid().equals(37)) { + // 只能定当天 + if (thinkSite.getDailyMaxNum() != null && thinkSite.getDailyMaxNum() > 0 && thinkSite.getDailyNum() >= thinkSite.getDailyMaxNum()) + return fail("已达上限,无法预定"); + } else { + // 只能定7天 + Date date = DateUtil.parse(thinkOrder.getThinkOrderInfos().get(0).getTimePeriod(), "yyyy-MM-dd"); + long secDiff = DateUtil.between(DateUtil.beginOfDay(DateUtil.date()), date, DateUnit.SECOND); + if (secDiff >= 604800 && !thinkOrder.getSid().equals(28)) { clearSiteRedis(thinkOrder.getThinkOrderInfos()); redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("周末场地需要周四17点后才能预定"); + return fail("只能预定7天内的场地"); } - if (dayOfWeek == 2 || dayOfWeek == 3 || dayOfWeek == 4) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("周四17点后才能预定"); + // 用户限制订单,单个用户(每个id)每个时段只能订两个场地,每次预订间隔要3分钟 + // 今天的订单 + ThinkOrder todayOrder = thinkOrderService.getTodayOrder(user.getUid()); + if (todayOrder != null) { + if ((System.currentTimeMillis() / 1000) - todayOrder.getCreateTime() < 180) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("每次预订需间隔3分钟"); + } } - if (dayOfWeek == 6 || dayOfWeek == 7 || dayOfWeek == 1) { - if (secDiff > 259200) { + // 周末场地需要周四17点后才能预定 + if (DateUtil.dayOfWeek(date) == 6 || DateUtil.dayOfWeek(date) == 7 || DateUtil.dayOfWeek(date) == 1) { + int dayOfWeek = DateUtil.dayOfWeek(new Date()); + if (dayOfWeek == 5 && DateUtil.hour(new Date(), true) < 17) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("周末场地需要周四17点后才能预定"); + } + if (dayOfWeek == 2 || dayOfWeek == 3 || dayOfWeek == 4) { clearSiteRedis(thinkOrder.getThinkOrderInfos()); redisUtil.delete(user.getUid() + "_lastPayOrderTime"); return fail("周四17点后才能预定"); } - } - } - Map siteTimeNumMap = new HashMap<>(); - siteTimeNumMap.put(thinkOrder.getThinkOrderInfos().get(0).getStartTime(), 1); - if (thinkOrder.getThinkOrderInfos().size() > 1) { - if (!Objects.equals(thinkOrder.getThinkOrderInfos().get(0).getStartTime(), thinkOrder.getThinkOrderInfos().get(1).getStartTime())) { - siteTimeNumMap.put(thinkOrder.getThinkOrderInfos().get(1).getStartTime(), 1); - } else { - siteTimeNumMap.put(thinkOrder.getThinkOrderInfos().get(0).getStartTime(), 2); - } - } - // 用户定的这个场的订单 - List startTimeList = thinkOrder.getThinkOrderInfos().stream().map(ThinkOrderInfo::getStartTime).toList(); - Map bookingNumMap = new HashMap<>(); - List orderInfoListInSite = thinkOrderInfoService.orderInfoListByStartTimeList( - thinkOrder.getSid(), startTimeList); - if (!orderInfoListInSite.isEmpty()) { - Set orderIdSet = orderInfoListInSite.stream().map(ThinkOrderInfo::getOid).collect(Collectors.toSet()); - List orderList = thinkOrderService.listByIds(orderIdSet); - List userOrderList = orderList.stream().filter(o -> o.getUid().equals(user.getUid())).toList(); - if (!userOrderList.isEmpty()) { - List userTodayOrderInfoListInSite = new ArrayList<>(); - userTodayOrderInfoListInSite = thinkOrderInfoService.listByOrderIds(userOrderList.stream().map(ThinkOrder::getId).toList()); - for (ThinkOrderInfo info : userTodayOrderInfoListInSite) { - if (bookingNumMap.containsKey(info.getStartTime())) { - bookingNumMap.put(info.getStartTime(), bookingNumMap.get(info.getStartTime()) + 1); - } else { - bookingNumMap.put(info.getStartTime(), 1); - } - } - } - } - // 250327规则修改 - // 周1~周5晚上的18-22时间段、周六~周日全天进行限制。 (限制规则:每个账号订场规则调整成这样,每个时段只能定2个场地) - int day = DateUtil.dayOfWeek(date); - if ((day == 1 || day == 7)) { - for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { - if (bookingNumMap.get(info.getStartTime()) != null) { - if (bookingNumMap.get(info.getStartTime()) + siteTimeNumMap.get(info.getStartTime()) > 2) { + if (dayOfWeek == 6 || dayOfWeek == 7 || dayOfWeek == 1) { + if (secDiff > 259200) { clearSiteRedis(thinkOrder.getThinkOrderInfos()); redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("每个时段只能预定两个场地"); + return fail("周四17点后才能预定"); } } } - } else { - for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { - String hour = DateUtil.format(DateUtil.date((info.getStartTime() * 1000L)), "HH"); - int hourInt = Integer.parseInt(hour); - if (hourInt >= 18) { + Map siteTimeNumMap = new HashMap<>(); + siteTimeNumMap.put(thinkOrder.getThinkOrderInfos().get(0).getStartTime(), 1); + if (thinkOrder.getThinkOrderInfos().size() > 1) { + if (!Objects.equals(thinkOrder.getThinkOrderInfos().get(0).getStartTime(), thinkOrder.getThinkOrderInfos().get(1).getStartTime())) { + siteTimeNumMap.put(thinkOrder.getThinkOrderInfos().get(1).getStartTime(), 1); + } else { + siteTimeNumMap.put(thinkOrder.getThinkOrderInfos().get(0).getStartTime(), 2); + } + } + // 用户定的这个场的订单 + List startTimeList = thinkOrder.getThinkOrderInfos().stream().map(ThinkOrderInfo::getStartTime).toList(); + Map bookingNumMap = new HashMap<>(); + List orderInfoListInSite = thinkOrderInfoService.orderInfoListByStartTimeList( + thinkOrder.getSid(), startTimeList); + if (!orderInfoListInSite.isEmpty()) { + Set orderIdSet = orderInfoListInSite.stream().map(ThinkOrderInfo::getOid).collect(Collectors.toSet()); + List orderList = thinkOrderService.listByIds(orderIdSet); + List userOrderList = orderList.stream().filter(o -> o.getUid().equals(user.getUid())).toList(); + if (!userOrderList.isEmpty()) { + List userTodayOrderInfoListInSite = new ArrayList<>(); + userTodayOrderInfoListInSite = thinkOrderInfoService.listByOrderIds(userOrderList.stream().map(ThinkOrder::getId).toList()); + for (ThinkOrderInfo info : userTodayOrderInfoListInSite) { + if (bookingNumMap.containsKey(info.getStartTime())) { + bookingNumMap.put(info.getStartTime(), bookingNumMap.get(info.getStartTime()) + 1); + } else { + bookingNumMap.put(info.getStartTime(), 1); + } + } + } + } + // 250327规则修改 + // 周1~周5晚上的18-22时间段、周六~周日全天进行限制。 (限制规则:每个账号订场规则调整成这样,每个时段只能定2个场地) + int day = DateUtil.dayOfWeek(date); + if ((day == 1 || day == 7)) { + for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { if (bookingNumMap.get(info.getStartTime()) != null) { if (bookingNumMap.get(info.getStartTime()) + siteTimeNumMap.get(info.getStartTime()) > 2) { clearSiteRedis(thinkOrder.getThinkOrderInfos()); @@ -778,265 +889,329 @@ public class ThinkOrderController extends BaseController { } } } + } else { + for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { + String hour = DateUtil.format(DateUtil.date((info.getStartTime() * 1000L)), "HH"); + int hourInt = Integer.parseInt(hour); + if (hourInt >= 18) { + if (bookingNumMap.get(info.getStartTime()) != null) { + if (bookingNumMap.get(info.getStartTime()) + siteTimeNumMap.get(info.getStartTime()) > 2) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("每个时段只能预定两个场地"); + } + } + } + } } - } - for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { + for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { - ThinkOrderInfo checkOrder = thinkOrderInfoService.checkOrder(info); - if (checkOrder != null) { - ThinkOrder thinkOrderCheck = thinkOrderService.getById(checkOrder.getOid()); - if (thinkOrderCheck != null && (thinkOrderCheck.getOrderStatus().equals(1) || thinkOrderCheck.getOrderStatus().equals(2))) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("该场地已被预定.code:1"); + ThinkOrderInfo checkOrder = thinkOrderInfoService.checkOrder(info); + if (checkOrder != null) { + ThinkOrder thinkOrderCheck = thinkOrderService.getById(checkOrder.getOid()); + if (thinkOrderCheck != null && (thinkOrderCheck.getOrderStatus().equals(1) || thinkOrderCheck.getOrderStatus().equals(2))) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("该场地已被预定.code:1"); + } } } } - } - if (thinkOrder.getPayType().equals(2) && thinkOrder.getVid() == null) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("请选择会员卡"); - } - if (thinkOrder.getPayType().equals(5) && thinkOrder.getCode() == null) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("请选择IC卡"); - } - thinkOrder.setCanInvoice(true); - thinkOrder.setOrderNum(IdUtil.getSnowflake().nextIdStr()); - BigDecimal totalPrice = BigDecimal.ZERO; + if (thinkOrder.getPayType().equals(2) && thinkOrder.getVid() == null) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("请选择会员卡"); + } + if (thinkOrder.getPayType().equals(5) && thinkOrder.getCode() == null) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("请选择IC卡"); + } + thinkOrder.setCanInvoice(true); + thinkOrder.setOrderNum(IdUtil.getSnowflake().nextIdStr()); + BigDecimal totalPrice = BigDecimal.ZERO; // BigDecimal reducePrice = BigDecimal.ZERO; - thinkOrder.setPayPrice(BigDecimal.ZERO); - thinkOrder.setReducePrice(BigDecimal.ZERO); - thinkOrder.setPrice(BigDecimal.ZERO); - thinkOrder.setUid(user.getUid()); - Long now = new Date().getTime(); - long timestamp = (now / 1000); - int num = 0; - if (thinkOrder.getThinkOrderInfos() != null) { - for (ThinkOrderInfo thinkOrderInfo : thinkOrder.getThinkOrderInfos()) { - ThinkSiteTime siteTime = thinkSiteTimeService.getById(thinkOrderInfo.getSiteTimeId()); - thinkOrderInfo.setPrice(BigDecimal.ZERO); - thinkOrderInfo.setChildrenPrice(BigDecimal.ZERO); - BigDecimal price = BigDecimal.ZERO; - BigDecimal halfPrice = BigDecimal.ZERO; - if (siteTime != null && siteTime.getIsStatus() == 1) { - // 半场 - price = siteTime.getPrice(); - halfPrice = siteTime.getHalfPrice(); - String month = DateUtil.format(DateUtil.date((thinkOrderInfo.getStartTime() * 1000L)), "yyyy-MM"); - if (siteTime.getPrices() != null && siteTime.getPrices().contains("{")) { - JSONObject prices = JSONUtil.parseObj(siteTime.getPrices()); - if (prices.getJSONArray(month) != null) { - String priceStr = prices.getJSONArray(month).getStr(thinkOrder.getDay()); - if (priceStr != null && !priceStr.isEmpty()) price = new BigDecimal(priceStr); + thinkOrder.setPayPrice(BigDecimal.ZERO); + thinkOrder.setReducePrice(BigDecimal.ZERO); + thinkOrder.setPrice(BigDecimal.ZERO); + thinkOrder.setUid(user.getUid()); + Long now = new Date().getTime(); + long timestamp = (now / 1000); + int num = 0; + if (thinkOrder.getThinkOrderInfos() != null) { + for (ThinkOrderInfo thinkOrderInfo : thinkOrder.getThinkOrderInfos()) { + ThinkSiteTime siteTime = thinkSiteTimeService.getById(thinkOrderInfo.getSiteTimeId()); + thinkOrderInfo.setPrice(BigDecimal.ZERO); + thinkOrderInfo.setChildrenPrice(BigDecimal.ZERO); + BigDecimal price = BigDecimal.ZERO; + BigDecimal halfPrice = BigDecimal.ZERO; + if (siteTime != null && siteTime.getIsStatus() == 1) { + // 半场 + price = siteTime.getPrice(); + halfPrice = siteTime.getHalfPrice(); + String month = DateUtil.format(DateUtil.date((thinkOrderInfo.getStartTime() * 1000L)), "yyyy-MM"); + if (siteTime.getPrices() != null && siteTime.getPrices().contains("{")) { + JSONObject prices = JSONUtil.parseObj(siteTime.getPrices()); + if (prices.getJSONArray(month) != null) { + String priceStr = prices.getJSONArray(month).getStr(thinkOrder.getDay()); + if (priceStr != null && !priceStr.isEmpty()) price = new BigDecimal(priceStr); + } } - } - if (siteTime.getHalfPrices() != null && siteTime.getHalfPrices().contains("{")) { - JSONObject prices = JSONUtil.parseObj(siteTime.getHalfPrices()); - if (prices.getJSONArray(month) != null) { - String priceStr = prices.getJSONArray(month).getStr(thinkOrder.getDay()); - if (priceStr != null && !priceStr.isEmpty()) halfPrice = new BigDecimal(priceStr); - } - } - thinkOrderInfo.setChildrenPrice(siteTime.getChildrenPrice()); - thinkOrderInfo.setOrderTime(timestamp); - thinkOrderInfo.setTimeFlag(now); -// thinkOrderInfo.setIsChildren(0); - if (thinkOrderInfo.getIsChildren().equals(2)) { - if (thinkOrderInfo.getAdultNum() < 1) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("非法请求,code:1"); - } - if (thinkOrderInfo.getType().equals(2)) - totalPrice = totalPrice.add(halfPrice.multiply(BigDecimal.valueOf(thinkOrderInfo.getAdultNum()))); - else - totalPrice = totalPrice.add(price.multiply(BigDecimal.valueOf(thinkOrderInfo.getAdultNum()))); - num += thinkOrderInfo.getAdultNum(); - } else { - if (thinkOrderInfo.getChildrenNum() < 1) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("非法请求,code:2"); + if (siteTime.getHalfPrices() != null && siteTime.getHalfPrices().contains("{")) { + JSONObject prices = JSONUtil.parseObj(siteTime.getHalfPrices()); + if (prices.getJSONArray(month) != null) { + String priceStr = prices.getJSONArray(month).getStr(thinkOrder.getDay()); + if (priceStr != null && !priceStr.isEmpty()) halfPrice = new BigDecimal(priceStr); + } } thinkOrderInfo.setChildrenPrice(siteTime.getChildrenPrice()); - totalPrice = totalPrice.add(siteTime.getChildrenPrice().multiply(BigDecimal.valueOf(thinkOrderInfo.getChildrenNum()))); - num += thinkOrderInfo.getChildrenNum(); - } - if (thinkOrderInfo.getType().equals(2)) { - thinkOrderInfo.setPrice(halfPrice); - } else { - thinkOrderInfo.setPrice(price); - } + thinkOrderInfo.setOrderTime(timestamp); + thinkOrderInfo.setTimeFlag(now); +// thinkOrderInfo.setIsChildren(0); + if (thinkOrderInfo.getIsChildren().equals(2)) { + if (thinkOrderInfo.getAdultNum() < 1) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("非法请求,code:1"); + } + if (thinkOrderInfo.getType().equals(2)) + totalPrice = totalPrice.add(halfPrice.multiply(BigDecimal.valueOf(thinkOrderInfo.getAdultNum()))); + else + totalPrice = totalPrice.add(price.multiply(BigDecimal.valueOf(thinkOrderInfo.getAdultNum()))); + num += thinkOrderInfo.getAdultNum(); + } else { + if (thinkOrderInfo.getChildrenNum() < 1) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("非法请求,code:2"); + } + thinkOrderInfo.setChildrenPrice(siteTime.getChildrenPrice()); + totalPrice = totalPrice.add(siteTime.getChildrenPrice().multiply(BigDecimal.valueOf(thinkOrderInfo.getChildrenNum()))); + num += thinkOrderInfo.getChildrenNum(); + } + if (thinkOrderInfo.getType().equals(2)) { + thinkOrderInfo.setPrice(halfPrice); + } else { + thinkOrderInfo.setPrice(price); + } // reducePrice = reducePrice.add(thinkOrderInfo.getChildrenPrice()); - } else { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("非法请求,code:3"); - } - } - } - thinkOrder.setTotalPrice(totalPrice); - thinkOrder.setPayPrice(totalPrice); - // VIP卡 - if (thinkOrder.getVid() != null) { - ThinkUsersVip usersVip = thinkUsersVipService.getById(thinkOrder.getVid()); - if (usersVip == null) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("非法请求,code:4"); - } - if (usersVip.getExpireTime() < timestamp) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("会员卡已过期"); - } - if (!usersVip.getUid().equals(getLoginUser().getUid())) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("非法请求,code:1"); - } - if (usersVip.getType().equals(5)) { - if (usersVip.getRemainingMoney().compareTo(BigDecimal.ZERO) < 1) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("余额不足"); - } - BigDecimal discount = usersVip.getDiscount().divide(BigDecimal.valueOf(10), 2, RoundingMode.HALF_UP); - BigDecimal payPrice = totalPrice.multiply(discount); - thinkOrder.setReducePrice(totalPrice.subtract(payPrice)); - thinkOrder.setPayPrice(payPrice); - if (usersVip.getRemainingMoney().compareTo(payPrice) < 0) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("余额不足"); - } - } else if (usersVip.getType().equals(2)) { - if (usersVip.getNum() < num) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("次数不足"); - } - thinkOrder.setReducePrice(totalPrice); - thinkOrder.setPayPrice(BigDecimal.ZERO); - } else { -// if (usersVip.getNum() < num) return fail("次数不足"); - long todayTime = DateUtil.parse(DateUtil.today() + " 00:00:00").getTime() / 1000; - if (usersVip.getUseTime().equals(todayTime)) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("今天已使用"); - } - if (thinkOrder.getSid().equals(37)) { - if (num > 1) { + } else { clearSiteRedis(thinkOrder.getThinkOrderInfos()); redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("年卡/季卡/月卡仅能一人使用"); + return fail("非法请求,code:3"); } } - // 上次使用的订单 + } + // 余额支付 + if (thinkOrder.getPayType().equals(19)) { + if (totalPrice.compareTo(user.getBalance()) > 0) { + return fail("余额不足"); + } + } + thinkOrder.setTotalPrice(totalPrice); + thinkOrder.setPayPrice(totalPrice); + // VIP卡 + if (thinkOrder.getVid() != null) { + ThinkUsersVip usersVip = thinkUsersVipService.getById(thinkOrder.getVid()); + if (usersVip == null) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("非法请求,code:4"); + } + if (usersVip.getExpireTime() < timestamp) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("会员卡已过期"); + } + if (!usersVip.getUid().equals(getLoginUser().getUid())) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("非法请求,code:1"); + } + ThinkVip thinkVip = thinkVipService.getById(usersVip.getVid()); + // 成人卡 + if (thinkVip.getCardType().equals(1) || thinkVip.getCardType().equals(3)) { + for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { + System.out.println("无法使用.code:0," + info.getAdultNum() + "," + thinkVip.getCardType()); + + if (info.getChildrenNum() > 0) return fail("无法使用.code:0"); + } + } else { + for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { + System.out.println("无法使用.code:1," + info.getAdultNum() + "," + thinkVip.getCardType()); + + if (info.getAdultNum() > 0) return fail("无法使用.code:1"); + } + } + if (usersVip.getType().equals(5)) { + if (usersVip.getRemainingMoney().compareTo(BigDecimal.ZERO) < 1) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("余额不足"); + } + BigDecimal discount = usersVip.getDiscount().divide(BigDecimal.valueOf(10), 2, RoundingMode.HALF_UP); + BigDecimal payPrice = totalPrice; + if (discount.compareTo(BigDecimal.ZERO) > 0) { + payPrice = totalPrice.multiply(discount); + thinkOrder.setReducePrice(totalPrice.subtract(payPrice)); + } + thinkOrder.setPayPrice(payPrice); + if (usersVip.getRemainingMoney().compareTo(payPrice) < 0) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("余额不足"); + } + } else if (usersVip.getType().equals(2)) { + if (usersVip.getNum() < num) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("次数不足"); + } + thinkOrder.setReducePrice(totalPrice); + thinkOrder.setPayPrice(BigDecimal.ZERO); + } else { +// if (usersVip.getNum() < num) return fail("次数不足"); + long todayTime = DateUtil.parse(DateUtil.today() + " 00:00:00").getTime() / 1000; + if (usersVip.getUseTime().equals(todayTime)) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("今天已使用"); + } + if (redisUtil.get(usersVip.getId() + "_" + DateUtil.today()) != null) { + return fail("今天已使用"); + } + if (thinkOrder.getSid().equals(37)) { + if (num > 1) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("年卡/季卡/月卡仅能一人使用"); + } + } + // 人脸判断 + String checkFaceRes = checkOrderWithCardHasFace(user.getUid()); + if (checkFaceRes != null) return fail(checkFaceRes); + // 上次使用的订单 // ThinkOrder lastOrder = thinkOrderService.getLastOrderByVid(usersVip.getId()); // if (lastOrder != null) { - // 今天是否已经使用 + // 今天是否已经使用 // long todayStart = DateUtil.beginOfDay(new Date()).getTime() / 1000; // long todayEnd = DateUtil.endOfDay(new Date()).getTime() / 1000; // if (lastOrder.getCreateTime() >= todayStart && lastOrder.getCreateTime() <= todayEnd) { // return fail("今天已使用"); // } // } - thinkOrder.setReducePrice(totalPrice); - thinkOrder.setPayPrice(BigDecimal.ZERO); + thinkOrder.setReducePrice(totalPrice); + thinkOrder.setPayPrice(BigDecimal.ZERO); + } + switch (usersVip.getType()) { + // 年卡 + case 1: { + thinkOrder.setPayType(7); + thinkOrder.setType(4); + } + break; + // 次卡 + case 2: { + thinkOrder.setPayType(8); + thinkOrder.setType(5); + } + break; + // 月卡 + case 3: { + thinkOrder.setPayType(6); + thinkOrder.setType(3); + } + break; + // 季卡 + case 4: { + thinkOrder.setPayType(16); + thinkOrder.setType(6); + } + break; + case 5: { + thinkOrder.setPayType(13); + thinkOrder.setType(12); + } + break; + } + if (!usersVip.getIsInvoice().equals(2)) thinkOrder.setCanInvoice(false); } - switch (usersVip.getType()) { - // 年卡 - case 1: { - thinkOrder.setPayType(7); - thinkOrder.setType(4); + // IC卡 + if (thinkOrder.getCode() != null) { + ThinkCard card = thinkCardService.getByCode(thinkOrder.getCode()); + if (card == null) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("非法请求,code:0"); } - break; - // 次卡 - case 2: { - thinkOrder.setPayType(8); - thinkOrder.setType(5); - } - break; - // 月卡 - case 3: { - thinkOrder.setPayType(6); - thinkOrder.setType(3); - } - break; - // 季卡 - case 4: { - thinkOrder.setPayType(16); - thinkOrder.setType(6); - } - break; - case 5: { - thinkOrder.setPayType(13); - thinkOrder.setType(12); - } - break; - } - if (!usersVip.getIsInvoice().equals(2)) thinkOrder.setCanInvoice(false); - } - // IC卡 - if (thinkOrder.getCode() != null) { - ThinkCard card = thinkCardService.getByCode(thinkOrder.getCode()); - if (card == null) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("非法请求,code:0"); - } // if (!card.getUid().equals(getLoginUser().getUid())) return fail("非法请求,code:1"); - thinkOrder.setCid(card.getId()); - if (card.getExpireTime() < timestamp) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("会员卡已过期"); - } - if (card.getType().equals(5)) { - if (card.getRemainingMoney().compareTo(BigDecimal.ZERO) < 1) { + thinkOrder.setCid(card.getId()); + if (card.getExpireTime() < timestamp) { clearSiteRedis(thinkOrder.getThinkOrderInfos()); redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("余额不足"); + return fail("会员卡已过期"); } - BigDecimal discount = card.getDiscount().divide(BigDecimal.valueOf(10), 2, RoundingMode.HALF_UP); - BigDecimal payPrice = totalPrice.multiply(discount); - BigDecimal reducePrice = totalPrice.subtract(payPrice); - thinkOrder.setReducePrice(reducePrice); - thinkOrder.setPayPrice(payPrice); - if (card.getRemainingMoney().compareTo(payPrice) < 0) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("余额不足"); - } - } else if (card.getType().equals(2)) { - if (card.getNum() < num) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("次数不足"); - } - thinkOrder.setReducePrice(totalPrice); - thinkOrder.setPayPrice(BigDecimal.ZERO); - } else { - long todayTime = DateUtil.parse(DateUtil.today() + " 00:00:00").getTime() / 1000; - if (card.getUseTime().equals(todayTime)) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("今天已使用"); - } - if (thinkOrder.getSid().equals(37)) { - if (num > 1) { - clearSiteRedis(thinkOrder.getThinkOrderInfos()); - redisUtil.delete(user.getUid() + "_lastPayOrderTime"); - return fail("年卡/季卡/月卡仅能一人使用"); + ThinkVip thinkVip = thinkVipService.getById(card.getVid()); + // 成人卡 + if (thinkVip.getCardType().equals(1) || thinkVip.getCardType().equals(3)) { + for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { + System.out.println("无法使用.code:2," + info.getAdultNum() + "," + thinkVip.getCardType()); + if (info.getChildrenNum() > 0) return fail("无法使用.code:2"); + } + } else { + for (ThinkOrderInfo info : thinkOrder.getThinkOrderInfos()) { + System.out.println("无法使用.code:3," + info.getAdultNum() + "," + thinkVip.getCardType()); + if (info.getAdultNum() > 0) return fail("无法使用.code:3"); } } - // 上次使用的订单 + if (card.getType().equals(5)) { + if (card.getRemainingMoney().compareTo(BigDecimal.ZERO) < 1) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("余额不足"); + } + BigDecimal discount = card.getDiscount().divide(BigDecimal.valueOf(10), 2, RoundingMode.HALF_UP); + BigDecimal payPrice = totalPrice; + if (discount.compareTo(BigDecimal.ZERO) > 0) { + payPrice = totalPrice.multiply(discount); + thinkOrder.setReducePrice(totalPrice.subtract(payPrice)); + } + thinkOrder.setPayPrice(payPrice); + if (card.getRemainingMoney().compareTo(payPrice) < 0) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("余额不足"); + } + } else if (card.getType().equals(2)) { + if (card.getNum() < num) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("次数不足"); + } + thinkOrder.setReducePrice(totalPrice); + thinkOrder.setPayPrice(BigDecimal.ZERO); + } else { + long todayTime = DateUtil.parse(DateUtil.today() + " 00:00:00").getTime() / 1000; + if (card.getUseTime().equals(todayTime)) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("今天已使用"); + } + if (redisUtil.get(card.getId() + "_" + DateUtil.today()) != null) { + return fail("今天已使用"); + } + if (thinkOrder.getSid().equals(37)) { + if (num > 1) { + clearSiteRedis(thinkOrder.getThinkOrderInfos()); + redisUtil.delete(user.getUid() + "_lastPayOrderTime"); + return fail("年卡/季卡/月卡仅能一人使用"); + } + } + // 人脸判断 + String checkFaceRes = checkOrderWithCardHasFace(user.getUid()); + if (checkFaceRes != null) return fail(checkFaceRes); + // 上次使用的订单 // ThinkOrder lastOrder = thinkOrderService.getLastOrderByCardCode(card.getCode()); // // 今天是否已经使用 // long todayStart = DateUtil.beginOfDay(new Date()).getTime() / 1000; @@ -1044,53 +1219,88 @@ public class ThinkOrderController extends BaseController { // if (lastOrder.getCreateTime() >= todayStart && lastOrder.getCreateTime() <= todayEnd) { // return fail("今天已使用"); // } - thinkOrder.setReducePrice(totalPrice); - thinkOrder.setPayPrice(BigDecimal.ZERO); + thinkOrder.setReducePrice(totalPrice); + thinkOrder.setPayPrice(BigDecimal.ZERO); + } + switch (card.getType()) { + // 年卡 + case 1: { + thinkOrder.setPayType(10); + thinkOrder.setType(8); + } + break; + // 次卡 + case 2: { + thinkOrder.setPayType(11); + thinkOrder.setType(9); + } + break; + // 月卡 + case 3: { + thinkOrder.setPayType(9); + thinkOrder.setType(7); + } + break; + // 季卡 + case 4: { + thinkOrder.setPayType(17); + thinkOrder.setType(10); + } + break; + case 5: { + thinkOrder.setPayType(14); + thinkOrder.setType(13); + } + break; + } + if (!card.getIsInvoice().equals(2)) thinkOrder.setCanInvoice(false); } - switch (card.getType()) { - // 年卡 - case 1: { - thinkOrder.setPayType(10); - thinkOrder.setType(8); - } - break; - // 次卡 - case 2: { - thinkOrder.setPayType(11); - thinkOrder.setType(9); - } - break; - // 月卡 - case 3: { - thinkOrder.setPayType(9); - thinkOrder.setType(7); - } - break; - // 季卡 - case 4: { - thinkOrder.setPayType(17); - thinkOrder.setType(10); - } - break; - case 5: { - thinkOrder.setPayType(14); - thinkOrder.setType(13); - } - break; - } - if (!card.getIsInvoice().equals(2)) thinkOrder.setCanInvoice(false); - } - thinkOrder.setCreateTime(timestamp); - thinkOrder.setUpdateTime(timestamp); - if (thinkOrderService.save(thinkOrder)) { - for (ThinkOrderInfo thinkOrderInfo : thinkOrder.getThinkOrderInfos()) { - thinkOrderInfo.setOid(thinkOrder.getId()); + thinkOrder.setCreateTime(timestamp); + thinkOrder.setUpdateTime(timestamp); + if (thinkOrderService.save(thinkOrder)) { + for (ThinkOrderInfo thinkOrderInfo : thinkOrder.getThinkOrderInfos()) { + thinkOrderInfo.setOid(thinkOrder.getId()); + } + thinkOrderInfoService.saveBatch(thinkOrder.getThinkOrderInfos()); + // 同步人脸 + if (getLoginUser().getUid() != null) { + ThinkUsers thinkUsers = thinkUsersService.getById(getLoginUser().getUid()); + if (thinkUsers != null && thinkUsers.getHasFace() != null && thinkUsers.getHasFace().equals(1) + && thinkUsers.getPersonPhoto() != null && !thinkUsers.getPersonPhoto().equals("")) { + ThinkUserInAccess check = thinkUserInAccessService.checkByUid(getLoginUser().getUid()); + if (check == null) { + ThinkUserInAccess thinkUserInAccess = new ThinkUserInAccess(); + thinkUserInAccess.setUid(getLoginUser().getUid()); + thinkUserInAccessService.save(thinkUserInAccess); + + List> list = new ArrayList<>(); + Map map = new HashMap<>(); + String day = DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd"); + String accStartTime = day + " 05:00:00"; + String accEndTime = day + " 22:00:00"; + map.put("pin", String.valueOf(thinkUsers.getId())); + map.put("mobilePhone", thinkUsers.getPhone()); + map.put("name", (thinkUsers.getUsername() == null || thinkUsers.getUsername().isEmpty()) + ? String.valueOf(thinkUsers.getId()) + : thinkUsers.getUsername()); + map.put("personPhoto", thinkUsers.getPersonPhoto()); + map.put("accEndTime", accEndTime); + map.put("accLevelIds", thinkGateControlService.getLevelId()); + map.put("accStartTime", accStartTime); + list.add(map); + + thinkGateControlService.addPersons(list); + } + } + } + + return onPay(thinkOrder); } - thinkOrderInfoService.saveBatch(thinkOrder.getThinkOrderInfos()); - return onPay(thinkOrder); + return fail("添加失败"); + } finally { + redisUtil.delete(submitLockKey); } - return fail("添加失败"); } @ApiOperation("营业端添加") @@ -1199,8 +1409,11 @@ public class ThinkOrderController extends BaseController { if (card.getExpireTime() < timestamp) return fail("会员卡已过期"); if (card.getType().equals(5)) { BigDecimal discount = card.getDiscount().divide(BigDecimal.valueOf(10), 2, RoundingMode.HALF_UP); - BigDecimal payPrice = totalPrice.multiply(discount); - thinkOrder.setReducePrice(totalPrice.subtract(payPrice)); + BigDecimal payPrice = totalPrice; + if (discount.compareTo(BigDecimal.ZERO) > 0) { + payPrice = totalPrice.multiply(discount); + thinkOrder.setReducePrice(totalPrice.subtract(payPrice)); + } thinkOrder.setPayPrice(payPrice); if (card.getRemainingMoney().compareTo(payPrice) < 0) return fail("余额不足"); } else if (card.getType().equals(2)) { @@ -1212,6 +1425,7 @@ public class ThinkOrderController extends BaseController { if (card.getUseTime().equals(todayTime)) { return fail("今天已使用"); } + thinkOrder.setReducePrice(totalPrice); thinkOrder.setPayPrice(BigDecimal.ZERO); } @@ -1324,6 +1538,30 @@ public class ThinkOrderController extends BaseController { return success("下单成功", thinkOrderService.createWxOrder(order.getPayPrice(), order.getOrderNum(), desc, getLoginUser().getOpenid(), "https://gxtyzx-api2.websoft.top/api/think/think-order/notify", order.getId())); } + if (order.getPayType().equals(19)) { + updatePay(order, null, order.getTotalPrice().multiply(BigDecimal.valueOf(100)).intValue()); + + User user = getLoginUser(); + BigDecimal currentBalance = user.getBalance() == null ? BigDecimal.ZERO : user.getBalance(); + BigDecimal latestBalance = currentBalance.subtract(order.getTotalPrice()); + user.setBalance(latestBalance); + userService.updateInner(user); + + UserBalanceLog userBalanceLog = new UserBalanceLog(); + userBalanceLog.setUserId(user.getUserId()); + userBalanceLog.setScene(1); + userBalanceLog.setMoney(order.getTotalPrice()); + userBalanceLog.setBalance(latestBalance); + userBalanceLog.setRemark("订场消费"); + userBalanceLog.setComments("消费订单号:" + order.getOrderNum()); + userBalanceLog.setStatus(0); + userBalanceLog.setDeleted(0); + userBalanceLog.setTenantId(10150); + userBalanceLog.setCreateTime(LocalDateTime.now()); + userBalanceLog.setUpdateTime(LocalDateTime.now()); + userBalanceLogService.save(userBalanceLog); + return success("支付成功", order.getId()); + } if (order.getPayType() >= 6 || order.getPayType().equals(2)) { order.setIsInvoice(order.getCanInvoice() ? 2 : 3); thinkOrderService.updateById(order); @@ -1333,10 +1571,26 @@ public class ThinkOrderController extends BaseController { return fail("支付失败"); } + @ApiOperation("设置已开票") + @PutMapping("/set-invoice") + public ApiResult setInvoice(@RequestBody List ids) { + if (ids == null || ids.isEmpty()) { + return fail("请选择订单"); + } + if (thinkOrderService.update(new LambdaUpdateWrapper() + .in(ThinkOrder::getId, ids) + .set(ThinkOrder::getIsInvoice, 1))) { + return success("设置成功"); + } + return fail("设置失败"); + } + @ApiOperation("修改") @PutMapping() public ApiResult update(@RequestBody ThinkOrder thinkOrder) { ThinkOrder thinkOrder1 = thinkOrderService.getByIdRel(thinkOrder.getId()); + if (thinkOrder1.getOrderStatus().equals(3)) return fail("订单已取消"); + if (!thinkOrder1.getOrderStatus().equals(2)) return fail("无法取消"); if (thinkOrder.getCid() != null && !thinkOrder.getCid().equals(0) && thinkOrder.getPayStatus() != null && thinkOrder.getPayStatus().equals(1)) { BigDecimal totalPrice = thinkOrder1.getTotalPrice(); @@ -1346,9 +1600,11 @@ public class ThinkOrderController extends BaseController { thinkOrder.setPayPrice(totalPrice); if (card.getType().equals(5)) { BigDecimal discount = card.getDiscount().divide(BigDecimal.valueOf(10), 2, RoundingMode.HALF_UP); - BigDecimal payPrice = totalPrice.multiply(discount); - BigDecimal reducePrice = totalPrice.subtract(payPrice); - thinkOrder.setReducePrice(reducePrice); + BigDecimal payPrice = totalPrice; + if (discount.compareTo(BigDecimal.ZERO) > 0) { + payPrice = totalPrice.multiply(discount); + thinkOrder.setReducePrice(totalPrice.subtract(payPrice)); + } thinkOrder.setPayPrice(payPrice); if (card.getRemainingMoney().compareTo(payPrice) < 0) return fail("余额不足"); @@ -1369,6 +1625,9 @@ public class ThinkOrderController extends BaseController { if (card.getUseTime().equals(todayTime)) { return fail("今天已使用"); } + if (redisUtil.get(card.getId() + "_" + DateUtil.today()) != null) { + return fail("今天已使用"); + } thinkOrder.setReducePrice(totalPrice); thinkOrder.setPayPrice(BigDecimal.ZERO); } @@ -1473,7 +1732,7 @@ public class ThinkOrderController extends BaseController { String[] headers = {"场馆名称", "下单时间", "订单号", "手机号", "实际转账单位/个人", "订单状态", "支付状态", "原价", "实付", "订场信息", "支付方式", "预付卡号", "预付卡到期时间"}; String[] payType = {"余额支付", "微信支付", "积分", "支付宝", "现金", "POS机", "VIP月卡", "VIP年卡", "VIP次卡", "IC月卡", - "IC年卡", "IC次卡", "免费", "VIP充值卡", "IC充值卡", "积分支付", "VIP季卡", "IC季卡"}; + "IC年卡", "IC次卡", "免费", "VIP充值卡", "IC充值卡", "积分支付", "VIP季卡", "IC季卡", "对公", "余额"}; for (int i = 0; i < headers.length; i++) { row.createCell(i).setCellValue(headers[i]); } @@ -1533,10 +1792,29 @@ public class ThinkOrderController extends BaseController { orderRow.createCell(8).setCellValue(order.getPayPrice().toString()); orderRow.createCell(9).setCellValue(order.getDateTime()); orderRow.createCell(10).setCellValue(payType[order.getPayType()]); + ThinkCard thinkCard = null; + if (order.getCode() != null && !order.getCode().isEmpty()) { + thinkCard = thinkCardService.getByCode(order.getCode()); + } + if (thinkCard == null) { + if (order.getCid() != null && order.getCid() != 0) { + thinkCard = thinkCardService.getById(order.getCid()); + } + } + if (thinkCard != null) { + order.setCard(thinkCard); + } if (order.getCard() != null) { orderRow.createCell(11).setCellValue(order.getCard().getCode()); orderRow.createCell(12).setCellValue(DateUtil.format(DateUtil.date(order.getCard().getExpireTime() * 1000), "yyyy-MM-dd HH:mm:ss")); } + ThinkUsersVip thinkUsersVip = null; + if (order.getVid() != null && order.getVid() != 0) { + thinkUsersVip = thinkUsersVipService.getById(order.getVid()); + } + if (thinkUsersVip != null) { + order.setThinkVip(thinkUsersVip); + } if (order.getThinkVip() != null) { orderRow.createCell(11).setCellValue(order.getThinkVip().getCode()); orderRow.createCell(12).setCellValue(DateUtil.format(DateUtil.date(order.getThinkVip().getExpireTime() * 1000), "yyyy-MM-dd HH:mm:ss")); @@ -1565,7 +1843,7 @@ public class ThinkOrderController extends BaseController { String path = uploadPath + filename; XSSFWorkbook workbook = new XSSFWorkbook(Files.newInputStream(Paths.get(uploadPath + "财务小程序报表样表.xlsx"))); XSSFSheet sheet0 = workbook.getSheetAt(0); - Integer[] sidList = {34, 33, 53, 31, 30, 32, 51, 50, 37, 36, 28, 48, 49, 44}; + Integer[] sidList = {34, 33, 53, 31, 30, 32, 51, 50, 37, 36, 56, 57, 28, 48, 49, 44, 55}; BigDecimal wechatIncome = BigDecimal.ZERO; BigDecimal posIncome = BigDecimal.ZERO; @@ -1638,7 +1916,7 @@ public class ThinkOrderController extends BaseController { queryWrapper.select("sum(total_price) as total_income", "pay_type") .eq("sid", sid) .eq("pay_status", 1) - .notIn("pay_type", Arrays.asList(1, 5, 18, 4)); + .notIn("pay_type", Arrays.asList(1, 5, 18, 19, 4)); if (param.getCreateTimeStart() != null) { queryWrapper.ge("create_time", param.getCreateTimeStart()); queryWrapper.le("create_time", param.getCreateTimeEnd()); @@ -1693,7 +1971,7 @@ public class ThinkOrderController extends BaseController { @PostMapping("/excel-data") public ApiResult excelData(@RequestBody ThinkOrderParam param) throws IOException { - Integer[] sidList = {34, 33, 53, 31, 30, 32, 51, 50, 37, 36, 28, 48, 49, 44}; + Integer[] sidList = {34, 33, 53, 31, 30, 32, 51, 50, 37, 36, 56, 57, 28, 48, 49, 44, 55}; List> list = new ArrayList<>(); BigDecimal wechatIncome = BigDecimal.ZERO; @@ -1714,7 +1992,10 @@ public class ThinkOrderController extends BaseController { } List rechargeLogList = thinkRechargeLogService.list(vipQueryWrapper); List vipOrderVipList = new ArrayList<>(); - List thinkVipList = thinkVipService.list(); + List thinkVipList = thinkVipService.list( + new LambdaQueryWrapper() + .in(ThinkVip::getVipType, 1, 2) + ); if (!rechargeLogList.isEmpty()) { Set vipIdSet = new HashSet<>(); for (ThinkRechargeLog vipOrder : rechargeLogList) { @@ -1767,7 +2048,7 @@ public class ThinkOrderController extends BaseController { if (!orderList.isEmpty()) { BigDecimal otherIncomeTmp = BigDecimal.ZERO; for (ThinkOrder order : orderList) { - if (order.getPayType().equals(1) && order.getWechatOrder() != null && order.getWechatOrder().contains("420000")) { + if (order.getPayType().equals(1) && order.getWechatOrder() != null && (order.getWechatOrder().contains("420000") || order.getWechatOrder().contains("450000"))) { wechatIncome = wechatIncome.add(order.getPayPrice()); wechatIncomeSum = wechatIncomeSum.add(order.getPayPrice()); siteIncome = siteIncome.add(order.getPayPrice()); @@ -1775,7 +2056,7 @@ public class ThinkOrderController extends BaseController { totalIncomeSum = totalIncomeSum.add(order.getPayPrice()); } else if (order.getPayType().equals(5) || order.getPayType().equals(3) || (order.getPayType().equals(1) - && (order.getWechatOrder() != null && !order.getWechatOrder().isEmpty() && !order.getWechatOrder().contains("420000")))) { + && (order.getWechatOrder() != null && !order.getWechatOrder().isEmpty() && !order.getWechatOrder().contains("420000") && !order.getWechatOrder().contains("450000")))) { if (!order.getOrderStatus().equals(6)) { posIncome = posIncome.add(order.getPayPrice()); posIncomeSum = posIncomeSum.add(order.getPayPrice()); @@ -1811,10 +2092,12 @@ public class ThinkOrderController extends BaseController { } } } - // 微信退款订单 + // 微信退款订单(与收入统计一致:微信单号含 420000 / 450000) LambdaQueryWrapper refundQueryWrapper = new LambdaQueryWrapper<>(); - refundQueryWrapper.like(ThinkOrder::getSid, sid) - .like(ThinkOrder::getWechatOrder, "420000") + refundQueryWrapper.eq(ThinkOrder::getSid, sid) + .and(w -> w.like(ThinkOrder::getWechatOrder, "420000") + .or() + .like(ThinkOrder::getWechatOrder, "450000")) .in(ThinkOrder::getOrderStatus, 6); if (param.getCreateTimeStart() != null) { refundQueryWrapper.between(ThinkOrder::getRefundTime, param.getCreateTimeStart(), param.getCreateTimeEnd()); @@ -1956,7 +2239,7 @@ public class ThinkOrderController extends BaseController { @PostMapping("/excel-data-for-card") public ApiResult excelDataForCard(@RequestBody ThinkOrderParam param) throws IOException { - Integer[] sidList = {34, 33, 53, 31, 30, 32, 51, 50, 37, 36, 28, 48, 49, 44}; + Integer[] sidList = {34, 33, 53, 31, 30, 32, 51, 50, 37, 36, 56, 57, 28, 48, 49, 44, 55}; List> list = new ArrayList<>(); // 次卡 @@ -2051,6 +2334,70 @@ public class ThinkOrderController extends BaseController { return success(list); } + @PostMapping("/training-business-data") + public ApiResult trainingBusinessData(@RequestBody ThinkOrderParam param) { + return success(buildTrainingBusinessSections(param)); + } + + @PostMapping("/training-business-export") + public ApiResult trainingBusinessExport(@RequestBody ThinkOrderParam param) throws IOException { + List> sections = buildTrainingBusinessSections(param); + String filename = "excel/培训业务报表-" + new Date().getTime() + ".xlsx"; + String path = uploadPath + filename; + SXSSFWorkbook workbook = new SXSSFWorkbook(); + SXSSFSheet sheet = workbook.createSheet("培训业务报表"); + + int[] widths = {28, 14, 16, 14, 16, 14, 16, 14, 16}; + for (int i = 0; i < widths.length; i++) { + sheet.setColumnWidth(i, widths[i] * 256); + } + + int rowNum = 0; + for (Map section : sections) { + SXSSFRow titleRow = sheet.createRow(rowNum++); + titleRow.createCell(0).setCellValue(String.valueOf(section.get("title"))); + + SXSSFRow headerRow1 = sheet.createRow(rowNum++); + headerRow1.createCell(0).setCellValue("培训机构名称"); + headerRow1.createCell(1).setCellValue("开卡统计"); + headerRow1.createCell(3).setCellValue("核销次数"); + headerRow1.createCell(5).setCellValue("过期次数"); + headerRow1.createCell(7).setCellValue("未核销次数"); + + SXSSFRow headerRow2 = sheet.createRow(rowNum++); + headerRow2.createCell(1).setCellValue("次数"); + headerRow2.createCell(2).setCellValue("收款金额"); + headerRow2.createCell(3).setCellValue("次数"); + headerRow2.createCell(4).setCellValue("核销金额"); + headerRow2.createCell(5).setCellValue("次数"); + headerRow2.createCell(6).setCellValue("过期金额"); + headerRow2.createCell(7).setCellValue("次数"); + headerRow2.createCell(8).setCellValue("剩余金额"); + + @SuppressWarnings("unchecked") + List> rows = (List>) section.get("rows"); + for (Map row : rows) { + SXSSFRow dataRow = sheet.createRow(rowNum++); + writeTrainingBusinessRow(dataRow, row); + } + SXSSFRow totalRow = sheet.createRow(rowNum++); + writeTrainingBusinessRow(totalRow, (Map) section.get("total")); + rowNum++; + } + + try (FileOutputStream output = new FileOutputStream(path)) { + workbook.write(output); + } + workbook.close(); + + FileRecord result = new FileRecord(); + result.setCreateUserId(getLoginUserId()); + result.setName(filename); + result.setPath(path); + result.setUrl(config.getServerUrl() + "/file/" + filename); + return success(result); + } + @PostMapping("/data-for-front") public ApiResult dataForFront(@RequestBody ThinkOrderParam param) throws IOException { String[] payTypeStrList = {"微信支付", "余额支付", "支付宝", "现金", "POS机", "VIP月卡", "VIP年卡", "VIP次卡", @@ -2058,9 +2405,10 @@ public class ThinkOrderController extends BaseController { List icCardList = new ArrayList<>(Arrays.asList(9, 10, 11, 14, 17)); List vipCardList = new ArrayList<>(Arrays.asList(6, 7, 8, 13, 16)); List> result = new ArrayList<>(); - List allThinkVipList = thinkVipService.listRel(new ThinkVipParam() {{ - setReportSid(param.getSid()); - }}); + List allThinkVipList = thinkVipService.list( + new LambdaQueryWrapper() + .in(ThinkVip::getVipType, 1, 2) + .eq(ThinkVip::getReportSid, param.getSid())); List cardList = new ArrayList<>(); List renewCardList = new ArrayList<>(); if (!allThinkVipList.isEmpty()) { @@ -2280,30 +2628,54 @@ public class ThinkOrderController extends BaseController { BigDecimal publicIncomeVIP = BigDecimal.ZERO; BigDecimal douyinIncomeVIP = BigDecimal.ZERO; int numVIP = 0; - List vipList = new ArrayList<>(); + List vipList = new ArrayList<>(); if (!allThinkVipList.isEmpty()) { - vipList = thinkUsersVipService.list( - new LambdaQueryWrapper() - .eq(ThinkUsersVip::getStatus, 1) - .in(ThinkUsersVip::getVid, allThinkVipList.stream().map(ThinkVip::getId).toList()) - .between(ThinkUsersVip::getCreateTime, param.getCreateTimeStart(), param.getCreateTimeEnd()) - .groupBy(ThinkUsersVip::getVid) +// List thinkUsersVipList = thinkUsersVipService.list( +// new LambdaQueryWrapper() +// .eq(ThinkUsersVip::getStatus, 1) +// .in(ThinkUsersVip::getVid, allThinkVipList.stream().map(ThinkVip::getId).toList()) +// .groupBy(ThinkUsersVip::getVid) +// ); +// vipList = thinkUsersVipService.list( +// new LambdaQueryWrapper() +// .eq(ThinkUsersVip::getStatus, 1) +// .in(ThinkUsersVip::getVid, allThinkVipList.stream().map(ThinkVip::getId).toList()) +// .between(ThinkUsersVip::getCreateTime, param.getCreateTimeStart(), param.getCreateTimeEnd()) +// .groupBy(ThinkUsersVip::getVid) +// ); + vipList = thinkRechargeLogService.list( + new MPJQueryWrapper() + .leftJoin("think_users_vip t1 on t1.id = t.vid") + .select("t.*", "t1.vid as vip_id", "t1.name") + .eq("t.status", 1) + .in("t1.vid", allThinkVipList.stream().map(ThinkVip::getId).toList()) + .between("t.create_time", param.getCreateTimeStart(), param.getCreateTimeEnd()) + .groupBy("t1.vid") ); } if (!vipList.isEmpty()) { for (int i = 0; i < vipList.size(); i++) { - ThinkUsersVip card = vipList.get(i); +// ThinkUsersVip card = vipList.get(i); + ThinkRechargeLog rechargeLog = vipList.get(i); Map data = new HashMap<>(); - List list = thinkUsersVipService.list( - new LambdaQueryWrapper() - .eq(ThinkUsersVip::getVid, card.getVid()) - .eq(ThinkUsersVip::getStatus, 1) - .between(ThinkUsersVip::getCreateTime, param.getCreateTimeStart(), param.getCreateTimeEnd()) +// List list = thinkUsersVipService.list( +// new LambdaQueryWrapper() +// .eq(ThinkUsersVip::getVid, card.getVid()) +// .eq(ThinkUsersVip::getStatus, 1) +// .between(ThinkUsersVip::getCreateTime, param.getCreateTimeStart(), param.getCreateTimeEnd()) +// ); + List list = thinkRechargeLogService.list( + new MPJQueryWrapper() + .select("t.*") + .leftJoin("think_users_vip t1 on t1.id = t.vid") + .eq("t1.vid", rechargeLog.getVipId()) + .between("t.create_time", param.getCreateTimeStart(), param.getCreateTimeEnd()) + .eq("t.status", 1) ); - data.put("name", card.getName()); + data.put("name", rechargeLog.getName()); data.put("num", list.size()); - data.put("vid", card.getVid()); - BigDecimal totalIncome = list.stream().map(ThinkUsersVip::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add); + data.put("vid", rechargeLog.getVipId()); + BigDecimal totalIncome = list.stream().map(ThinkRechargeLog::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal cashIncome = BigDecimal.ZERO; BigDecimal bankIncome = BigDecimal.ZERO; BigDecimal wechatIncome = BigDecimal.ZERO; @@ -2312,8 +2684,8 @@ public class ThinkOrderController extends BaseController { BigDecimal publicIncome = BigDecimal.ZERO; BigDecimal douyinIncome = BigDecimal.ZERO; - for (ThinkUsersVip card1 : list) { - wechatIncome = wechatIncome.add(card1.getPrice()); + for (ThinkRechargeLog card1 : list) { + wechatIncome = wechatIncome.add(card1.getMoney()); } data.put("wechatIncome", wechatIncome); @@ -2781,4 +3153,290 @@ public class ThinkOrderController extends BaseController { } } + private List> buildTrainingBusinessSections(ThinkOrderParam param) { + LambdaQueryWrapper vipWrapper = new LambdaQueryWrapper() + .eq(ThinkVip::getVipType, 3) + .isNotNull(ThinkVip::getReportSid) + .isNotNull(ThinkVip::getTrainingInstitutionId) + .orderByAsc(ThinkVip::getReportSid) + .orderByAsc(ThinkVip::getTrainingInstitutionId) + .orderByAsc(ThinkVip::getId); + List trainingVipList = thinkVipService.list(vipWrapper); + if (trainingVipList.isEmpty()) { + return new ArrayList<>(); + } + + Set institutionIdSet = trainingVipList.stream() + .map(ThinkVip::getTrainingInstitutionId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + List institutionList = institutionIdSet.isEmpty() + ? new ArrayList<>() + : thinkTrainingInstitutionService.listByIds(institutionIdSet); + Map institutionMap = institutionList.stream() + .collect(Collectors.toMap(ThinkTrainingInstitution::getId, item -> item, (a, b) -> a)); + + List vipIds = trainingVipList.stream().map(ThinkVip::getId).toList(); + List usersVipList = vipIds.isEmpty() + ? new ArrayList<>() + : thinkUsersVipService.list( + new LambdaQueryWrapper() + .in(ThinkUsersVip::getVid, vipIds) + .eq(ThinkUsersVip::getStatus, 1) + ); + Map> usersVipMap = usersVipList.stream() + .collect(Collectors.groupingBy(ThinkUsersVip::getVid)); + + List usersVipIds = usersVipList.stream().map(ThinkUsersVip::getId).toList(); + List billsList = usersVipIds.isEmpty() + ? new ArrayList<>() + : thinkVipCardsBillsService.list( + new LambdaQueryWrapper() + .in(ThinkVipCardsBills::getVid, usersVipIds) + ); + Map> billMap = billsList.stream() + .collect(Collectors.groupingBy(ThinkVipCardsBills::getVid)); + List trainingCardList = vipIds.isEmpty() + ? new ArrayList<>() + : thinkCardService.list( + new LambdaQueryWrapper() + .in(ThinkCard::getVid, vipIds) + .eq(ThinkCard::getStatus, 1) + ); + Map> trainingCardMap = trainingCardList.stream() + .collect(Collectors.groupingBy(ThinkCard::getVid)); + List trainingCardIds = trainingCardList.stream().map(ThinkCard::getId).toList(); + List trainingOrderList = trainingCardIds.isEmpty() + ? new ArrayList<>() + : thinkOrderService.list( + new LambdaQueryWrapper() + .in(ThinkOrder::getCid, trainingCardIds) + .eq(ThinkOrder::getPayStatus, 1) + ); + Map> trainingOrderMap = trainingOrderList.stream() + .filter(order -> order.getCid() != null) + .collect(Collectors.groupingBy(ThinkOrder::getCid)); + + Set reportSidSet = trainingVipList.stream() + .map(ThinkVip::getReportSid) + .filter(Objects::nonNull) + .collect(Collectors.toCollection(LinkedHashSet::new)); + Map siteMap = reportSidSet.isEmpty() + ? new HashMap<>() + : thinkSiteService.listByIds(reportSidSet).stream() + .collect(Collectors.toMap(ThinkSite::getId, item -> item, (a, b) -> a)); + + List> sections = new ArrayList<>(); + for (Integer reportSid : reportSidSet) { + List reportSiteVips = trainingVipList.stream() + .filter(v -> reportSid.equals(v.getReportSid())) + .toList(); + List> rows = new ArrayList<>(); + Set currentInstitutionIds = reportSiteVips.stream() + .map(ThinkVip::getTrainingInstitutionId) + .filter(Objects::nonNull) + .collect(Collectors.toCollection(LinkedHashSet::new)); + for (Integer institutionId : currentInstitutionIds) { + ThinkTrainingInstitution institution = institutionMap.get(institutionId); + String institutionName = institution != null ? institution.getName() : "未命名机构"; + List institutionVips = reportSiteVips.stream() + .filter(v -> institutionId.equals(v.getTrainingInstitutionId())) + .toList(); + rows.add(buildTrainingInstitutionRow( + institutionName, + institutionVips, + trainingCardMap, + trainingOrderMap, + param + )); + } + ThinkSite site = siteMap.get(reportSid); + String siteName = site != null ? site.getName() : "未命名场馆"; + sections.add(new HashMap<>() {{ + put("key", String.valueOf(reportSid)); + put("title", siteName + "培训业务报表"); + put("rows", rows); + put("total", sumTrainingRows(rows)); + }}); + } + return sections; + } + + private Map buildTrainingInstitutionRow( + String institutionName, + List vipList, + Map> trainingCardMap, + Map> trainingOrderMap, + ThinkOrderParam param + ) { + Map row = initTrainingRow(institutionName); + for (ThinkVip vip : vipList) { + List trainingCards = trainingCardMap.getOrDefault(vip.getId(), new ArrayList<>()); + int expiredCount = 0; + int unverifiedCount = 0; + BigDecimal expiredAmount = BigDecimal.ZERO; + BigDecimal remainingAmount = BigDecimal.ZERO; + for (ThinkCard trainingCard : trainingCards) { + if (!matchTrainingDateRange(trainingCard.getCreateTime(), param)) { + continue; + } + addCount(row, "openCount", trainingCard.getCount()); + addAmount(row, "openAmount", trainingCard.getPrice()); + + BigDecimal unitAmount = resolveTrainingCardUnitAmount(trainingCard); + Integer remainNum = safeInt(trainingCard.getNum()); + BigDecimal remainAmount = trainingCard.getRemainingMoney(); + if (trainingCard.getExpireTime() != null && trainingCard.getExpireTime() < System.currentTimeMillis() / 1000) { + expiredCount += remainNum; + expiredAmount = expiredAmount.add(remainAmount); + } else { + unverifiedCount += remainNum; + remainingAmount = remainingAmount.add(remainAmount); + } + + List thinkOrders = trainingOrderMap.getOrDefault(trainingCard.getId(), new ArrayList<>()); + List matchedOrders = thinkOrders.stream() + .filter(order -> matchTrainingDateRange(order.getCreateTime(), param)) + .toList(); + if (!matchedOrders.isEmpty()) { + int verifyCount = matchedOrders.size(); + BigDecimal verifyAmount = matchedOrders.stream() + .map(ThinkOrder::getPayPrice) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + addCount(row, "verifyCount", verifyCount); + addAmount(row, "verifyAmount", verifyAmount); + } + } + addCount(row, "expiredCount", expiredCount); + addAmount(row, "expiredAmount", expiredAmount); + addCount(row, "unverifiedCount", unverifiedCount); + addAmount(row, "remainingAmount", remainingAmount); + } + return row; + } + + private boolean matchTrainingDateRange(Long createTime, ThinkOrderParam param) { + if (createTime == null) { + return false; + } + if (param.getCreateTimeStart() != null && createTime < Long.parseLong(String.valueOf(param.getCreateTimeStart()))) { + return false; + } + return param.getCreateTimeEnd() == null || createTime <= Long.parseLong(String.valueOf(param.getCreateTimeEnd())); + } + + private BigDecimal resolveTrainingCardUnitAmount(ThinkCard trainingCard) { + Integer totalCount = safeInt(trainingCard.getCount()); + if (trainingCard.getEachMoney() != null && trainingCard.getEachMoney().compareTo(BigDecimal.ZERO) > 0) { + return trainingCard.getEachMoney(); + } + if (totalCount > 0 && trainingCard.getPrice() != null) { + return trainingCard.getPrice().divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP); + } + return BigDecimal.ZERO; + } + + private Map initTrainingRow(String institutionName) { + Map row = new LinkedHashMap<>(); + row.put("trainingInstitutionName", institutionName); + row.put("openCount", 0); + row.put("openAmount", BigDecimal.ZERO); + row.put("verifyCount", 0); + row.put("verifyAmount", BigDecimal.ZERO); + row.put("expiredCount", 0); + row.put("expiredAmount", BigDecimal.ZERO); + row.put("unverifiedCount", 0); + row.put("remainingAmount", BigDecimal.ZERO); + return row; + } + + private Map sumTrainingRows(List> rows) { + Map total = initTrainingRow("合计"); + for (Map row : rows) { + addCount(total, "openCount", safeInt(row.get("openCount"))); + addAmount(total, "openAmount", safeAmount(row.get("openAmount"))); + addCount(total, "verifyCount", safeInt(row.get("verifyCount"))); + addAmount(total, "verifyAmount", safeAmount(row.get("verifyAmount"))); + addCount(total, "expiredCount", safeInt(row.get("expiredCount"))); + addAmount(total, "expiredAmount", safeAmount(row.get("expiredAmount"))); + addCount(total, "unverifiedCount", safeInt(row.get("unverifiedCount"))); + addAmount(total, "remainingAmount", safeAmount(row.get("remainingAmount"))); + } + formatTrainingRow(total); + return total; + } + + private void writeTrainingBusinessRow(SXSSFRow row, Map data) { + row.createCell(0).setCellValue(String.valueOf(data.get("trainingInstitutionName"))); + row.createCell(1).setCellValue(safeInt(data.get("openCount"))); + row.createCell(2).setCellValue(String.valueOf(data.get("openAmount"))); + row.createCell(3).setCellValue(safeInt(data.get("verifyCount"))); + row.createCell(4).setCellValue(String.valueOf(data.get("verifyAmount"))); + row.createCell(5).setCellValue(safeInt(data.get("expiredCount"))); + row.createCell(6).setCellValue(String.valueOf(data.get("expiredAmount"))); + row.createCell(7).setCellValue(safeInt(data.get("unverifiedCount"))); + row.createCell(8).setCellValue(String.valueOf(data.get("remainingAmount"))); + } + + private void addCount(Map row, String field, int count) { + row.put(field, safeInt(row.get(field)) + count); + } + + private void addAmount(Map row, String field, BigDecimal amount) { + row.put(field, safeAmount(row.get(field)).add(amount == null ? BigDecimal.ZERO : amount)); + formatTrainingRow(row); + } + + private void formatTrainingRow(Map row) { + row.put("openAmount", formatTrainingAmount(row.get("openAmount"))); + row.put("verifyAmount", formatTrainingAmount(row.get("verifyAmount"))); + row.put("expiredAmount", formatTrainingAmount(row.get("expiredAmount"))); + row.put("remainingAmount", formatTrainingAmount(row.get("remainingAmount"))); + } + + private String formatTrainingAmount(Object value) { + return new DecimalFormat("0.##").format(safeAmount(value)); + } + + private int safeInt(Object value) { + if (value == null) { + return 0; + } + if (value instanceof Number number) { + return number.intValue(); + } + if (String.valueOf(value).isEmpty()) { + return 0; + } + return Integer.parseInt(String.valueOf(value)); + } + + private BigDecimal safeAmount(Object value) { + if (value == null) { + return BigDecimal.ZERO; + } + if (value instanceof BigDecimal bigDecimal) { + return bigDecimal; + } + if (value instanceof Number number) { + return BigDecimal.valueOf(number.doubleValue()); + } + String str = String.valueOf(value).replace(",", ""); + if (str.isEmpty()) { + return BigDecimal.ZERO; + } + return new BigDecimal(str); + } + + private String checkOrderWithCardHasFace(Integer uid) { + if (uid == 49042 || uid == 41767 || uid == 13448) { + ThinkUsers thinkUsers = thinkUsersService.getById(uid); + if (thinkUsers == null) return "用户不存在"; + if (thinkUsers.getHasFace() == null || thinkUsers.getHasFace().equals(0) || thinkUsers.getPersonPhoto() == null || thinkUsers.getPersonPhoto().isEmpty()) + return "未绑定人脸"; + return null; + } + return null; + } } diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkOrderRefundLogController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkOrderRefundLogController.java index 4250391..ae063cc 100644 --- a/src/main/java/com/gxwebsoft/think/controller/ThinkOrderRefundLogController.java +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkOrderRefundLogController.java @@ -5,6 +5,9 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.LocalDateTimeUtil; import com.gxwebsoft.common.core.utils.RedisUtil; import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.common.system.service.UserService; +import com.gxwebsoft.shop.entity.UserBalanceLog; +import com.gxwebsoft.shop.service.UserBalanceLogService; import com.gxwebsoft.think.entity.*; import com.gxwebsoft.think.service.*; import com.gxwebsoft.think.param.ThinkOrderRefundLogParam; @@ -58,6 +61,12 @@ public class ThinkOrderRefundLogController extends BaseController { private ThinkUsersVipService thinkUsersVipService; @Resource private ThinkCardService thinkCardService; + @Resource + private UserService userService; + @Resource + private UserBalanceLogService userBalanceLogService; + @Resource + private ThinkMachineOpenLogService thinkMachineOpenLogService; @Autowired private RedisUtil redisUtil; @@ -87,6 +96,7 @@ public class ThinkOrderRefundLogController extends BaseController { thinkOrderRefundLog.setStatus(2); if (thinkOrder != null) { thinkOrder.setOrderStatus(6); + thinkOrder.setRefundBy(1); thinkOrder.setRefundTime((int) (System.currentTimeMillis() / 1000)); List thinkOrderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId()); for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) { @@ -136,15 +146,25 @@ public class ThinkOrderRefundLogController extends BaseController { // 可提前6小时退 ThinkOrder thinkOrder = thinkOrderService.getById(thinkOrderRefundLog.getOid()); List thinkOrderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId()); + long currentSeconds = DateUtil.currentSeconds(); if (thinkOrderRefundLog.getIsAdmin() == null) { if (!thinkOrder.getSid().equals(37)) { - System.out.println("time cal: " + DateUtil.currentSeconds() + "," + thinkOrder.getCreateTime() + "," + ((int) DateUtil.currentSeconds() - thinkOrder.getCreateTime())); - if ((int) DateUtil.currentSeconds() - thinkOrder.getCreateTime() > 1800) { - if (thinkOrderInfoList.get(0).getStartTime() - (int) DateUtil.currentSeconds() < (3600 * 6)) { + for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) { + if (thinkOrderInfo.getStartTime() != null && currentSeconds > thinkOrderInfo.getStartTime()) { + return fail("已过开场时间不可退"); + } + } + System.out.println("time cal: " + currentSeconds + "," + thinkOrder.getCreateTime() + "," + ((int) currentSeconds - thinkOrder.getCreateTime())); + if ((int) currentSeconds - thinkOrder.getCreateTime() > 1800) { + if (thinkOrderInfoList.get(0).getStartTime() - (int) currentSeconds < (3600 * 6)) { return fail("距离开场已不足6小时不可退"); } } } else { + ThinkMachineOpenLog thinkMachineOpenLog = thinkMachineOpenLogService.getByOrderId(thinkOrder.getId()); + if (thinkMachineOpenLog != null) { + return fail("该订单已使用不可退"); + } if (thinkOrder.getOrderStatus().equals(1)) { return fail("该订单已使用不可退"); } @@ -158,9 +178,12 @@ public class ThinkOrderRefundLogController extends BaseController { thinkOrderService.updateById(thinkOrder); if (thinkOrder.getPayType().equals(1)) { if (thinkOrder.getWechatOrder() != null - && !thinkOrder.getWechatOrder().isEmpty() && thinkOrder.getWechatOrder().contains("420000")) - thinkOrderService.refund(thinkOrderRefundLog); - else { + && !thinkOrder.getWechatOrder().isEmpty() && ( + thinkOrder.getWechatOrder().contains("420000") || thinkOrder.getWechatOrder().contains("450000") + )) { + Refund refundRes = thinkOrderService.refund(thinkOrderRefundLog); + System.out.println("refund req res: " + refundRes.toString()); + } else { for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) { thinkOrderInfo.setPayStatus(0); @@ -170,6 +193,36 @@ public class ThinkOrderRefundLogController extends BaseController { thinkOrder.setOrderStatus(3); thinkOrderService.updateById(thinkOrder); } + } else if (thinkOrder.getPayType().equals(19)) { + for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) { + thinkOrderInfo.setPayStatus(0); + redisUtil.delete(thinkOrderInfo.getStartTime().toString() + thinkOrderInfo.getFid().toString()); + } + thinkOrderInfoService.updateBatchById(thinkOrderInfoList); + thinkOrder.setOrderStatus(3); + thinkOrderService.updateById(thinkOrder); + + User user = userService.getByUidInner(thinkOrder.getUid()); + if (user != null) { + BigDecimal currentBalance = user.getBalance() == null ? BigDecimal.ZERO : user.getBalance(); + BigDecimal latestBalance = currentBalance.add(thinkOrder.getTotalPrice()); + user.setBalance(latestBalance); + userService.updateInner(user); + + UserBalanceLog userBalanceLog = new UserBalanceLog(); + userBalanceLog.setUserId(user.getUserId()); + userBalanceLog.setScene(3); + userBalanceLog.setMoney(thinkOrder.getTotalPrice()); + userBalanceLog.setBalance(latestBalance); + userBalanceLog.setRemark("订单退款"); + userBalanceLog.setComments("退款订单号:" + thinkOrder.getOrderNum()); + userBalanceLog.setStatus(0); + userBalanceLog.setDeleted(0); + userBalanceLog.setTenantId(10150); + userBalanceLog.setCreateTime(LocalDateTime.now()); + userBalanceLog.setUpdateTime(LocalDateTime.now()); + userBalanceLogService.save(userBalanceLog); + } } else { int num = 0; for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) { @@ -179,6 +232,7 @@ public class ThinkOrderRefundLogController extends BaseController { } thinkOrderInfoService.updateBatchById(thinkOrderInfoList); thinkOrder.setOrderStatus(6); + thinkOrder.setRefundBy(1); thinkOrder.setRefundTime((int) (System.currentTimeMillis() / 1000)); thinkOrderService.updateById(thinkOrder); if (thinkOrder.getVid() != null && thinkOrder.getVid() != 0) { diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkSiteController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkSiteController.java index a13b8b8..1b677ed 100644 --- a/src/main/java/com/gxwebsoft/think/controller/ThinkSiteController.java +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkSiteController.java @@ -49,6 +49,7 @@ public class ThinkSiteController extends BaseController { param.setIdList(Arrays.stream(param.getIds().split(",")).map(Integer::parseInt).toList()); } if (getLoginUser() != null && param.getIsAdmin() != null) param.setLoginUser(getLoginUser()); + if (param.getIsAdmin() == null) param.setIsOn(1); // 使用关联查询 return success(thinkSiteService.listRel(param)); } diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkSiteTimeController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkSiteTimeController.java index b59be5f..eea4aa7 100644 --- a/src/main/java/com/gxwebsoft/think/controller/ThinkSiteTimeController.java +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkSiteTimeController.java @@ -56,6 +56,11 @@ public class ThinkSiteTimeController extends BaseController { .eq(ThinkSiteTime::getIsStatus, 1) .orderByAsc(ThinkSiteTime::getSort) ); + for (ThinkSiteTime thinkSiteTime : list) { + thinkSiteTime.setPriceOrigin(thinkSiteTime.getPrice()); + thinkSiteTime.setHalfPriceOrigin(thinkSiteTime.getHalfPrice()); + + } return success(list); } diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkSmallRechargeController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkSmallRechargeController.java new file mode 100644 index 0000000..ea0ebb7 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkSmallRechargeController.java @@ -0,0 +1,204 @@ +package com.gxwebsoft.think.controller; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.RandomUtil; +import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.think.entity.*; +import com.gxwebsoft.think.service.*; +import com.gxwebsoft.think.param.ThinkSmallRechargeParam; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.common.core.web.PageParam; +import com.gxwebsoft.common.core.web.BatchParam; +import com.gxwebsoft.common.core.annotation.OperationLog; +import com.gxwebsoft.common.system.entity.User; +import com.wechat.pay.java.core.notification.NotificationConfig; +import com.wechat.pay.java.core.notification.NotificationParser; +import com.wechat.pay.java.core.notification.RequestParam; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 控制器 + * + * @author 科技小王子 + * @since 2026-01-07 21:24:29 + */ +@Api(tags = "管理") +@RestController +@RequestMapping("/api/think/think-small-recharge") +public class ThinkSmallRechargeController extends BaseController { + @Resource + private ThinkSmallRechargeService thinkSmallRechargeService; + @Resource + private WechatConfigService wechatConfigService; + @Resource + private ThinkUsersVipService thinkUsersVipService; + @Resource + private ThinkCardService thinkCardService; + @Resource + private ThinkCardBalanceService thinkCardBalanceService; + @Resource + private ThinkOrderService thinkOrderService; + + @ApiOperation("分页查询") + @GetMapping("/page") + public ApiResult> page(ThinkSmallRechargeParam param) { + // 使用关联查询 + return success(thinkSmallRechargeService.pageRel(param)); + } + + @ApiOperation("查询全部") + @GetMapping() + public ApiResult> list(ThinkSmallRechargeParam param) { + // 使用关联查询 + return success(thinkSmallRechargeService.listRel(param)); + } + + @ApiOperation("根据id查询") + @GetMapping("/{id}") + public ApiResult get(@PathVariable("id") Integer id) { + // 使用关联查询 + return success(thinkSmallRechargeService.getByIdRel(id)); + } + + @ApiOperation("添加") + @PostMapping() + public ApiResult save(@RequestBody ThinkSmallRecharge thinkSmallRecharge) { + if (thinkSmallRecharge.getCid() != null && thinkSmallRecharge.getCid() > 0) { + ThinkSmallRecharge check = thinkSmallRechargeService.checkByCid(thinkSmallRecharge.getCid()); + if (check != null) return fail("该会员卡已充值"); + } + if (thinkSmallRecharge.getVid() != null && thinkSmallRecharge.getVid() > 0) { + ThinkSmallRecharge check = thinkSmallRechargeService.checkByVid(thinkSmallRecharge.getVid()); + if (check != null) return fail("该会员卡已充值"); + } + thinkSmallRecharge.setUid(getLoginUserId()); + thinkSmallRecharge.setCreateTime(DateUtil.currentSeconds()); + thinkSmallRecharge.setUpdateTime(DateUtil.currentSeconds()); + thinkSmallRecharge.setUid(getLoginUserId()); + thinkSmallRecharge.setOrderNo(LocalDateTimeUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss") + RandomUtil.randomNumbers(5)); + if (thinkSmallRechargeService.save(thinkSmallRecharge)) { + if (thinkSmallRecharge.getPayType() == null || thinkSmallRecharge.getPayType() == 0) { + String notify = "https://gxtyzx-api2.websoft.top/api/think/think-small-recharge/notify"; + return success("下单成功", thinkOrderService.createWxOrder(thinkSmallRecharge.getAmount(), thinkSmallRecharge.getOrderNo(), + "会员卡小额充值", getLoginUser().getOpenid(), notify)); + }else { + doCharge(thinkSmallRecharge); + return success("操作成功"); + } + } + return fail("添加失败"); + } + + @ApiOperation("修改") + @PutMapping() + public ApiResult update(@RequestBody ThinkSmallRecharge thinkSmallRecharge) { + if (thinkSmallRechargeService.updateById(thinkSmallRecharge)) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @ApiOperation("删除") + @DeleteMapping("/{id}") + public ApiResult remove(@PathVariable("id") Integer id) { + if (thinkSmallRechargeService.removeById(id)) { + return success("删除成功"); + } + return fail("删除失败"); + } + + @ApiOperation("批量添加") + @PostMapping("/batch") + public ApiResult saveBatch(@RequestBody List list) { + if (thinkSmallRechargeService.saveBatch(list)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @ApiOperation("批量修改") + @PutMapping("/batch") + public ApiResult removeBatch(@RequestBody BatchParam batchParam) { + if (batchParam.update(thinkSmallRechargeService, "id")) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @ApiOperation("批量删除") + @DeleteMapping("/batch") + public ApiResult removeBatch(@RequestBody List ids) { + if (thinkSmallRechargeService.removeByIds(ids)) { + return success("删除成功"); + } + return fail("删除失败"); + } + + @ApiOperation("微信通知") + @PostMapping("/notify") + public String notify(@RequestBody String body, @RequestHeader Map header) { + System.out.println("小额冲卡支付通知 >>>>> "); + com.wechat.pay.java.core.notification.RequestParam requestParam = new RequestParam.Builder() + .serialNumber(header.get("wechatpay-serial").toString()) + .nonce(header.get("wechatpay-nonce").toString()) + .signature(header.get("wechatpay-signature").toString()) + .timestamp(header.get("wechatpay-timestamp").toString()) + .body(body) + .build(); + NotificationConfig config = wechatConfigService.getNotificationConfig(); + NotificationParser parser = new NotificationParser(config); + com.wechat.pay.java.service.payments.model.Transaction transaction = parser.parse(requestParam, com.wechat.pay.java.service.payments.model.Transaction.class); + ThinkSmallRecharge thinkSmallRecharge = thinkSmallRechargeService.getByOrderNo(transaction.getOutTradeNo()); + if (thinkSmallRecharge != null && thinkSmallRecharge.getStatus() == 0) { + doCharge(thinkSmallRecharge); + } + return "订单已支付"; + } + + private void doCharge(ThinkSmallRecharge thinkSmallRecharge){ + thinkSmallRecharge.setStatus(1); + thinkSmallRecharge.setUpdateTime(DateUtil.currentSeconds()); + thinkSmallRechargeService.updateById(thinkSmallRecharge); + + if (thinkSmallRecharge.getVid() != null && thinkSmallRecharge.getVid() > 0) { + ThinkUsersVip thinkUsersVip = thinkUsersVipService.getById(thinkSmallRecharge.getVid()); + if (thinkUsersVip != null) { + thinkUsersVip.setRemainingMoney(thinkUsersVip.getRemainingMoney().add(thinkSmallRecharge.getAmount())); + thinkUsersVipService.updateById(thinkUsersVip); + + ThinkCardBalance thinkCardBalance = thinkCardBalanceService.getByVid(thinkSmallRecharge.getVid()); + if (thinkCardBalance != null) { + thinkCardBalance.setBalance(thinkUsersVip.getRemainingMoney()); + thinkCardBalanceService.updateById(thinkCardBalance); + } + } + } + + if (thinkSmallRecharge.getCid() != null && thinkSmallRecharge.getCid() > 0) { + ThinkCard thinkCard = thinkCardService.getById(thinkSmallRecharge.getCid()); + if (thinkCard != null) { + thinkCard.setRemainingMoney(thinkCard.getRemainingMoney().add(thinkSmallRecharge.getAmount())); + thinkCardService.updateById(thinkCard); + ThinkCardBalance thinkCardBalance = thinkCardBalanceService.getByCid(thinkSmallRecharge.getCid()); + if (thinkCardBalance != null) { + thinkCardBalance.setBalance(thinkCard.getRemainingMoney()); + thinkCardBalanceService.updateById(thinkCardBalance); + } + } + } + } +} diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkTrainingInstitutionController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkTrainingInstitutionController.java new file mode 100644 index 0000000..cbaf40b --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkTrainingInstitutionController.java @@ -0,0 +1,110 @@ +package com.gxwebsoft.think.controller; + +import cn.hutool.core.date.DateUtil; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.common.core.web.BatchParam; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.think.entity.ThinkTrainingInstitution; +import com.gxwebsoft.think.param.ThinkTrainingInstitutionParam; +import com.gxwebsoft.think.service.ThinkTrainingInstitutionService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 培训机构管理 + * + * @author Codex + * @since 2026-04-16 + */ +@Api(tags = "培训机构管理") +@RestController +@RequestMapping("/api/think/think-training-institution") +public class ThinkTrainingInstitutionController extends BaseController { + @Resource + private ThinkTrainingInstitutionService thinkTrainingInstitutionService; + + @ApiOperation("分页查询") + @GetMapping("/page") + public ApiResult> page(ThinkTrainingInstitutionParam param) { + return success(thinkTrainingInstitutionService.pageRel(param)); + } + + @ApiOperation("查询全部") + @GetMapping() + public ApiResult> list(ThinkTrainingInstitutionParam param) { + return success(thinkTrainingInstitutionService.listRel(param)); + } + + @ApiOperation("根据id查询") + @GetMapping("/{id}") + public ApiResult get(@PathVariable("id") Integer id) { + return success(thinkTrainingInstitutionService.getByIdRel(id)); + } + + @ApiOperation("添加") + @PostMapping() + public ApiResult save(@RequestBody ThinkTrainingInstitution thinkTrainingInstitution) { + thinkTrainingInstitution.setCreateTime((int) DateUtil.currentSeconds()); + thinkTrainingInstitution.setUpdateTime((int) DateUtil.currentSeconds()); + if (thinkTrainingInstitutionService.save(thinkTrainingInstitution)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @ApiOperation("修改") + @PutMapping() + public ApiResult update(@RequestBody ThinkTrainingInstitution thinkTrainingInstitution) { + thinkTrainingInstitution.setUpdateTime((int) DateUtil.currentSeconds()); + if (thinkTrainingInstitutionService.updateById(thinkTrainingInstitution)) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @ApiOperation("删除") + @DeleteMapping("/{id}") + public ApiResult remove(@PathVariable("id") Integer id) { + if (thinkTrainingInstitutionService.removeById(id)) { + return success("删除成功"); + } + return fail("删除失败"); + } + + @ApiOperation("批量添加") + @PostMapping("/batch") + public ApiResult saveBatch(@RequestBody List list) { + int now = (int) DateUtil.currentSeconds(); + for (ThinkTrainingInstitution item : list) { + item.setCreateTime(now); + item.setUpdateTime(now); + } + if (thinkTrainingInstitutionService.saveBatch(list)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @ApiOperation("批量修改") + @PutMapping("/batch") + public ApiResult removeBatch(@RequestBody BatchParam batchParam) { + if (batchParam.update(thinkTrainingInstitutionService, "id")) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @ApiOperation("批量删除") + @DeleteMapping("/batch") + public ApiResult removeBatch(@RequestBody List ids) { + if (thinkTrainingInstitutionService.removeByIds(ids)) { + return success("删除成功"); + } + return fail("删除失败"); + } +} diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkUserInAccessController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkUserInAccessController.java new file mode 100644 index 0000000..72ca4fa --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkUserInAccessController.java @@ -0,0 +1,112 @@ +package com.gxwebsoft.think.controller; + +import cn.hutool.core.date.DateUtil; +import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.think.service.ThinkUserInAccessService; +import com.gxwebsoft.think.entity.ThinkUserInAccess; +import com.gxwebsoft.think.param.ThinkUserInAccessParam; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.common.core.web.PageParam; +import com.gxwebsoft.common.core.web.BatchParam; +import com.gxwebsoft.common.core.annotation.OperationLog; +import com.gxwebsoft.common.system.entity.User; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 能刷脸开闸的用户列表控制器 + * + * @author 科技小王子 + * @since 2026-03-13 02:27:34 + */ +@Api(tags = "能刷脸开闸的用户列表管理") +@RestController +@RequestMapping("/api/think/think-user-in-access") +public class ThinkUserInAccessController extends BaseController { + @Resource + private ThinkUserInAccessService thinkUserInAccessService; + + @ApiOperation("分页查询能刷脸开闸的用户列表") + @GetMapping("/page") + public ApiResult> page(ThinkUserInAccessParam param) { + // 使用关联查询 + return success(thinkUserInAccessService.pageRel(param)); + } + + @ApiOperation("查询全部能刷脸开闸的用户列表") + @GetMapping() + public ApiResult> list(ThinkUserInAccessParam param) { + // 使用关联查询 + return success(thinkUserInAccessService.listRel(param)); + } + + @PreAuthorize("hasAuthority('think:thinkUserInAccess:list')") + @ApiOperation("根据id查询能刷脸开闸的用户列表") + @GetMapping("/{id}") + public ApiResult get(@PathVariable("id") Integer id) { + // 使用关联查询 + return success(thinkUserInAccessService.getByIdRel(id)); + } + + @ApiOperation("添加能刷脸开闸的用户列表") + @PostMapping() + public ApiResult save(@RequestBody ThinkUserInAccess thinkUserInAccess) { + thinkUserInAccess.setCreateTime(DateUtil.currentSeconds()); + if (thinkUserInAccessService.save(thinkUserInAccess)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @ApiOperation("修改能刷脸开闸的用户列表") + @PutMapping() + public ApiResult update(@RequestBody ThinkUserInAccess thinkUserInAccess) { + if (thinkUserInAccessService.updateById(thinkUserInAccess)) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @ApiOperation("删除能刷脸开闸的用户列表") + @DeleteMapping("/{id}") + public ApiResult remove(@PathVariable("id") Integer id) { + if (thinkUserInAccessService.removeById(id)) { + return success("删除成功"); + } + return fail("删除失败"); + } + + @ApiOperation("批量添加能刷脸开闸的用户列表") + @PostMapping("/batch") + public ApiResult saveBatch(@RequestBody List list) { + if (thinkUserInAccessService.saveBatch(list)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @ApiOperation("批量修改能刷脸开闸的用户列表") + @PutMapping("/batch") + public ApiResult removeBatch(@RequestBody BatchParam batchParam) { + if (batchParam.update(thinkUserInAccessService, "id")) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @ApiOperation("批量删除能刷脸开闸的用户列表") + @DeleteMapping("/batch") + public ApiResult removeBatch(@RequestBody List ids) { + if (thinkUserInAccessService.removeByIds(ids)) { + return success("删除成功"); + } + return fail("删除失败"); + } + +} diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkUsersBlackController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkUsersBlackController.java new file mode 100644 index 0000000..16efa98 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkUsersBlackController.java @@ -0,0 +1,113 @@ +package com.gxwebsoft.think.controller; + +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.common.core.web.BatchParam; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.think.entity.ThinkUsersBlack; +import com.gxwebsoft.think.param.ThinkUsersBlackParam; +import com.gxwebsoft.think.service.ThinkUsersBlackService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 用户黑名单控制器 + * + * @author Codex + * @since 2026-06-04 + */ +@Api(tags = "用户黑名单管理") +@RestController +@RequestMapping("/api/think/think-users-black") +public class ThinkUsersBlackController extends BaseController { + @Resource + private ThinkUsersBlackService thinkUsersBlackService; + + @ApiOperation("分页查询用户黑名单") + @GetMapping("/page") + public ApiResult> page(ThinkUsersBlackParam param) { + return success(thinkUsersBlackService.pageRel(param)); + } + + @ApiOperation("查询全部用户黑名单") + @GetMapping() + public ApiResult> list(ThinkUsersBlackParam param) { + return success(thinkUsersBlackService.listRel(param)); + } + + @PreAuthorize("hasAuthority('think:thinkUsersBlack:list')") + @ApiOperation("根据id查询用户黑名单") + @GetMapping("/{id}") + public ApiResult get(@PathVariable("id") Integer id) { + return success(thinkUsersBlackService.getByIdRel(id)); + } + + @ApiOperation("添加用户黑名单") + @PostMapping() + public ApiResult save(@RequestBody ThinkUsersBlack thinkUsersBlack) { + if (thinkUsersBlack.getCreateTime() == null) { + thinkUsersBlack.setCreateTime(LocalDateTime.now()); + } + if (thinkUsersBlackService.save(thinkUsersBlack)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @ApiOperation("修改用户黑名单") + @PutMapping() + public ApiResult update(@RequestBody ThinkUsersBlack thinkUsersBlack) { + if (thinkUsersBlackService.updateById(thinkUsersBlack)) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @ApiOperation("删除用户黑名单") + @DeleteMapping("/{id}") + public ApiResult remove(@PathVariable("id") Integer id) { + if (thinkUsersBlackService.removeById(id)) { + return success("删除成功"); + } + return fail("删除失败"); + } + + @ApiOperation("批量添加用户黑名单") + @PostMapping("/batch") + public ApiResult saveBatch(@RequestBody List list) { + LocalDateTime now = LocalDateTime.now(); + for (ThinkUsersBlack item : list) { + if (item.getCreateTime() == null) { + item.setCreateTime(now); + } + } + if (thinkUsersBlackService.saveBatch(list)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @ApiOperation("批量修改用户黑名单") + @PutMapping("/batch") + public ApiResult removeBatch(@RequestBody BatchParam batchParam) { + if (batchParam.update(thinkUsersBlackService, "id")) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @ApiOperation("批量删除用户黑名单") + @DeleteMapping("/batch") + public ApiResult removeBatch(@RequestBody List ids) { + if (thinkUsersBlackService.removeByIds(ids)) { + return success("删除成功"); + } + return fail("删除失败"); + } +} diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkUsersController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkUsersController.java index 13786de..88f0506 100644 --- a/src/main/java/com/gxwebsoft/think/controller/ThinkUsersController.java +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkUsersController.java @@ -69,6 +69,15 @@ public class ThinkUsersController extends BaseController { return success(thinkUsersService.getByIdRel(id)); } + @PostMapping("/setHasFace") + public ApiResult setHasFace(@RequestBody ThinkUsers thinkUsers) { + ThinkUsers thinkUser = thinkUsersService.getById(getLoginUser().getUid()); + thinkUser.setHasFace(1); + thinkUser.setPersonPhoto(thinkUsers.getPersonPhoto()); + thinkUsersService.updateById(thinkUser); + return success(); + } + @ApiOperation("添加") @PostMapping() public ApiResult save(@RequestBody ThinkUsers thinkUsers, HttpServletRequest request) { @@ -76,7 +85,7 @@ public class ThinkUsersController extends BaseController { RequestUtil requestUtil = new RequestUtil(); requestUtil.setAccessToken(JwtUtil.getAccessToken(request)); requestUtil.setTenantId(getTenantId().toString()); - System.out.println("check:" + check); +// System.out.println("check:" + check); if (check != null) { User user = new User(); user.setUserId(thinkUsers.getUserId()); diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkUsersVipController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkUsersVipController.java index f01e450..6c5d705 100644 --- a/src/main/java/com/gxwebsoft/think/controller/ThinkUsersVipController.java +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkUsersVipController.java @@ -36,6 +36,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDateTime; import java.util.*; +import java.util.concurrent.TimeUnit; /** * 控制器 @@ -363,7 +364,7 @@ public class ThinkUsersVipController extends BaseController { @PutMapping() public ApiResult update(@RequestBody ThinkUsersVip thinkUsersVip) { if (thinkUsersVipService.updateById(thinkUsersVip)) { - if (thinkUsersVip.getUid().equals(0)) { + if (thinkUsersVip.getUid() != null && thinkUsersVip.getUid().equals(0)) { thinkVipCardsBillsService.clearUid(thinkUsersVip.getId()); } return success("修改成功"); @@ -371,6 +372,35 @@ public class ThinkUsersVipController extends BaseController { return fail("修改失败"); } + /** 管理端单独修改会员卡剩余金额或剩余次数,避免覆盖其他字段。 */ + @ApiOperation("修改剩余金额/次数") + @PreAuthorize("hasAuthority('think:thinkUsersVip:changeRemain')") + @PutMapping("/remaining") + public ApiResult updateRemaining(@RequestBody ThinkUsersVip thinkUsersVip) { + if (thinkUsersVip.getId() == null) return fail("会员卡ID不能为空"); + if (thinkUsersVip.getNum() == null && thinkUsersVip.getRemainingMoney() == null) { + return fail("剩余金额或剩余次数不能为空"); + } + if (thinkUsersVip.getNum() != null && thinkUsersVip.getNum() < 0) { + return fail("剩余次数不能为负数"); + } + if (thinkUsersVip.getRemainingMoney() != null + && thinkUsersVip.getRemainingMoney().compareTo(BigDecimal.ZERO) < 0) { + return fail("剩余金额不能为负数"); + } + if (thinkUsersVipService.getById(thinkUsersVip.getId()) == null) { + return fail("会员卡不存在"); + } + + ThinkUsersVip update = new ThinkUsersVip(); + update.setId(thinkUsersVip.getId()); + update.setNum(thinkUsersVip.getNum()); + update.setRemainingMoney(thinkUsersVip.getRemainingMoney()); + return thinkUsersVipService.updateById(update) + ? success("修改成功") + : fail("修改失败"); + } + @ApiOperation("删除") @DeleteMapping("/{id}") public ApiResult remove(@PathVariable("id") Integer id) { diff --git a/src/main/java/com/gxwebsoft/think/controller/ThinkVipController.java b/src/main/java/com/gxwebsoft/think/controller/ThinkVipController.java index 64c6026..67e7ec8 100644 --- a/src/main/java/com/gxwebsoft/think/controller/ThinkVipController.java +++ b/src/main/java/com/gxwebsoft/think/controller/ThinkVipController.java @@ -4,8 +4,14 @@ import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.core.web.BatchParam; import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.think.entity.ThinkCard; +import com.gxwebsoft.think.entity.ThinkTrainingInstitution; +import com.gxwebsoft.think.entity.ThinkUsersVip; import com.gxwebsoft.think.entity.ThinkVip; import com.gxwebsoft.think.param.ThinkVipParam; +import com.gxwebsoft.think.service.ThinkCardService; +import com.gxwebsoft.think.service.ThinkTrainingInstitutionService; +import com.gxwebsoft.think.service.ThinkUsersVipService; import com.gxwebsoft.think.service.ThinkVipService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -13,6 +19,7 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.util.ArrayList; import java.util.List; /** @@ -27,6 +34,12 @@ import java.util.List; public class ThinkVipController extends BaseController { @Resource private ThinkVipService thinkVipService; + @Resource + private ThinkCardService thinkCardService; + @Resource + private ThinkUsersVipService thinkUsersVipService; + @Resource + private ThinkTrainingInstitutionService thinkTrainingInstitutionService; @PostMapping("/list-by-group") public ApiResult listByGroup(@RequestBody ThinkVipParam param) { @@ -64,8 +77,20 @@ public class ThinkVipController extends BaseController { @ApiOperation("添加") @PostMapping() public ApiResult save(@RequestBody ThinkVip thinkVip) { - thinkVip.setCreateTime((int) (System.currentTimeMillis()/1000)); - thinkVip.setUpdateTime((int) (System.currentTimeMillis()/1000)); + if (thinkVip.getVipType() != null && thinkVip.getVipType().equals(3)) { + if (thinkVip.getTrainingInstitutionId() == null) { + return fail("培训卡必须选择培训机构"); + } + ThinkTrainingInstitution trainingInstitution = + thinkTrainingInstitutionService.getById(thinkVip.getTrainingInstitutionId()); + if (trainingInstitution == null) { + return fail("培训机构不存在"); + } + } else { + thinkVip.setTrainingInstitutionId(null); + } + thinkVip.setCreateTime((int) (System.currentTimeMillis() / 1000)); + thinkVip.setUpdateTime((int) (System.currentTimeMillis() / 1000)); if (thinkVipService.save(thinkVip)) { return success("添加成功"); } @@ -75,7 +100,52 @@ public class ThinkVipController extends BaseController { @ApiOperation("修改") @PutMapping() public ApiResult update(@RequestBody ThinkVip thinkVip) { + if (thinkVip.getVipType() != null && thinkVip.getVipType().equals(3)) { + if (thinkVip.getTrainingInstitutionId() == null) { + return fail("培训卡必须选择培训机构"); + } + ThinkTrainingInstitution trainingInstitution = + thinkTrainingInstitutionService.getById(thinkVip.getTrainingInstitutionId()); + if (trainingInstitution == null) { + return fail("培训机构不存在"); + } + } else if (thinkVip.getVipType() != null) { + thinkVip.setTrainingInstitutionId(null); + } if (thinkVipService.updateById(thinkVip)) { + List thinkCardList = thinkCardService.listByVidList(new ArrayList<>() {{ + add(thinkVip.getId()); + }}); + if (!thinkCardList.isEmpty()) { + for (ThinkCard thinkCard : thinkCardList) { + thinkCard.setSid(thinkVip.getSid()); + thinkCard.setName(thinkVip.getName()); + thinkCard.setInfo(thinkVip.getInfo()); + thinkCard.setDesc(thinkVip.getDesc()); + thinkCard.setUpdateTime(System.currentTimeMillis() / 1000); +// if (thinkVip.getMode() == 1 && thinkVip.getExpiredTime() != null) { +// // 固定时间 +// thinkUsersVipService.updateByCardId(thinkCard); +// } + } + thinkCardService.updateBatchById(thinkCardList); + } + List thinkUsersVipList = thinkUsersVipService.listByVipIds(new ArrayList<>() {{ + add(thinkVip.getId()); + }}); + if (!thinkUsersVipList.isEmpty()) { + for (ThinkUsersVip thinkUsersVip : thinkUsersVipList) { + thinkUsersVip.setSid(thinkVip.getSid()); + thinkUsersVip.setName(thinkVip.getName()); + thinkUsersVip.setInfo(thinkVip.getInfo()); + thinkUsersVip.setDesc(thinkVip.getDesc()); +// if (thinkVip.getMode() == 1 && thinkVip.getExpiredTime() != null) { +// // 固定时间 +// thinkUsersVipService.updateByCardId(thinkCard); +// } + } + thinkUsersVipService.updateBatchById(thinkUsersVipList); + } return success("修改成功"); } return fail("修改失败"); diff --git a/src/main/java/com/gxwebsoft/think/entity/ThinkCardLog.java b/src/main/java/com/gxwebsoft/think/entity/ThinkCardLog.java index 62b6c82..bb78512 100644 --- a/src/main/java/com/gxwebsoft/think/entity/ThinkCardLog.java +++ b/src/main/java/com/gxwebsoft/think/entity/ThinkCardLog.java @@ -90,4 +90,6 @@ public class ThinkCardLog implements Serializable { @TableField(exist = false) private List payTypeList; + @TableField(exist = false) + private Integer vid; } diff --git a/src/main/java/com/gxwebsoft/think/entity/ThinkMachineOpenLog.java b/src/main/java/com/gxwebsoft/think/entity/ThinkMachineOpenLog.java index ff0e7fc..c4d424a 100644 --- a/src/main/java/com/gxwebsoft/think/entity/ThinkMachineOpenLog.java +++ b/src/main/java/com/gxwebsoft/think/entity/ThinkMachineOpenLog.java @@ -49,4 +49,8 @@ public class ThinkMachineOpenLog implements Serializable { @TableField(exist = false) private String qrcode; + +// private String qrCode; + + private Integer logId; } diff --git a/src/main/java/com/gxwebsoft/think/entity/ThinkRechargeLog.java b/src/main/java/com/gxwebsoft/think/entity/ThinkRechargeLog.java index 5124723..393de5c 100644 --- a/src/main/java/com/gxwebsoft/think/entity/ThinkRechargeLog.java +++ b/src/main/java/com/gxwebsoft/think/entity/ThinkRechargeLog.java @@ -104,4 +104,10 @@ public class ThinkRechargeLog implements Serializable { @TableField(exist = false) private ThinkUsersVip thinkUsersVip; + + @TableField(exist = false) + private String name; + + @TableField(exist = false) + private Integer vipId; } diff --git a/src/main/java/com/gxwebsoft/think/entity/ThinkSite.java b/src/main/java/com/gxwebsoft/think/entity/ThinkSite.java index d5ab555..fbabd59 100644 --- a/src/main/java/com/gxwebsoft/think/entity/ThinkSite.java +++ b/src/main/java/com/gxwebsoft/think/entity/ThinkSite.java @@ -106,6 +106,8 @@ public class ThinkSite implements Serializable { private String machineCode; + private Integer isOn; + @TableField(exist = false) private BigDecimal distance; diff --git a/src/main/java/com/gxwebsoft/think/entity/ThinkSiteTime.java b/src/main/java/com/gxwebsoft/think/entity/ThinkSiteTime.java index 8c59c88..bb14c31 100644 --- a/src/main/java/com/gxwebsoft/think/entity/ThinkSiteTime.java +++ b/src/main/java/com/gxwebsoft/think/entity/ThinkSiteTime.java @@ -1,6 +1,7 @@ package com.gxwebsoft.think.entity; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -31,12 +32,18 @@ public class ThinkSiteTime implements Serializable { @ApiModelProperty(value = "价格") private BigDecimal price; + @TableField(exist = false) + private BigDecimal priceOrigin; + @ApiModelProperty(value = "每日不同价格") private String prices; @ApiModelProperty(value = "半场价格") private BigDecimal halfPrice; + @TableField(exist = false) + private BigDecimal halfPriceOrigin; + @ApiModelProperty(value = "每日不同半场价格") private String halfPrices; diff --git a/src/main/java/com/gxwebsoft/think/entity/ThinkSmallRecharge.java b/src/main/java/com/gxwebsoft/think/entity/ThinkSmallRecharge.java new file mode 100644 index 0000000..74bdf66 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/entity/ThinkSmallRecharge.java @@ -0,0 +1,54 @@ +package com.gxwebsoft.think.entity; + +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * + * + * @author 科技小王子 + * @since 2026-01-07 21:24:29 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "ThinkSmallRecharge对象", description = "") +public class ThinkSmallRecharge implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + private Integer cid; + + private Integer vid; + + private Integer uid; + + private Integer payType; + + private Integer status; + + private String orderNo; + + private String payVoucher; + + private BigDecimal amount; + + @ApiModelProperty(value = "下单时间") + private Long createTime; + + private Long updateTime; + + @TableField(exist = false) + private ThinkUsersVip usersVip; + + @TableField(exist = false) + private ThinkCard card; +} diff --git a/src/main/java/com/gxwebsoft/think/entity/ThinkTrainingInstitution.java b/src/main/java/com/gxwebsoft/think/entity/ThinkTrainingInstitution.java new file mode 100644 index 0000000..d186006 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/entity/ThinkTrainingInstitution.java @@ -0,0 +1,41 @@ +package com.gxwebsoft.think.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + * 培训机构 + * + * @author Codex + * @since 2026-04-16 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "ThinkTrainingInstitution对象", description = "培训机构") +public class ThinkTrainingInstitution implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty(value = "机构名称") + private String name; + + @ApiModelProperty(value = "联系人") + private String contactName; + + @ApiModelProperty(value = "联系方式") + private String contactPhone; + + @ApiModelProperty(value = "创建时间") + private Integer createTime; + + @ApiModelProperty(value = "更新时间") + private Integer updateTime; +} diff --git a/src/main/java/com/gxwebsoft/think/entity/ThinkUserInAccess.java b/src/main/java/com/gxwebsoft/think/entity/ThinkUserInAccess.java new file mode 100644 index 0000000..6634ab5 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/entity/ThinkUserInAccess.java @@ -0,0 +1,30 @@ +package com.gxwebsoft.think.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 能刷脸开闸的用户列表 + * + * @author 科技小王子 + * @since 2026-03-13 02:27:34 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "ThinkUserInAccess对象", description = "能刷脸开闸的用户列表") +public class ThinkUserInAccess implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + private Integer uid; + + private Long createTime; + +} diff --git a/src/main/java/com/gxwebsoft/think/entity/ThinkUsers.java b/src/main/java/com/gxwebsoft/think/entity/ThinkUsers.java index f31bdfe..11110fc 100644 --- a/src/main/java/com/gxwebsoft/think/entity/ThinkUsers.java +++ b/src/main/java/com/gxwebsoft/think/entity/ThinkUsers.java @@ -63,6 +63,10 @@ public class ThinkUsers implements Serializable { @ApiModelProperty(value = "注册时间") private Integer createTime; + private Integer hasFace; + + private String personPhoto; + private String idcard; private String truename; @@ -76,4 +80,7 @@ public class ThinkUsers implements Serializable { @TableField(exist = false) private Integer userId; + + @TableField(exist = false) + private BigDecimal balance; } diff --git a/src/main/java/com/gxwebsoft/think/entity/ThinkUsersBlack.java b/src/main/java/com/gxwebsoft/think/entity/ThinkUsersBlack.java new file mode 100644 index 0000000..ae33f45 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/entity/ThinkUsersBlack.java @@ -0,0 +1,51 @@ +package com.gxwebsoft.think.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 用户黑名单 + * + * @author Codex + * @since 2026-06-04 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "ThinkUsersBlack对象", description = "用户黑名单") +public class ThinkUsersBlack implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @ApiModelProperty(value = "用户ID") + private Integer uid; + + @ApiModelProperty(value = "状态:1,正常;2,禁用") + private Integer status; + + @ApiModelProperty(value = "失效时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime expireTime; + + @ApiModelProperty(value = "添加时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + @TableField(exist = false) + @ApiModelProperty(value = "姓名") + private String truename; + + @TableField(exist = false) + @ApiModelProperty(value = "手机号") + private String phone; +} diff --git a/src/main/java/com/gxwebsoft/think/entity/ThinkVip.java b/src/main/java/com/gxwebsoft/think/entity/ThinkVip.java index 383c31c..a567ad9 100644 --- a/src/main/java/com/gxwebsoft/think/entity/ThinkVip.java +++ b/src/main/java/com/gxwebsoft/think/entity/ThinkVip.java @@ -83,6 +83,9 @@ public class ThinkVip implements Serializable { @ApiModelProperty(value = "vip卡等级类型:1特殊vip卡,2普通vip卡") private Integer vipType; + @ApiModelProperty(value = "培训机构ID") + private Integer trainingInstitutionId; + @ApiModelProperty(value = "特殊卡开发凭证图") private String pic; @@ -110,6 +113,10 @@ public class ThinkVip implements Serializable { @TableField(exist = false) private String siteNames; + @ApiModelProperty(value = "培训机构名称") + @TableField(exist = false) + private String trainingInstitutionName; + @TableField(exist = false) private List cardList; diff --git a/src/main/java/com/gxwebsoft/think/mapper/ThinkSmallRechargeMapper.java b/src/main/java/com/gxwebsoft/think/mapper/ThinkSmallRechargeMapper.java new file mode 100644 index 0000000..1434ea6 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/mapper/ThinkSmallRechargeMapper.java @@ -0,0 +1,37 @@ +package com.gxwebsoft.think.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.gxwebsoft.think.entity.ThinkSmallRecharge; +import com.gxwebsoft.think.param.ThinkSmallRechargeParam; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * Mapper + * + * @author 科技小王子 + * @since 2026-01-07 21:24:29 + */ +public interface ThinkSmallRechargeMapper extends BaseMapper { + + /** + * 分页查询 + * + * @param page 分页对象 + * @param param 查询参数 + * @return List + */ + List selectPageRel(@Param("page") IPage page, + @Param("param") ThinkSmallRechargeParam param); + + /** + * 查询全部 + * + * @param param 查询参数 + * @return List + */ + List selectListRel(@Param("param") ThinkSmallRechargeParam param); + +} diff --git a/src/main/java/com/gxwebsoft/think/mapper/ThinkTrainingInstitutionMapper.java b/src/main/java/com/gxwebsoft/think/mapper/ThinkTrainingInstitutionMapper.java new file mode 100644 index 0000000..a1673f0 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/mapper/ThinkTrainingInstitutionMapper.java @@ -0,0 +1,31 @@ +package com.gxwebsoft.think.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.gxwebsoft.think.entity.ThinkTrainingInstitution; +import com.gxwebsoft.think.param.ThinkTrainingInstitutionParam; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 培训机构 Mapper + * + * @author Codex + * @since 2026-04-16 + */ +public interface ThinkTrainingInstitutionMapper extends BaseMapper { + + /** + * 分页查询 + */ + List selectPageRel( + @Param("page") IPage page, + @Param("param") ThinkTrainingInstitutionParam param + ); + + /** + * 查询全部 + */ + List selectListRel(@Param("param") ThinkTrainingInstitutionParam param); +} diff --git a/src/main/java/com/gxwebsoft/think/mapper/ThinkUserInAccessMapper.java b/src/main/java/com/gxwebsoft/think/mapper/ThinkUserInAccessMapper.java new file mode 100644 index 0000000..f4bdc76 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/mapper/ThinkUserInAccessMapper.java @@ -0,0 +1,37 @@ +package com.gxwebsoft.think.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.gxwebsoft.think.entity.ThinkUserInAccess; +import com.gxwebsoft.think.param.ThinkUserInAccessParam; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 能刷脸开闸的用户列表Mapper + * + * @author 科技小王子 + * @since 2026-03-13 02:27:34 + */ +public interface ThinkUserInAccessMapper extends BaseMapper { + + /** + * 分页查询 + * + * @param page 分页对象 + * @param param 查询参数 + * @return List + */ + List selectPageRel(@Param("page") IPage page, + @Param("param") ThinkUserInAccessParam param); + + /** + * 查询全部 + * + * @param param 查询参数 + * @return List + */ + List selectListRel(@Param("param") ThinkUserInAccessParam param); + +} diff --git a/src/main/java/com/gxwebsoft/think/mapper/ThinkUsersBlackMapper.java b/src/main/java/com/gxwebsoft/think/mapper/ThinkUsersBlackMapper.java new file mode 100644 index 0000000..a400716 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/mapper/ThinkUsersBlackMapper.java @@ -0,0 +1,31 @@ +package com.gxwebsoft.think.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.gxwebsoft.think.entity.ThinkUsersBlack; +import com.gxwebsoft.think.param.ThinkUsersBlackParam; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 用户黑名单 Mapper + * + * @author Codex + * @since 2026-06-04 + */ +public interface ThinkUsersBlackMapper extends BaseMapper { + + /** + * 分页查询 + */ + List selectPageRel( + @Param("page") IPage page, + @Param("param") ThinkUsersBlackParam param + ); + + /** + * 查询全部 + */ + List selectListRel(@Param("param") ThinkUsersBlackParam param); +} diff --git a/src/main/java/com/gxwebsoft/think/mapper/ThinkUsersVipMapper.java b/src/main/java/com/gxwebsoft/think/mapper/ThinkUsersVipMapper.java index 69fab5c..4e6abe4 100644 --- a/src/main/java/com/gxwebsoft/think/mapper/ThinkUsersVipMapper.java +++ b/src/main/java/com/gxwebsoft/think/mapper/ThinkUsersVipMapper.java @@ -2,6 +2,7 @@ package com.gxwebsoft.think.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.github.yulichang.base.MPJBaseMapper; import com.gxwebsoft.think.entity.ThinkUsersVip; import com.gxwebsoft.think.param.ThinkUsersVipParam; import org.apache.ibatis.annotations.Param; @@ -14,7 +15,7 @@ import java.util.List; * @author 科技小王子 * @since 2024-08-11 20:50:59 */ -public interface ThinkUsersVipMapper extends BaseMapper { +public interface ThinkUsersVipMapper extends MPJBaseMapper { /** * 分页查询 diff --git a/src/main/java/com/gxwebsoft/think/mapper/ThinkVipMapper.java b/src/main/java/com/gxwebsoft/think/mapper/ThinkVipMapper.java index 0bf1473..795c6ce 100644 --- a/src/main/java/com/gxwebsoft/think/mapper/ThinkVipMapper.java +++ b/src/main/java/com/gxwebsoft/think/mapper/ThinkVipMapper.java @@ -2,6 +2,7 @@ package com.gxwebsoft.think.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.github.yulichang.base.MPJBaseMapper; import com.gxwebsoft.think.entity.ThinkVip; import com.gxwebsoft.think.param.ThinkVipParam; import org.apache.ibatis.annotations.Param; @@ -14,7 +15,7 @@ import java.util.List; * @author 科技小王子 * @since 2024-08-12 02:12:22 */ -public interface ThinkVipMapper extends BaseMapper { +public interface ThinkVipMapper extends MPJBaseMapper { /** * 分页查询 diff --git a/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkSiteMapper.xml b/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkSiteMapper.xml index 058bf11..4d205da 100644 --- a/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkSiteMapper.xml +++ b/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkSiteMapper.xml @@ -25,6 +25,9 @@ AND a.price = #{param.price} + + AND a.is_on = #{param.isOn} + AND a.business_time LIKE CONCAT('%', #{param.businessTime}, '%') diff --git a/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkSmallRechargeMapper.xml b/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkSmallRechargeMapper.xml new file mode 100644 index 0000000..4fb0d77 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkSmallRechargeMapper.xml @@ -0,0 +1,48 @@ + + + + + + + SELECT a.* + FROM think_small_recharge a + + + AND a.id = #{param.id} + + + AND a.cid = #{param.cid} + + + AND a.vid = #{param.vid} + + + AND a.uid = #{param.uid} + + + AND a.amount = #{param.amount} + + + AND a.create_time >= #{param.createTimeStart} + + + AND a.create_time <= #{param.createTimeEnd} + + + AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') + ) + + + + + + + + + + + diff --git a/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkTrainingInstitutionMapper.xml b/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkTrainingInstitutionMapper.xml new file mode 100644 index 0000000..773be93 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkTrainingInstitutionMapper.xml @@ -0,0 +1,45 @@ + + + + + + SELECT a.* + FROM think_training_institution a + + + AND a.id = #{param.id} + + + AND a.name LIKE CONCAT('%', #{param.name}, '%') + + + AND a.contact_name LIKE CONCAT('%', #{param.contactName}, '%') + + + AND a.contact_phone LIKE CONCAT('%', #{param.contactPhone}, '%') + + + AND a.create_time >= #{param.createTimeStart} + + + AND a.create_time <= #{param.createTimeEnd} + + + AND ( + a.name LIKE CONCAT('%', #{param.keywords}, '%') + OR a.contact_name LIKE CONCAT('%', #{param.keywords}, '%') + OR a.contact_phone LIKE CONCAT('%', #{param.keywords}, '%') + ) + + + + + + + + + diff --git a/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkUserInAccessMapper.xml b/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkUserInAccessMapper.xml new file mode 100644 index 0000000..2e93906 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkUserInAccessMapper.xml @@ -0,0 +1,33 @@ + + + + + + + SELECT a.* + FROM think_user_in_access a + + + AND a.id = #{param.id} + + + AND a.uid = #{param.uid} + + + AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') + ) + + + + + + + + + + + diff --git a/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkUsersBlackMapper.xml b/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkUsersBlackMapper.xml new file mode 100644 index 0000000..8ce5985 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkUsersBlackMapper.xml @@ -0,0 +1,39 @@ + + + + + + SELECT a.*, u.truename, u.phone + FROM think_users_black a + LEFT JOIN think_users u ON a.uid = u.id + + + AND a.id = #{param.id} + + + AND a.uid = #{param.uid} + + + AND a.status = #{param.status} + + + AND a.expire_time LIKE CONCAT('%', #{param.expireTime}, '%') + + + AND a.create_time >= #{param.createTimeStart} + + + AND a.create_time <= #{param.createTimeEnd} + + + + + + + + + diff --git a/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkVipMapper.xml b/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkVipMapper.xml index 73a38d3..cab0ec3 100644 --- a/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkVipMapper.xml +++ b/src/main/java/com/gxwebsoft/think/mapper/xml/ThinkVipMapper.xml @@ -4,8 +4,9 @@ - SELECT a.* + SELECT a.*, b.name AS trainingInstitutionName FROM think_vip a + LEFT JOIN think_training_institution b ON a.training_institution_id = b.id AND a.id = #{param.id} @@ -62,6 +63,9 @@ AND a.vip_type = #{param.vipType} + + AND a.training_institution_id = #{param.trainingInstitutionId} + AND a.pic LIKE CONCAT('%', #{param.pic}, '%') diff --git a/src/main/java/com/gxwebsoft/think/param/ThinkInvoiceParam.java b/src/main/java/com/gxwebsoft/think/param/ThinkInvoiceParam.java index b52bdf6..e639146 100644 --- a/src/main/java/com/gxwebsoft/think/param/ThinkInvoiceParam.java +++ b/src/main/java/com/gxwebsoft/think/param/ThinkInvoiceParam.java @@ -102,4 +102,7 @@ public class ThinkInvoiceParam extends BaseParam { @TableField(exist = false) private Boolean forAdmin; + @TableField(exist = false) + private Boolean group; + } diff --git a/src/main/java/com/gxwebsoft/think/param/ThinkSiteParam.java b/src/main/java/com/gxwebsoft/think/param/ThinkSiteParam.java index 903f16b..a5aa901 100644 --- a/src/main/java/com/gxwebsoft/think/param/ThinkSiteParam.java +++ b/src/main/java/com/gxwebsoft/think/param/ThinkSiteParam.java @@ -71,6 +71,8 @@ public class ThinkSiteParam extends BaseParam { @ApiModelProperty(value = "退款规则组") private String moneyJson; + private Integer isOn; + private String lat; private String lng; diff --git a/src/main/java/com/gxwebsoft/think/param/ThinkSmallRechargeParam.java b/src/main/java/com/gxwebsoft/think/param/ThinkSmallRechargeParam.java new file mode 100644 index 0000000..f5f2d5f --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/param/ThinkSmallRechargeParam.java @@ -0,0 +1,41 @@ +package com.gxwebsoft.think.param; + +import java.math.BigDecimal; +import com.gxwebsoft.common.core.annotation.QueryField; +import com.gxwebsoft.common.core.annotation.QueryType; +import com.gxwebsoft.common.core.web.BaseParam; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 查询参数 + * + * @author 科技小王子 + * @since 2026-01-07 21:24:29 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@JsonInclude(JsonInclude.Include.NON_NULL) +@ApiModel(value = "ThinkSmallRechargeParam对象", description = "查询参数") +public class ThinkSmallRechargeParam extends BaseParam { + private static final long serialVersionUID = 1L; + + @QueryField(type = QueryType.EQ) + private Integer id; + + @QueryField(type = QueryType.EQ) + private Integer cid; + + @QueryField(type = QueryType.EQ) + private Integer vid; + + @QueryField(type = QueryType.EQ) + private Integer uid; + + @QueryField(type = QueryType.EQ) + private BigDecimal amount; + +} diff --git a/src/main/java/com/gxwebsoft/think/param/ThinkTrainingInstitutionParam.java b/src/main/java/com/gxwebsoft/think/param/ThinkTrainingInstitutionParam.java new file mode 100644 index 0000000..330263f --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/param/ThinkTrainingInstitutionParam.java @@ -0,0 +1,36 @@ +package com.gxwebsoft.think.param; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.gxwebsoft.common.core.annotation.QueryField; +import com.gxwebsoft.common.core.annotation.QueryType; +import com.gxwebsoft.common.core.web.BaseParam; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 培训机构查询参数 + * + * @author Codex + * @since 2026-04-16 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@JsonInclude(JsonInclude.Include.NON_NULL) +@ApiModel(value = "ThinkTrainingInstitutionParam对象", description = "培训机构查询参数") +public class ThinkTrainingInstitutionParam extends BaseParam { + private static final long serialVersionUID = 1L; + + @QueryField(type = QueryType.EQ) + private Integer id; + + @ApiModelProperty(value = "机构名称") + private String name; + + @ApiModelProperty(value = "联系人") + private String contactName; + + @ApiModelProperty(value = "联系方式") + private String contactPhone; +} diff --git a/src/main/java/com/gxwebsoft/think/param/ThinkUserInAccessParam.java b/src/main/java/com/gxwebsoft/think/param/ThinkUserInAccessParam.java new file mode 100644 index 0000000..be3c650 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/param/ThinkUserInAccessParam.java @@ -0,0 +1,32 @@ +package com.gxwebsoft.think.param; + +import java.math.BigDecimal; +import com.gxwebsoft.common.core.annotation.QueryField; +import com.gxwebsoft.common.core.annotation.QueryType; +import com.gxwebsoft.common.core.web.BaseParam; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 能刷脸开闸的用户列表查询参数 + * + * @author 科技小王子 + * @since 2026-03-13 02:27:34 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@JsonInclude(JsonInclude.Include.NON_NULL) +@ApiModel(value = "ThinkUserInAccessParam对象", description = "能刷脸开闸的用户列表查询参数") +public class ThinkUserInAccessParam extends BaseParam { + private static final long serialVersionUID = 1L; + + @QueryField(type = QueryType.EQ) + private Integer id; + + @QueryField(type = QueryType.EQ) + private Integer uid; + +} diff --git a/src/main/java/com/gxwebsoft/think/param/ThinkUsersBlackParam.java b/src/main/java/com/gxwebsoft/think/param/ThinkUsersBlackParam.java new file mode 100644 index 0000000..a986e4b --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/param/ThinkUsersBlackParam.java @@ -0,0 +1,38 @@ +package com.gxwebsoft.think.param; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.gxwebsoft.common.core.annotation.QueryField; +import com.gxwebsoft.common.core.annotation.QueryType; +import com.gxwebsoft.common.core.web.BaseParam; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 用户黑名单查询参数 + * + * @author Codex + * @since 2026-06-04 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@JsonInclude(JsonInclude.Include.NON_NULL) +@ApiModel(value = "ThinkUsersBlackParam对象", description = "用户黑名单查询参数") +public class ThinkUsersBlackParam extends BaseParam { + private static final long serialVersionUID = 1L; + + @QueryField(type = QueryType.EQ) + private Integer id; + + @ApiModelProperty(value = "用户ID") + @QueryField(type = QueryType.EQ) + private Integer uid; + + @ApiModelProperty(value = "状态:1,正常;2,禁用") + @QueryField(type = QueryType.EQ) + private Integer status; + + @ApiModelProperty(value = "失效时间") + private String expireTime; +} diff --git a/src/main/java/com/gxwebsoft/think/param/ThinkVipParam.java b/src/main/java/com/gxwebsoft/think/param/ThinkVipParam.java index e705761..2401a39 100644 --- a/src/main/java/com/gxwebsoft/think/param/ThinkVipParam.java +++ b/src/main/java/com/gxwebsoft/think/param/ThinkVipParam.java @@ -85,6 +85,10 @@ public class ThinkVipParam extends BaseParam { @QueryField(type = QueryType.EQ) private Integer vipType; + @ApiModelProperty(value = "培训机构ID") + @QueryField(type = QueryType.EQ) + private Integer trainingInstitutionId; + @ApiModelProperty(value = "特殊卡开发凭证图") private String pic; diff --git a/src/main/java/com/gxwebsoft/think/service/ThinkGateControlService.java b/src/main/java/com/gxwebsoft/think/service/ThinkGateControlService.java new file mode 100644 index 0000000..9daf901 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/service/ThinkGateControlService.java @@ -0,0 +1,114 @@ +package com.gxwebsoft.think.service; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import com.alibaba.fastjson.JSONObject; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 闸机控制远程调用 + * + * @author WebSoft + * @since 2026-03-13 + */ +@Service +public class ThinkGateControlService { + + private static final String BASE_URL = "http://47.121.133.163:18098"; + private static final String ACCESS_TOKEN = "6F9B7E4DA34AB1B5EA95CF4B6FBDABE0"; + private static final String LEVEL_ID = "8a94a9d19cd1f3fa019ce34a58133b8f"; + + public String getLevelId() { + return LEVEL_ID; + } + + public Object accLevelList(Integer pageNo, Integer pageSize) { + String apiUrl = BASE_URL + "/api/v2/accLevel/list"; + Map params = new HashMap<>(); + params.put("pageNo", pageNo); + params.put("pageSize", pageSize); + params.put("access_token", ACCESS_TOKEN); + String response = HttpRequest.get(apiUrl) + .form(params) + .timeout(20000) + .execute() + .body(); + return parseJson(response); + } + + public Object syncPerson(String pin, String levelIds) { + String apiUrl = BASE_URL + "/api/accLevel/syncPerson"; + Map params = new HashMap<>(); + params.put("pin", pin); + params.put("levelIds", levelIds); + params.put("access_token", ACCESS_TOKEN); + String response = HttpRequest.post(apiUrl) + .body(JSONObject.toJSONString(params)) + .timeout(20000) + .execute() + .body(); + return parseJson(response); + } + + public Object detectFace(Map params) { + String apiUrl = BASE_URL + "/api/v2/person/detectFace?access_token=" + ACCESS_TOKEN; + Map reqParams = new HashMap<>(); + reqParams.put("personPhoto", params.get("personPhoto")); + String response = HttpRequest.post(apiUrl) + .body(JSONObject.toJSONString(reqParams)) + .timeout(20000) + .execute() + .body(); + return parseJson(response); + } + + public Object deleteByPins(String pins) { + String apiUrl = BASE_URL + "/api/person/deleteByPins?access_token=" + ACCESS_TOKEN + "&pins=" + pins; + Map params = new HashMap<>(); + params.put("pins", pins); + String response = HttpRequest.post(apiUrl) + .body(JSONObject.toJSONString(params)) + .timeout(20000) + .execute() + .body(); + return parseJson(response); + } + + public String addPersons(List> personList) { + String apiUrl = BASE_URL + "/api/v2/person/addPersons?access_token=" + ACCESS_TOKEN; + return HttpRequest.post(apiUrl) + .body(JSONObject.toJSONString(personList)) + .timeout(20000) + .execute() + .body(); + } + + public Object transactionList() { + String apiUrl = BASE_URL + "/api/transaction/list"; + Map params = new HashMap<>(); + params.put("pageNo", 1); + params.put("pageSize", 999); + params.put("access_token", ACCESS_TOKEN); + String response = HttpRequest.get(apiUrl) + .form(params) + .timeout(20000) + .execute() + .body(); + return parseJson(response); + } + + private Object parseJson(String response) { + if (StrUtil.isBlank(response)) { + return response; + } + try { + return JSONObject.parse(response); + } catch (Exception e) { + return response; + } + } +} diff --git a/src/main/java/com/gxwebsoft/think/service/ThinkMachineOpenLogService.java b/src/main/java/com/gxwebsoft/think/service/ThinkMachineOpenLogService.java index 3edab11..ef3579a 100644 --- a/src/main/java/com/gxwebsoft/think/service/ThinkMachineOpenLogService.java +++ b/src/main/java/com/gxwebsoft/think/service/ThinkMachineOpenLogService.java @@ -41,5 +41,7 @@ public interface ThinkMachineOpenLogService extends IService listByOids(List orderIds); } diff --git a/src/main/java/com/gxwebsoft/think/service/ThinkOrderService.java b/src/main/java/com/gxwebsoft/think/service/ThinkOrderService.java index 63c277c..79df3c3 100644 --- a/src/main/java/com/gxwebsoft/think/service/ThinkOrderService.java +++ b/src/main/java/com/gxwebsoft/think/service/ThinkOrderService.java @@ -74,6 +74,8 @@ public interface ThinkOrderService extends IService { ThinkOrder getTodayOrder(Integer userId); + List getTodayOrderList(Integer userId); + List getTodayOrderInSite(Integer userId, Integer sid, String date); ThinkOrder getUnCheckBillByWechatCode(String wechatCode, long startTime, long endTime); diff --git a/src/main/java/com/gxwebsoft/think/service/ThinkSmallRechargeService.java b/src/main/java/com/gxwebsoft/think/service/ThinkSmallRechargeService.java new file mode 100644 index 0000000..e5ebc48 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/service/ThinkSmallRechargeService.java @@ -0,0 +1,47 @@ +package com.gxwebsoft.think.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.think.entity.ThinkSmallRecharge; +import com.gxwebsoft.think.param.ThinkSmallRechargeParam; + +import java.util.List; + +/** + * Service + * + * @author 科技小王子 + * @since 2026-01-07 21:24:29 + */ +public interface ThinkSmallRechargeService extends IService { + + /** + * 分页关联查询 + * + * @param param 查询参数 + * @return PageResult + */ + PageResult pageRel(ThinkSmallRechargeParam param); + + /** + * 关联查询全部 + * + * @param param 查询参数 + * @return List + */ + List listRel(ThinkSmallRechargeParam param); + + /** + * 根据id查询 + * + * @param id + * @return ThinkSmallRecharge + */ + ThinkSmallRecharge getByIdRel(Integer id); + + ThinkSmallRecharge getByOrderNo(String orderNo); + + ThinkSmallRecharge checkByVid(Integer vid); + + ThinkSmallRecharge checkByCid(Integer cid); +} diff --git a/src/main/java/com/gxwebsoft/think/service/ThinkTrainingInstitutionService.java b/src/main/java/com/gxwebsoft/think/service/ThinkTrainingInstitutionService.java new file mode 100644 index 0000000..1a17610 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/service/ThinkTrainingInstitutionService.java @@ -0,0 +1,32 @@ +package com.gxwebsoft.think.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.think.entity.ThinkTrainingInstitution; +import com.gxwebsoft.think.param.ThinkTrainingInstitutionParam; + +import java.util.List; + +/** + * 培训机构 Service + * + * @author Codex + * @since 2026-04-16 + */ +public interface ThinkTrainingInstitutionService extends IService { + + /** + * 分页关联查询 + */ + PageResult pageRel(ThinkTrainingInstitutionParam param); + + /** + * 查询全部 + */ + List listRel(ThinkTrainingInstitutionParam param); + + /** + * 根据 id 查询 + */ + ThinkTrainingInstitution getByIdRel(Integer id); +} diff --git a/src/main/java/com/gxwebsoft/think/service/ThinkUserInAccessService.java b/src/main/java/com/gxwebsoft/think/service/ThinkUserInAccessService.java new file mode 100644 index 0000000..8700dca --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/service/ThinkUserInAccessService.java @@ -0,0 +1,43 @@ +package com.gxwebsoft.think.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.think.entity.ThinkUserInAccess; +import com.gxwebsoft.think.param.ThinkUserInAccessParam; + +import java.util.List; + +/** + * 能刷脸开闸的用户列表Service + * + * @author 科技小王子 + * @since 2026-03-13 02:27:34 + */ +public interface ThinkUserInAccessService extends IService { + + /** + * 分页关联查询 + * + * @param param 查询参数 + * @return PageResult + */ + PageResult pageRel(ThinkUserInAccessParam param); + + /** + * 关联查询全部 + * + * @param param 查询参数 + * @return List + */ + List listRel(ThinkUserInAccessParam param); + + /** + * 根据id查询 + * + * @param id + * @return ThinkUserInAccess + */ + ThinkUserInAccess getByIdRel(Integer id); + + ThinkUserInAccess checkByUid(Integer id); +} diff --git a/src/main/java/com/gxwebsoft/think/service/ThinkUsersBlackService.java b/src/main/java/com/gxwebsoft/think/service/ThinkUsersBlackService.java new file mode 100644 index 0000000..d894e48 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/service/ThinkUsersBlackService.java @@ -0,0 +1,32 @@ +package com.gxwebsoft.think.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.think.entity.ThinkUsersBlack; +import com.gxwebsoft.think.param.ThinkUsersBlackParam; + +import java.util.List; + +/** + * 用户黑名单 Service + * + * @author Codex + * @since 2026-06-04 + */ +public interface ThinkUsersBlackService extends IService { + + /** + * 分页关联查询 + */ + PageResult pageRel(ThinkUsersBlackParam param); + + /** + * 查询全部 + */ + List listRel(ThinkUsersBlackParam param); + + /** + * 根据 id 查询 + */ + ThinkUsersBlack getByIdRel(Integer id); +} diff --git a/src/main/java/com/gxwebsoft/think/service/impl/ThinkCardServiceImpl.java b/src/main/java/com/gxwebsoft/think/service/impl/ThinkCardServiceImpl.java index 1c875b5..d734395 100644 --- a/src/main/java/com/gxwebsoft/think/service/impl/ThinkCardServiceImpl.java +++ b/src/main/java/com/gxwebsoft/think/service/impl/ThinkCardServiceImpl.java @@ -65,11 +65,13 @@ public class ThinkCardServiceImpl extends ServiceImpl vidList = list.stream().map(ThinkCard::getVid).collect(Collectors.toSet()); List vipList = thinkVipService.listByIds(vidList); for (ThinkCard item : list) { - String[] sids = item.getSid().split(","); - item.setSiteList(thinkSiteService.listByIds(Arrays.stream(sids).map(Integer::valueOf).toList())); - item.setThinkVip(vipList.stream().filter(item1 -> item1.getId().equals(item.getVid())).findFirst().orElse(null)); - if (item.getIsInvoice().equals(1)) { - item.setThinkInvoice(thinkInvoiceService.getByOidNType(item.getId(), 3)); + if (!item.getSid().isEmpty()) { + String[] sids = item.getSid().split(","); + item.setSiteList(thinkSiteService.listByIds(Arrays.stream(sids).map(Integer::valueOf).toList())); + item.setThinkVip(vipList.stream().filter(item1 -> item1.getId().equals(item.getVid())).findFirst().orElse(null)); + if (item.getIsInvoice().equals(1)) { + item.setThinkInvoice(thinkInvoiceService.getByOidNType(item.getId(), 3)); + } } } } diff --git a/src/main/java/com/gxwebsoft/think/service/impl/ThinkInvoiceServiceImpl.java b/src/main/java/com/gxwebsoft/think/service/impl/ThinkInvoiceServiceImpl.java index d2ad0b2..0ee76c1 100644 --- a/src/main/java/com/gxwebsoft/think/service/impl/ThinkInvoiceServiceImpl.java +++ b/src/main/java/com/gxwebsoft/think/service/impl/ThinkInvoiceServiceImpl.java @@ -57,6 +57,7 @@ public class ThinkInvoiceServiceImpl extends ServiceImpl() + .eq(ThinkMachineOpenLog::getLogId, logId) + .last("limit 1") + ); + } + @Override public List listByOids(List orderIds) { return list( diff --git a/src/main/java/com/gxwebsoft/think/service/impl/ThinkOrderServiceImpl.java b/src/main/java/com/gxwebsoft/think/service/impl/ThinkOrderServiceImpl.java index adef8e3..e651690 100644 --- a/src/main/java/com/gxwebsoft/think/service/impl/ThinkOrderServiceImpl.java +++ b/src/main/java/com/gxwebsoft/think/service/impl/ThinkOrderServiceImpl.java @@ -258,6 +258,7 @@ public class ThinkOrderServiceImpl extends ServiceImpl Long.parseLong(idArr[1]) + 30) { return new HashMap<>() {{ put("res", false); @@ -272,6 +273,9 @@ public class ThinkOrderServiceImpl extends ServiceImpl() {{ put("res", false); put("msg", "系统错误"); @@ -805,6 +809,7 @@ public class ThinkOrderServiceImpl extends ServiceImpl getTodayOrderList(Integer userId) { + return list( + new LambdaQueryWrapper() + .eq(ThinkOrder::getUid, userId) + .eq(ThinkOrder::getPayStatus, 1) + .eq(ThinkOrder::getOrderStatus, 2) + .between(ThinkOrder::getCreateTime, + DateUtil.parse(DateUtil.today() + " 00:00:00").getTime() / 1000, + (int) (System.currentTimeMillis() / 1000)) + .orderByDesc(ThinkOrder::getCreateTime) + ); + } + @Override public List getTodayOrderInSite(Integer userId, Integer sid, String date) { return list( diff --git a/src/main/java/com/gxwebsoft/think/service/impl/ThinkSmallRechargeServiceImpl.java b/src/main/java/com/gxwebsoft/think/service/impl/ThinkSmallRechargeServiceImpl.java new file mode 100644 index 0000000..4bfaf42 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/service/impl/ThinkSmallRechargeServiceImpl.java @@ -0,0 +1,90 @@ +package com.gxwebsoft.think.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gxwebsoft.think.mapper.ThinkSmallRechargeMapper; +import com.gxwebsoft.think.service.ThinkCardService; +import com.gxwebsoft.think.service.ThinkSmallRechargeService; +import com.gxwebsoft.think.entity.ThinkSmallRecharge; +import com.gxwebsoft.think.param.ThinkSmallRechargeParam; +import com.gxwebsoft.common.core.web.PageParam; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.think.service.ThinkUsersVipService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * Service实现 + * + * @author 科技小王子 + * @since 2026-01-07 21:24:29 + */ +@Service +public class ThinkSmallRechargeServiceImpl extends ServiceImpl implements ThinkSmallRechargeService { + @Resource + private ThinkUsersVipService thinkUsersVipService; + @Resource + private ThinkCardService thinkCardService; + + @Override + public PageResult pageRel(ThinkSmallRechargeParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("create_time desc"); + List list = baseMapper.selectPageRel(page, param); + for (ThinkSmallRecharge item : list) { + if (item.getVid() != null && item.getVid() > 0) + item.setUsersVip(thinkUsersVipService.getByIdRel(item.getVid())); + if (item.getCid() != null && item.getCid() > 0) + item.setCard(thinkCardService.getByIdRel(item.getCid())); + } + return new PageResult<>(list, page.getTotal()); + } + + @Override + public List listRel(ThinkSmallRechargeParam param) { + List list = baseMapper.selectListRel(param); + // 排序 + PageParam page = new PageParam<>(); + page.setDefaultOrder("create_time desc"); + return page.sortRecords(list); + } + + @Override + public ThinkSmallRecharge getByIdRel(Integer id) { + ThinkSmallRechargeParam param = new ThinkSmallRechargeParam(); + param.setId(id); + return param.getOne(baseMapper.selectListRel(param)); + } + + @Override + public ThinkSmallRecharge getByOrderNo(String orderNo) { + return getOne( + new LambdaQueryWrapper() + .eq(ThinkSmallRecharge::getOrderNo, orderNo) + .last("limit 1") + ); + } + + @Override + public ThinkSmallRecharge checkByVid(Integer vid) { + return getOne( + new LambdaQueryWrapper() + .eq(ThinkSmallRecharge::getVid, vid) + .eq(ThinkSmallRecharge::getStatus, 1) + .last("limit 1") + ); + } + + @Override + public ThinkSmallRecharge checkByCid(Integer cid) { + return getOne( + new LambdaQueryWrapper() + .eq(ThinkSmallRecharge::getCid, cid) + .eq(ThinkSmallRecharge::getStatus, 1) + .last("limit 1") + ); + } + +} diff --git a/src/main/java/com/gxwebsoft/think/service/impl/ThinkTrainingInstitutionServiceImpl.java b/src/main/java/com/gxwebsoft/think/service/impl/ThinkTrainingInstitutionServiceImpl.java new file mode 100644 index 0000000..4662df5 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/service/impl/ThinkTrainingInstitutionServiceImpl.java @@ -0,0 +1,47 @@ +package com.gxwebsoft.think.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gxwebsoft.common.core.web.PageParam; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.think.entity.ThinkTrainingInstitution; +import com.gxwebsoft.think.mapper.ThinkTrainingInstitutionMapper; +import com.gxwebsoft.think.param.ThinkTrainingInstitutionParam; +import com.gxwebsoft.think.service.ThinkTrainingInstitutionService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 培训机构 Service 实现 + * + * @author Codex + * @since 2026-04-16 + */ +@Service +public class ThinkTrainingInstitutionServiceImpl + extends ServiceImpl + implements ThinkTrainingInstitutionService { + + @Override + public PageResult pageRel(ThinkTrainingInstitutionParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("create_time desc"); + List list = baseMapper.selectPageRel(page, param); + return new PageResult<>(list, page.getTotal()); + } + + @Override + public List listRel(ThinkTrainingInstitutionParam param) { + List list = baseMapper.selectListRel(param); + PageParam page = new PageParam<>(); + page.setDefaultOrder("create_time desc"); + return page.sortRecords(list); + } + + @Override + public ThinkTrainingInstitution getByIdRel(Integer id) { + ThinkTrainingInstitutionParam param = new ThinkTrainingInstitutionParam(); + param.setId(id); + return param.getOne(baseMapper.selectListRel(param)); + } +} diff --git a/src/main/java/com/gxwebsoft/think/service/impl/ThinkUserInAccessServiceImpl.java b/src/main/java/com/gxwebsoft/think/service/impl/ThinkUserInAccessServiceImpl.java new file mode 100644 index 0000000..82819ea --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/service/impl/ThinkUserInAccessServiceImpl.java @@ -0,0 +1,56 @@ +package com.gxwebsoft.think.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gxwebsoft.think.mapper.ThinkUserInAccessMapper; +import com.gxwebsoft.think.service.ThinkUserInAccessService; +import com.gxwebsoft.think.entity.ThinkUserInAccess; +import com.gxwebsoft.think.param.ThinkUserInAccessParam; +import com.gxwebsoft.common.core.web.PageParam; +import com.gxwebsoft.common.core.web.PageResult; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 能刷脸开闸的用户列表Service实现 + * + * @author 科技小王子 + * @since 2026-03-13 02:27:34 + */ +@Service +public class ThinkUserInAccessServiceImpl extends ServiceImpl implements ThinkUserInAccessService { + + @Override + public PageResult pageRel(ThinkUserInAccessParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("create_time desc"); + List list = baseMapper.selectPageRel(page, param); + return new PageResult<>(list, page.getTotal()); + } + + @Override + public List listRel(ThinkUserInAccessParam param) { + List list = baseMapper.selectListRel(param); + // 排序 + PageParam page = new PageParam<>(); + page.setDefaultOrder("create_time desc"); + return page.sortRecords(list); + } + + @Override + public ThinkUserInAccess getByIdRel(Integer id) { + ThinkUserInAccessParam param = new ThinkUserInAccessParam(); + param.setId(id); + return param.getOne(baseMapper.selectListRel(param)); + } + + @Override + public ThinkUserInAccess checkByUid(Integer uid) { + return getOne( + new LambdaQueryWrapper() + .eq(ThinkUserInAccess::getUid, uid) + ); + } + +} diff --git a/src/main/java/com/gxwebsoft/think/service/impl/ThinkUsersBlackServiceImpl.java b/src/main/java/com/gxwebsoft/think/service/impl/ThinkUsersBlackServiceImpl.java new file mode 100644 index 0000000..c034c49 --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/service/impl/ThinkUsersBlackServiceImpl.java @@ -0,0 +1,47 @@ +package com.gxwebsoft.think.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gxwebsoft.common.core.web.PageParam; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.think.entity.ThinkUsersBlack; +import com.gxwebsoft.think.mapper.ThinkUsersBlackMapper; +import com.gxwebsoft.think.param.ThinkUsersBlackParam; +import com.gxwebsoft.think.service.ThinkUsersBlackService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 用户黑名单 Service 实现 + * + * @author Codex + * @since 2026-06-04 + */ +@Service +public class ThinkUsersBlackServiceImpl + extends ServiceImpl + implements ThinkUsersBlackService { + + @Override + public PageResult pageRel(ThinkUsersBlackParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("create_time desc"); + List list = baseMapper.selectPageRel(page, param); + return new PageResult<>(list, page.getTotal()); + } + + @Override + public List listRel(ThinkUsersBlackParam param) { + List list = baseMapper.selectListRel(param); + PageParam page = new PageParam<>(); + page.setDefaultOrder("create_time desc"); + return page.sortRecords(list); + } + + @Override + public ThinkUsersBlack getByIdRel(Integer id) { + ThinkUsersBlackParam param = new ThinkUsersBlackParam(); + param.setId(id); + return param.getOne(baseMapper.selectListRel(param)); + } +} diff --git a/src/main/java/com/gxwebsoft/think/service/impl/ThinkUsersServiceImpl.java b/src/main/java/com/gxwebsoft/think/service/impl/ThinkUsersServiceImpl.java index df240a4..1e9858d 100644 --- a/src/main/java/com/gxwebsoft/think/service/impl/ThinkUsersServiceImpl.java +++ b/src/main/java/com/gxwebsoft/think/service/impl/ThinkUsersServiceImpl.java @@ -1,6 +1,8 @@ package com.gxwebsoft.think.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.common.system.service.UserService; import com.gxwebsoft.think.mapper.ThinkUsersMapper; import com.gxwebsoft.think.service.ThinkUsersService; import com.gxwebsoft.think.entity.ThinkUsers; @@ -9,6 +11,8 @@ import com.gxwebsoft.common.core.web.PageParam; import com.gxwebsoft.common.core.web.PageResult; import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import java.math.BigDecimal; import java.util.List; /** @@ -19,12 +23,24 @@ import java.util.List; */ @Service public class ThinkUsersServiceImpl extends ServiceImpl implements ThinkUsersService { + @Resource + private UserService userService; @Override public PageResult pageRel(ThinkUsersParam param) { PageParam page = new PageParam<>(param); page.setDefaultOrder("create_time desc"); List list = baseMapper.selectPageRel(page, param); + for (ThinkUsers user : list) { + if (user.getPhone() != null ){ + User user1 = userService.getByPhoneInner(user.getPhone()); + user.setBalance(BigDecimal.ZERO); + if (user1 != null) { + user.setBalance(user1.getBalance()); + user.setUserId(user1.getUserId()); + } + } + } return new PageResult<>(list, page.getTotal()); } diff --git a/src/main/java/com/gxwebsoft/think/service/impl/ThinkVipServiceImpl.java b/src/main/java/com/gxwebsoft/think/service/impl/ThinkVipServiceImpl.java index 622114d..1c1363a 100644 --- a/src/main/java/com/gxwebsoft/think/service/impl/ThinkVipServiceImpl.java +++ b/src/main/java/com/gxwebsoft/think/service/impl/ThinkVipServiceImpl.java @@ -46,15 +46,17 @@ public class ThinkVipServiceImpl extends ServiceImpl i list.forEach(d -> { final ArrayList siteNames = new ArrayList<>(); final String sid = d.getSid(); - final String[] split = sid.split(","); - for (String siteId : split) { - final List thinkSites = collect.get(Integer.valueOf(siteId)); - if (!CollectionUtils.isEmpty(thinkSites)) { - final String name = thinkSites.get(0).getName(); - siteNames.add(name); + if (!sid.isEmpty()) { + final String[] split = sid.split(","); + for (String siteId : split) { + final List thinkSites = collect.get(Integer.valueOf(siteId)); + if (!CollectionUtils.isEmpty(thinkSites)) { + final String name = thinkSites.get(0).getName(); + siteNames.add(name); + } } + d.setSiteNames(String.join(",", siteNames)); } - d.setSiteNames(String.join(",", siteNames)); }); return new PageResult<>(list, page.getTotal()); } @@ -129,7 +131,8 @@ public class ThinkVipServiceImpl extends ServiceImpl i List cardList = list(wrapper); for (ThinkVip card : cardList) { List siteList = thinkSiteService.listByIds(Arrays.stream(card.getSid().split(",")).map(Integer::valueOf).toList()); - if (!siteList.isEmpty()) card.setSiteNames(String.join(",", siteList.stream().map(ThinkSite::getName).toList())); + if (!siteList.isEmpty()) + card.setSiteNames(String.join(",", siteList.stream().map(ThinkSite::getName).toList())); } thinkVip.setCardList(cardList); } @@ -138,7 +141,7 @@ public class ThinkVipServiceImpl extends ServiceImpl i } @Override - public List total(ThinkVipParam param){ + public List total(ThinkVipParam param) { List list = list(); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(ThinkUsersVip::getStatus, 1); diff --git a/src/main/java/com/gxwebsoft/think/task/ThinkFaceAccessTask.java b/src/main/java/com/gxwebsoft/think/task/ThinkFaceAccessTask.java new file mode 100644 index 0000000..22f033d --- /dev/null +++ b/src/main/java/com/gxwebsoft/think/task/ThinkFaceAccessTask.java @@ -0,0 +1,356 @@ +package com.gxwebsoft.think.task; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gxwebsoft.common.core.utils.RedisUtil; +import com.gxwebsoft.think.entity.*; +import com.gxwebsoft.think.service.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * 人脸权限定时同步 + * + * @author WebSoft + * @since 2026-03-13 + */ +@Component +public class ThinkFaceAccessTask { + + private static final Logger logger = LoggerFactory.getLogger(ThinkFaceAccessTask.class); + private static final int BATCH_SIZE = 100; + private static final String LOCK_KEY = "think:face:access:sync"; + private static final String ORDER_FACE_SYNC_LOCK_KEY = "think:face:access:order:sync"; + private static final DateTimeFormatter ACCESS_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + @Resource + private RedisUtil redisUtil; + @Resource + private ThinkUserInAccessService thinkUserInAccessService; + @Resource + private ThinkCardService thinkCardService; + @Resource + private ThinkUsersVipService thinkUsersVipService; + @Resource + private ThinkUsersService thinkUsersService; + @Resource + private ThinkGateControlService thinkGateControlService; + @Resource + private ThinkOrderService thinkOrderService; + @Resource + private ThinkOrderInfoService thinkOrderInfoService; + @Resource + private ThinkMachineOpenLogService thinkMachineOpenLogService; + + @Scheduled(cron = "*/5 * * * * ?") + public void syncTodayOrderFaceAccess() { + if (redisUtil.get(ORDER_FACE_SYNC_LOCK_KEY) != null) { + logger.info("skip syncTodayOrderFaceAccess, last task is still locked"); + return; + } + redisUtil.set(ORDER_FACE_SYNC_LOCK_KEY, DateUtil.currentSeconds(), 30L, TimeUnit.SECONDS); + try { + long startTime = DateUtil.parse(DateUtil.today() + " 00:00:00").getTime() / 1000; + long now = System.currentTimeMillis() / 1000; + List orderList = thinkOrderService.list( + new LambdaQueryWrapper() + .select(ThinkOrder::getUid) + .eq(ThinkOrder::getPayStatus, 1) + .eq(ThinkOrder::getOrderStatus, 2) + .eq(ThinkOrder::getSid, 37) + .between(ThinkOrder::getCreateTime, startTime, now) + ); + if (orderList == null || orderList.isEmpty()) { + return; + } + + Set uidSet = orderList.stream() + .map(ThinkOrder::getUid) + .filter(Objects::nonNull) + .collect(Collectors.toCollection(LinkedHashSet::new)); + if (uidSet.isEmpty()) { + return; + } + + List faceUsers = thinkUsersService.list( + new LambdaQueryWrapper() + .in(ThinkUsers::getId, uidSet) + .eq(ThinkUsers::getHasFace, 1) + .isNotNull(ThinkUsers::getPersonPhoto) + .ne(ThinkUsers::getPersonPhoto, "") + ); + if (faceUsers == null || faceUsers.isEmpty()) { + return; + } + + for (ThinkUsers faceUser : faceUsers) { + syncFaceUserToAccess(faceUser); + } + logger.info("syncTodayOrderFaceAccess success, orderCount={}, userCount={}", orderList.size(), faceUsers.size()); + } catch (Exception e) { + logger.error("syncTodayOrderFaceAccess failed", e); + } finally { + redisUtil.delete(ORDER_FACE_SYNC_LOCK_KEY); + } + } + + @Scheduled(cron = "*/5 * * * * ?") + public void syncTransactionList() { + try { + logger.info("syncTransactionList start"); + Object res = thinkGateControlService.transactionList(); + if (!(res instanceof Map)) { + logger.info("syncTransactionList skip, invalid res={}", res); + return; + } + + Map map = (Map) res; + Object codeObj = map.get("code"); + if (!"0".equals(String.valueOf(codeObj))) { + logger.info("syncTransactionList skip, code={}, res={}", codeObj, res); + return; + } + + Object dataObj = map.get("data"); + if (!(dataObj instanceof List)) { + logger.info("syncTransactionList skip, data is not list, data={}", dataObj); + return; + } + + List> transactionList = new ArrayList<>(); + for (Object item : (List) dataObj) { + if (!(item instanceof Map)) { + continue; + } + Map rawMap = (Map) item; + Object pinObj = rawMap.get("pin"); + if (StrUtil.isBlank(pinObj == null ? null : String.valueOf(pinObj))) { + continue; + } + Map transaction = new HashMap<>(); + for (Map.Entry entry : rawMap.entrySet()) { + if (entry.getKey() != null) { + transaction.put(String.valueOf(entry.getKey()), entry.getValue()); + } + } + transactionList.add(transaction); + if (transactionList.size() >= 100) { + break; + } + } + for (Map transaction : transactionList) { + Integer pin = Integer.valueOf(String.valueOf(transaction.get("pin"))); + List thinkOrderList = thinkOrderService.getTodayOrderList(pin); + for (ThinkOrder thinkOrder : thinkOrderList) { + ThinkMachineOpenLog openLog = thinkMachineOpenLogService.getByOrderId(thinkOrder.getId()); + Integer logId = Integer.valueOf(String.valueOf(transaction.get("logId"))); + ThinkMachineOpenLog check = thinkMachineOpenLogService.getByLogId(logId); + if (openLog == null && check == null) { + ThinkMachineOpenLog thinkMachineOpenLog = new ThinkMachineOpenLog(); + thinkMachineOpenLog.setOrderId(thinkOrder.getId()); + thinkMachineOpenLog.setLogId(logId); + thinkMachineOpenLogService.save(thinkMachineOpenLog); + int usedNum = 0; + int totalNum = 0; + List thinkOrderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId()); + for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) { + usedNum += thinkOrderInfo.getUsedNum() + 1; + totalNum += thinkOrderInfo.getAdultNum() + thinkOrderInfo.getChildrenNum(); + thinkOrderInfo.setUsedNum(thinkOrderInfo.getUsedNum() + 1); + thinkOrderInfoService.updateById(thinkOrderInfo); + } + if (usedNum == totalNum) { + thinkOrder.setOrderStatus(1); + thinkOrderService.updateById(thinkOrder); + } + thinkGateControlService.deleteByPins(pin.toString()); + } + } + } + logger.info("syncTransactionList success, size={}", transactionList.size()); + // 后续按需要处理 transactionList + if (!transactionList.isEmpty()) { + logger.debug("syncTransactionList pins={}", + transactionList.stream().map(item -> String.valueOf(item.get("pin"))).collect(Collectors.joining(","))); + } + } catch (Exception e) { + logger.error("syncTransactionList failed", e); + } + } + + private void syncFaceUserToAccess(ThinkUsers thinkUsers) { + if (thinkUsers == null || thinkUsers.getId() == null) { + return; + } + try { + ThinkUserInAccess check = thinkUserInAccessService.checkByUid(thinkUsers.getId()); + if (check != null) { + return; + } + + ThinkUserInAccess thinkUserInAccess = new ThinkUserInAccess(); + thinkUserInAccess.setUid(thinkUsers.getId()); + thinkUserInAccessService.save(thinkUserInAccess); + + List> list = new ArrayList<>(); + Map map = new HashMap<>(); + String day = DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd"); + String accStartTime = day + " 05:00:00"; + String accEndTime = day + " 22:00:00"; + map.put("pin", String.valueOf(thinkUsers.getId())); + map.put("mobilePhone", thinkUsers.getPhone()); + map.put("name", StrUtil.blankToDefault(thinkUsers.getUsername(), String.valueOf(thinkUsers.getId()))); + map.put("personPhoto", thinkUsers.getPersonPhoto()); + map.put("accEndTime", accEndTime); + map.put("accLevelIds", thinkGateControlService.getLevelId()); + map.put("accStartTime", accStartTime); + list.add(map); + thinkGateControlService.addPersons(list); + } catch (Exception e) { + logger.error("syncFaceUserToAccess failed, uid={}", thinkUsers.getId(), e); + } + } + + @Scheduled(cron = "0 30 0 * * ?") + public void syncFaceAccess() { + if (redisUtil.get(LOCK_KEY) != null) { + logger.info("skip syncFaceAccess, last task is still locked"); + return; + } + redisUtil.set(LOCK_KEY, DateUtil.currentSeconds(), 2L, TimeUnit.HOURS); + try { + clearRemotePersons(); + List faceUsers = listAvailableFaceUsers(); + syncRemotePersons(faceUsers); + rebuildLocalAccessRecords(faceUsers); + logger.info("syncFaceAccess finished, userCount={}", faceUsers.size()); + } catch (Exception e) { + logger.error("syncFaceAccess failed", e); + } + } + + private void clearRemotePersons() { + long pageNo = 1L; + while (true) { + Page page = thinkUserInAccessService.page( + new Page<>(pageNo, BATCH_SIZE), + new LambdaQueryWrapper().orderByAsc(ThinkUserInAccess::getId) + ); + List records = page.getRecords(); + if (records == null || records.isEmpty()) { + return; + } + String pins = records.stream() + .map(ThinkUserInAccess::getUid) + .filter(uid -> uid != null) + .map(String::valueOf) + .collect(Collectors.joining(",")); + if (StrUtil.isNotBlank(pins)) { + thinkGateControlService.deleteByPins(pins); + } + if (pageNo >= page.getPages()) { + return; + } + pageNo++; + } + } + + private List listAvailableFaceUsers() { + long now = DateUtil.currentSeconds(); + Set uidSet = new LinkedHashSet<>(); + + List thinkCardList = thinkCardService.list( + new LambdaQueryWrapper() + .gt(ThinkCard::getExpireTime, now) + .select(ThinkCard::getUid) + ); + uidSet.addAll(thinkCardList.stream() + .map(ThinkCard::getUid) + .filter(uid -> uid != null) + .toList()); + + List thinkUsersVipList = thinkUsersVipService.list( + new LambdaQueryWrapper() + .gt(ThinkUsersVip::getExpireTime, now) + .select(ThinkUsersVip::getUid) + ); + uidSet.addAll(thinkUsersVipList.stream() + .map(ThinkUsersVip::getUid) + .filter(uid -> uid != null) + .toList()); + + if (uidSet.isEmpty()) { + return Collections.emptyList(); + } + + return thinkUsersService.list( + new LambdaQueryWrapper() + .in(ThinkUsers::getId, uidSet) + .eq(ThinkUsers::getHasFace, 1) + .isNotNull(ThinkUsers::getPersonPhoto) + .ne(ThinkUsers::getPersonPhoto, "") + ); + } + + private void syncRemotePersons(List faceUsers) { + if (faceUsers == null || faceUsers.isEmpty()) { + return; + } + List> personList = new ArrayList<>(faceUsers.size()); + String accStartTime = formatTodayTime(5); + String accEndTime = formatTodayTime(22); + for (ThinkUsers faceUser : faceUsers) { + Map person = new HashMap<>(); + person.put("pin", String.valueOf(faceUser.getId())); + person.put("mobilePhone", faceUser.getPhone()); + person.put("name", StrUtil.blankToDefault(faceUser.getUsername(), String.valueOf(faceUser.getId()))); + person.put("personPhoto", faceUser.getPersonPhoto()); + person.put("accEndTime", accEndTime); + person.put("accLevelIds", thinkGateControlService.getLevelId()); + person.put("accStartTime", accStartTime); + personList.add(person); + } + for (int i = 0; i < personList.size(); i += BATCH_SIZE) { + int end = Math.min(i + BATCH_SIZE, personList.size()); + thinkGateControlService.addPersons(personList.subList(i, end)); + } + } + + private void rebuildLocalAccessRecords(List faceUsers) { + thinkUserInAccessService.remove(new LambdaQueryWrapper()); + if (faceUsers == null || faceUsers.isEmpty()) { + return; + } + List accessList = new ArrayList<>(faceUsers.size()); + for (ThinkUsers faceUser : faceUsers) { + ThinkUserInAccess access = new ThinkUserInAccess(); + access.setUid(faceUser.getId()); + accessList.add(access); + } + thinkUserInAccessService.saveBatch(accessList, BATCH_SIZE); + } + + private String formatTodayTime(int hour) { + return LocalDateTime.of(LocalDate.now(), java.time.LocalTime.of(hour, 0)) + .format(ACCESS_TIME_FORMATTER); + } +} diff --git a/src/main/resources/application-dev-local.yml b/src/main/resources/application-dev-local.yml index 194a500..bcf1ca8 100644 --- a/src/main/resources/application-dev-local.yml +++ b/src/main/resources/application-dev-local.yml @@ -3,11 +3,22 @@ # 数据源配置 spring: datasource: - url: jdbc:mysql://47.121.133.163:3308/gxtyzx_prod?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 - username: gxtyzx_prod - password: bfhrfCGdwABywbX3 - driver-class-name: com.mysql.cj.jdbc.Driver - type: com.alibaba.druid.pool.DruidDataSource + dynamic: + primary: master + strict: false + datasource: + master: + url: jdbc:mysql://47.121.133.163:3308/gxtyzx_prod?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 + username: gxtyzx_prod + password: bfhrfCGdwABywbX3 + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + server: + url: jdbc:mysql://47.121.133.163:3308/gxwebsoft_core?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true + username: gxwebsoft_core + password: jdj7HYEdYHnYEFBy + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource # 日志配置 logging: diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 1293c20..77bdd2a 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -3,11 +3,22 @@ # 数据源配置 spring: datasource: - url: jdbc:mysql://127.0.0.1:3308/gxtyzx_prod?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 - username: gxtyzx_prod - password: bfhrfCGdwABywbX3 - driver-class-name: com.mysql.cj.jdbc.Driver - type: com.alibaba.druid.pool.DruidDataSource + dynamic: + primary: master + strict: false + datasource: + master: + url: jdbc:mysql://127.0.0.1:3308/gxtyzx_prod?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 + username: gxtyzx_prod + password: bfhrfCGdwABywbX3 + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + server: + url: jdbc:mysql://127.0.0.1:3308/gxwebsoft_core?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true + username: gxwebsoft_core + password: jdj7HYEdYHnYEFBy + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource # 日志配置 logging: diff --git a/src/test/java/com/gxwebsoft/generator/ShopGenerator.java b/src/test/java/com/gxwebsoft/generator/ShopGenerator.java index 673c2a6..976cc4e 100644 --- a/src/test/java/com/gxwebsoft/generator/ShopGenerator.java +++ b/src/test/java/com/gxwebsoft/generator/ShopGenerator.java @@ -28,20 +28,19 @@ public class ShopGenerator { // 输出目录 private static final String OUTPUT_DIR = "/src/main/java"; // Vue文件输出位置 - private static final String OUTPUT_LOCATION_VUE = "/Users/gxwebsoft/VUE/gxtyzx-admin-vue"; - // Vue文件输出目录 - private static final String OUTPUT_LOCATION_UNIAPP = "/Users/gxwebsoft/VUE/gxtyzx-uniapp-cli"; + private static final String OUTPUT_LOCATION_VUE = "/Users/liangxin/Project/Html/web/gxtyzx-admin-vue"; + private static final String OUTPUT_LOCATION_UNIAPP = "/Users/liangxin/Project/Html/miniProgram/gxtyzx-uniapp-cli"; // Vue文件输出目录 private static final String OUTPUT_DIR_VUE = "/src"; // 作者名称 - private static final String AUTHOR = "科技小王子"; + private static final String AUTHOR = "LX"; // 是否在xml中添加二级缓存配置 private static final boolean ENABLE_CACHE = false; // 数据库连接配置 - private static final String DB_URL = "jdbc:mysql://47.119.165.234:3308/gxtyzx_ws?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8"; + private static final String DB_URL = "jdbc:mysql://47.121.133.163:3308/gxtyzx_prod?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8"; private static final String DB_DRIVER = "com.mysql.cj.jdbc.Driver"; - private static final String DB_USERNAME = "gxtyzx_ws"; - private static final String DB_PASSWORD = "2jPKyRhw5eTLHhJJ"; + private static final String DB_USERNAME = "gxtyzx_prod"; + private static final String DB_PASSWORD = "bfhrfCGdwABywbX3"; // 包名 private static final String PACKAGE_NAME = "com.gxwebsoft"; // 模块名 @@ -70,7 +69,8 @@ public class ShopGenerator { // "shop_user_collection", // "shop_mp_menu", // "shop_order", - "shop_order_info", + "shop_balance_charge_log", + "shop_user_balance_log", // "shop_order_info_log", // "shop_order_goods", // "shop_wechat_deposit", @@ -92,7 +92,7 @@ public class ShopGenerator { }; // 需要去除的表前缀 private static final String[] TABLE_PREFIX = new String[]{ - "tb_" + "shop_" }; // 不需要作为查询参数的字段 private static final String[] PARAM_EXCLUDE_FIELDS = new String[]{ diff --git a/src/test/java/com/gxwebsoft/generator/ThinkGenerator.java b/src/test/java/com/gxwebsoft/generator/ThinkGenerator.java index 56903b5..3378a6e 100644 --- a/src/test/java/com/gxwebsoft/generator/ThinkGenerator.java +++ b/src/test/java/com/gxwebsoft/generator/ThinkGenerator.java @@ -32,7 +32,7 @@ public class ThinkGenerator { // Vue文件输出目录 private static final String OUTPUT_DIR_VUE = "/src"; // 作者名称 - private static final String AUTHOR = "科技小王子"; + private static final String AUTHOR = "LX"; // 是否在xml中添加二级缓存配置 private static final boolean ENABLE_CACHE = false; // 数据库连接配置 @@ -119,7 +119,7 @@ public class ThinkGenerator { // "think_wechat_bill_log", // "think_cards_bills", // "think_ftp_check_bill", - "think_card_balance", + "think_user_in_access", }; // 需要去除的表前缀 private static final String[] TABLE_PREFIX = new String[]{