| | |
| | | *.jar |
| | | *.war |
| | | /CLAUDE.md |
| | | /.claude/settings.local.json |
| | | /.vscode/settings.json |
| | |
| | | return ApiResponse.success(null); |
| | | } |
| | | |
| | | @ApiOperation("修改状态") |
| | | @PostMapping("/updateStatus") |
| | | @RequiresPermissions("business:banner:update") |
| | | public ApiResponse updateStatus(@RequestBody Banner banner) { |
| | | bannerService.updateStatus(banner); |
| | | return ApiResponse.success(null); |
| | | } |
| | | |
| | | @ApiOperation("分页查询") |
| | | @PostMapping("/page") |
| | | @RequiresPermissions("business:banner:query") |
| | |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.dao.business.model.DriverInfo; |
| | | import com.doumee.dao.dto.AuditDTO; |
| | | import com.doumee.dao.dto.ChangeStatusDTO; |
| | | import com.doumee.service.business.DriverInfoService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | |
| | | return ApiResponse.success(driverInfoService.findById(id)); |
| | | } |
| | | |
| | | @ApiOperation("司机详情(含附件)") |
| | | @GetMapping("/detail/{id}") |
| | | @RequiresPermissions("business:driverInfo:query") |
| | | public ApiResponse getDetail(@PathVariable Integer id) { |
| | | return ApiResponse.success(driverInfoService.getDetail(id)); |
| | | } |
| | | |
| | | @ApiOperation("审批司机实名认证") |
| | | @PostMapping("/audit") |
| | | @RequiresPermissions("business:driverInfo:audit") |
| | | @RequiresPermissions("business:driverInfo:update") |
| | | public ApiResponse audit(@RequestBody AuditDTO auditDTO) { |
| | | auditDTO.setAuditUser(this.getLoginUser().getId()); |
| | | driverInfoService.auditVerify(auditDTO); |
| | | return ApiResponse.success("审批成功"); |
| | | } |
| | | |
| | | @ApiOperation("修改司机状态") |
| | | @PostMapping("/changeStatus") |
| | | @RequiresPermissions("business:driverInfo:update") |
| | | public ApiResponse changeStatus(@RequestBody ChangeStatusDTO dto) { |
| | | driverInfoService.changeStatus(dto); |
| | | return ApiResponse.success("操作成功"); |
| | | } |
| | | |
| | | } |
| | |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.dao.business.model.Member; |
| | | import com.doumee.dao.dto.MemberListQueryDTO; |
| | | import com.doumee.dao.vo.MemberDetailVO; |
| | | import com.doumee.dao.vo.MemberListVO; |
| | | import com.doumee.service.business.MemberService; |
| | | import com.github.xiaoymin.knife4j.core.util.CollectionUtils; |
| | | import io.swagger.annotations.Api; |
| | |
| | | public ApiResponse findById(@PathVariable Integer id) { |
| | | return ApiResponse.success(memberService.findById(id)); |
| | | } |
| | | |
| | | @ApiOperation("会员列表分页查询") |
| | | @PostMapping("/list/page") |
| | | @RequiresPermissions("business:member:query") |
| | | public ApiResponse<PageData<MemberListVO>> findMemberListPage(@RequestBody PageWrap<MemberListQueryDTO> pageWrap) { |
| | | return ApiResponse.success(memberService.findMemberListPage(pageWrap)); |
| | | } |
| | | |
| | | @ApiOperation("会员列表导出Excel") |
| | | @PostMapping("/list/exportExcel") |
| | | @RequiresPermissions("business:member:exportExcel") |
| | | public void exportMemberListExcel(@RequestBody PageWrap<MemberListQueryDTO> pageWrap, HttpServletResponse response) { |
| | | List<MemberListVO> list = memberService.findMemberListPage(pageWrap).getRecords(); |
| | | ExcelExporter.build(MemberListVO.class).export(list, "会员列表", response); |
| | | } |
| | | |
| | | @ApiOperation("会员详情查询") |
| | | @GetMapping("/detail/{id}") |
| | | @RequiresPermissions("business:member:query") |
| | | public ApiResponse<MemberDetailVO> findMemberDetail(@PathVariable Integer id) { |
| | | return ApiResponse.success(memberService.findMemberDetail(id)); |
| | | } |
| | | } |
| | |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.dao.business.model.Orders; |
| | | import com.doumee.dao.dto.ConfirmArriveDTO; |
| | | import com.doumee.dao.dto.DispatchDTO; |
| | | import com.doumee.dao.vo.OrderDetailVO; |
| | | import com.doumee.dao.vo.OrderDispatchVO; |
| | | import com.doumee.dao.vo.OrderSummaryVO; |
| | | import com.doumee.service.business.OrdersService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | |
| | | return ApiResponse.success(ordersService.findPage(pageWrap)); |
| | | } |
| | | |
| | | @ApiOperation("订单汇总统计") |
| | | @PostMapping("/summary") |
| | | @RequiresPermissions("business:orders:query") |
| | | public ApiResponse<OrderSummaryVO> findSummary(@RequestBody PageWrap<Orders> pageWrap) { |
| | | return ApiResponse.success(ordersService.findSummary(pageWrap)); |
| | | } |
| | | |
| | | @ApiOperation("导出Excel") |
| | | @PostMapping("/exportExcel") |
| | | @RequiresPermissions("business:orders:exportExcel") |
| | |
| | | return ApiResponse.success(ordersService.findById(id)); |
| | | } |
| | | |
| | | @ApiOperation("订单详情") |
| | | @GetMapping("/detail/{id}") |
| | | @RequiresPermissions("business:orders:query") |
| | | public ApiResponse<OrderDetailVO> findDetail(@PathVariable Integer id) { |
| | | return ApiResponse.success(ordersService.findDetail(id)); |
| | | } |
| | | |
| | | @ApiOperation("手动派单信息") |
| | | @GetMapping("/dispatch/{id}") |
| | | @RequiresPermissions("business:orders:query") |
| | | public ApiResponse<OrderDispatchVO> findDispatchInfo(@PathVariable Integer id) { |
| | | return ApiResponse.success(ordersService.findDispatchInfo(id)); |
| | | } |
| | | |
| | | @ApiOperation("订单派单") |
| | | @PostMapping("/dispatch") |
| | | @RequiresPermissions("business:orders:update") |
| | | public ApiResponse dispatch(@RequestBody DispatchDTO dto) { |
| | | ordersService.dispatch(dto); |
| | | return ApiResponse.success(null); |
| | | } |
| | | |
| | | @ApiOperation("确认顾客到店") |
| | | @PostMapping("/confirmArrived") |
| | | @RequiresPermissions("business:orders:update") |
| | | public ApiResponse confirmArrived(@RequestBody ConfirmArriveDTO dto) { |
| | | ordersService.confirmCustomerArrived(dto.getOrderId(), dto.getShopId()); |
| | | return ApiResponse.success(null); |
| | | } |
| | | |
| | | } |
| | |
| | | @ApiOperation("查询预计时效配置") |
| | | @GetMapping("/estimatedDelivery/list") |
| | | @RequiresPermissions("business:pricingRule:query") |
| | | public ApiResponse<EstimatedDeliveryVO> listEstimatedDelivery(@RequestParam Integer cityId) { |
| | | public ApiResponse<List<EstimatedDeliveryVO>> listEstimatedDelivery(@RequestParam Integer cityId) { |
| | | return ApiResponse.success(pricingRuleService.getEstimatedDelivery(cityId)); |
| | | } |
| | | |
| | |
| | | |
| | | @ApiOperation("分页查询") |
| | | @PostMapping("/page") |
| | | @RequiresPermissions("business:revenue:query") |
| | | public ApiResponse<PageData<Revenue>> findPage(@RequestBody PageWrap<Revenue> pageWrap) { |
| | | return ApiResponse.success(revenueService.findPage(pageWrap)); |
| | | } |
| | | |
| | | @ApiOperation("导出Excel") |
| | | @PostMapping("/exportExcel") |
| | | @RequiresPermissions("business:revenue:exportExcel") |
| | | public void exportExcel(@RequestBody PageWrap<Revenue> pageWrap, HttpServletResponse response) { |
| | | ExcelExporter.build(Revenue.class).export(revenueService.findPage(pageWrap).getRecords(), "收支记录", response); |
| | | } |
| | | |
| | | @ApiOperation("根据ID查询") |
| | | @GetMapping("/{id}") |
| | | @RequiresPermissions("business:revenue:query") |
| | | public ApiResponse findById(@PathVariable Integer id) { |
| | | return ApiResponse.success(revenueService.findById(id)); |
| | | } |
| | |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.dao.business.model.WithdrawalOrders; |
| | | import com.doumee.dao.dto.WithdrawalApproveDTO; |
| | | import com.doumee.service.business.WithdrawalOrdersService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | |
| | | @ApiOperation("根据ID查询") |
| | | @GetMapping("/{id}") |
| | | @RequiresPermissions("business:withdrawalOrders:query") |
| | | public ApiResponse findById(@PathVariable Integer id) { |
| | | public ApiResponse<WithdrawalOrders> findById(@PathVariable Integer id) { |
| | | return ApiResponse.success(withdrawalOrdersService.findById(id)); |
| | | } |
| | | |
| | | @ApiOperation("已提现统计金额") |
| | | @PostMapping("/totalAmount") |
| | | @RequiresPermissions("business:withdrawalOrders:query") |
| | | public ApiResponse<Long> totalAmount(@RequestBody PageWrap<WithdrawalOrders> pageWrap) { |
| | | return ApiResponse.success(withdrawalOrdersService.totalAmount(pageWrap)); |
| | | } |
| | | |
| | | @ApiOperation("提现审批") |
| | | @PostMapping("/approve") |
| | | @RequiresPermissions("business:withdrawalOrders:update") |
| | | public ApiResponse approve(@RequestBody WithdrawalApproveDTO dto) { |
| | | withdrawalOrdersService.approve(dto); |
| | | return ApiResponse.success(null); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/04/15 订单表添加核销码字段 |
| | | -- ============================================================ |
| | | |
| | | ALTER TABLE `orders` ADD COLUMN `MEMBER_VERIFY_CODE` VARCHAR(32) DEFAULT NULL COMMENT '会员订单核销码' AFTER `OVERDUE_STATUS`; |
| | | ALTER TABLE `orders` ADD COLUMN `DRIVER_VERIFY_CODE` VARCHAR(32) DEFAULT NULL COMMENT '司机订单核销码' AFTER `MEMBER_VERIFY_CODE`; |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/04/15 订单表添加是否逾期字段 |
| | | -- ============================================================ |
| | | |
| | | ALTER TABLE `orders` ADD COLUMN `OVERDUE_STATUS` TINYINT DEFAULT 0 COMMENT '是否逾期: 0=否 1=是 2=已支付' AFTER `OVERDUE_DAYS`; |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/04/15 订单物品明细表添加就地存取单价字段 |
| | | -- ============================================================ |
| | | |
| | | ALTER TABLE `orders_detail` ADD COLUMN `LOCALLY_PRICE` BIGINT DEFAULT NULL COMMENT '就地存取单价(分/天)' AFTER `EXTRA_PRICE`; |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/04/14 门店营业类型字段 |
| | | -- ============================================================ |
| | | |
| | | ALTER TABLE `shop_info` ADD COLUMN `BUSINESS_TYPE` INT DEFAULT 0 COMMENT '门店营业类型:0=非全天;1=全天' AFTER `SHOP_HOURS`; |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/04/14 门店信息维护字段 |
| | | -- ============================================================ |
| | | |
| | | ALTER TABLE `shop_info` ADD COLUMN `COVER_IMG` VARCHAR(500) DEFAULT NULL COMMENT '门店头像' AFTER `PAY_MEMBER_OPEN_ID`; |
| | | ALTER TABLE `shop_info` ADD COLUMN `CONTENT` TEXT DEFAULT NULL COMMENT '门店介绍' AFTER `COVER_IMG`; |
| | | ALTER TABLE `shop_info` ADD COLUMN `DEPOSIT_TYPES` VARCHAR(500) DEFAULT NULL COMMENT '寄存类型(逗号分隔的category主键)' AFTER `CONTENT`; |
| | | ALTER TABLE `shop_info` ADD COLUMN `FEE_STANDARD` VARCHAR(500) DEFAULT NULL COMMENT '收费标准' AFTER `DEPOSIT_TYPES`; |
| | | ALTER TABLE `shop_info` ADD COLUMN `DELIVERY_AREA` DECIMAL(10,2) DEFAULT NULL COMMENT '配送范围(km)' AFTER `FEE_STANDARD`; |
| | | ALTER TABLE `shop_info` ADD COLUMN `SHOP_HOURS` VARCHAR(100) DEFAULT NULL COMMENT '营业时间' AFTER `DELIVERY_AREA`; |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/04/13 提现申请用户类型字段 |
| | | -- ============================================================ |
| | | |
| | | ALTER TABLE `withdrawal_orders` ADD COLUMN `MEMBER_TYPE` INT DEFAULT NULL COMMENT '用户类型:1=司机;2=店铺' AFTER `MEMBER_ID`; |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/04/13 提现申请审批字段 + 审批权限 |
| | | -- ============================================================ |
| | | |
| | | ALTER TABLE `withdrawal_orders` ADD COLUMN `USER_ID` INT DEFAULT NULL COMMENT '审批操作人(关联system_user)' AFTER `ALI_ACCOUNT`; |
| | | ALTER TABLE `withdrawal_orders` ADD COLUMN `APPROVE_TIME` DATETIME DEFAULT NULL COMMENT '审批时间' AFTER `USER_ID`; |
| | | ALTER TABLE `withdrawal_orders` ADD COLUMN `APPROVE_REMARK` VARCHAR(500) DEFAULT NULL COMMENT '审批备注' AFTER `APPROVE_TIME`; |
| | | |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:withdrawalOrders:create', '新建提现申请', '提现申请', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:withdrawalOrders:delete', '删除提现申请', '提现申请', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:withdrawalOrders:update', '修改提现申请', '提现申请', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:withdrawalOrders:query', '查询提现申请', '提现申请', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:withdrawalOrders:exportExcel', '导出提现申请(Excel)', '提现申请', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/04/13 订单退款记录权限 |
| | | -- ============================================================ |
| | | |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:ordersRefund:create', '新建订单退款记录', '订单退款记录', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:ordersRefund:delete', '删除订单退款记录', '订单退款记录', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:ordersRefund:update', '修改订单退款记录', '订单退款记录', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:ordersRefund:query', '查询订单退款记录', '订单退款记录', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/04/13 会员列表与详情权限 |
| | | -- ============================================================ |
| | | |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:member:list', '查询会员列表', '会员管理', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | INSERT INTO `SYSTEM_PERMISSION`(`CODE`, `NAME`, `MODULE`, `REMARK`, `FIXED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('business:member:listExport', '导出会员列表(Excel)', '会员管理', '', 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0); |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/04/13 订单新增取消备注字段 + 订单文件路径字典 |
| | | -- ============================================================ |
| | | |
| | | ALTER TABLE `orders` ADD COLUMN `cancel_remark` VARCHAR(500) DEFAULT NULL COMMENT '取消备注' AFTER `cancel_time`; |
| | | ALTER TABLE `orders` ADD COLUMN `CANCEL_REMARK` VARCHAR(500) DEFAULT NULL COMMENT '取消备注' AFTER `CANCEL_TIME`; |
| | | |
| | | INSERT INTO `system_dict_data`(`DICT_ID`, `CODE`, `LABEL`, `REMARK`, `SORT`, `DISABLED`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) |
| | | SELECT 100, '/orders/', 'ORDERS_FILES', '订单文件路径', 22, 0, 1, CURRENT_TIMESTAMP, NULL, NULL, 0 |
| | |
| | | -- 2026/04/13 支付宝提现账户字段 |
| | | -- ============================================================ |
| | | |
| | | ALTER TABLE `withdrawal_orders` ADD COLUMN `ali_account` VARCHAR(64) DEFAULT NULL COMMENT '支付宝提现账户' AFTER `out_bill_no`; |
| | | ALTER TABLE `shop_info` ADD COLUMN `ali_account` VARCHAR(64) DEFAULT NULL COMMENT '支付宝提现账户' AFTER `delivery_area`; |
| | | ALTER TABLE `withdrawal_orders` ADD COLUMN `ALI_ACCOUNT` VARCHAR(64) DEFAULT NULL COMMENT '支付宝提现账户' AFTER `OUT_BILL_NO`; |
| | | ALTER TABLE `shop_info` ADD COLUMN `ALI_ACCOUNT` VARCHAR(64) DEFAULT NULL COMMENT '支付宝提现账户' AFTER `DELIVERY_AREA`; |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/04/13 轮播图业务调整 |
| | | -- ============================================================ |
| | | |
| | | ALTER TABLE `banner` MODIFY COLUMN `title` VARCHAR(255) DEFAULT NULL COMMENT '标题'; |
| | | ALTER TABLE `banner` MODIFY COLUMN `TITLE` VARCHAR(255) DEFAULT NULL COMMENT '标题'; |
| | | |
| | | INSERT INTO `SYSTEM_DICT_DATA`(`TYPE`, `CODE`, `NAME`, `VALUE`, `REMARK`, `CREATE_TIME`, `DELETED`) |
| | | VALUES ('SYSTEM', 'BANNER_FILES', '轮播图文件路径', '/banner/', '轮播图图片存储子路径', CURRENT_TIMESTAMP, 0); |
| | |
| | | |
| | | public static final String MEMBER_INFO = "MEMBER_INFO"; |
| | | |
| | | public static final String SHOP_ID = "SHOP_ID"; |
| | | |
| | | public static final String SHOP_INFO = "SHOP_INFO"; |
| | | |
| | | @Resource |
| | | private RedisTemplate<String,Object> redisTemplate; |
| | | |
| | |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.doumee.core.annotation.LoginRequired; |
| | | import com.doumee.core.annotation.LoginShopRequired; |
| | | import com.doumee.core.constants.Constants; |
| | | import com.doumee.core.constants.ResponseStatus; |
| | | import com.doumee.core.exception.BusinessException; |
| | | import com.doumee.dao.business.model.Member; |
| | | import com.doumee.dao.business.model.ShopInfo; |
| | | import io.jsonwebtoken.JwtException; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | import org.springframework.web.client.RestTemplate; |
| | | import org.springframework.web.method.HandlerMethod; |
| | |
| | | @Autowired |
| | | private JdbcTemplate dao; |
| | | |
| | | @Resource |
| | | private JwtTokenUtil jwtTokenUtil; |
| | | @Autowired |
| | | private RedisTemplate<String,Object> redisTemplate; |
| | | |
| | | |
| | | /** |
| | | * 添加拦截器 |
| | |
| | | //获取token |
| | | String token = request.getHeader(JwtTokenUtil.HEADER_KEY); // 从 http 请求头中取出 token |
| | | if (StringUtils.isNotBlank(token)) { |
| | | checkLogin(request,response); |
| | | checkMemberLogin(request,response); |
| | | } else { |
| | | throw new BusinessException(ResponseStatus.BE_OVERDUE.getCode(),"未登录"); |
| | | } |
| | |
| | | //获取token |
| | | String token = request.getHeader(JwtTokenUtil.HEADER_KEY); // 从 http 请求头中取出 token |
| | | if (StringUtils.isNotBlank(token)) { |
| | | checkLogin(request,response); |
| | | checkMemberLogin(request,response); |
| | | } else { |
| | | throw new BusinessException(ResponseStatus.BE_OVERDUE.getCode(),"未登录"); |
| | | } |
| | | }else if (beanType.isAnnotationPresent(LoginShopRequired.class)) { |
| | | //获取token |
| | | String token = request.getHeader(JwtTokenUtil.HEADER_KEY); // 从 http 请求头中取出 token |
| | | if (StringUtils.isNotBlank(token)) { |
| | | checkShopLogin(request,response); |
| | | } else { |
| | | throw new BusinessException(ResponseStatus.BE_OVERDUE.getCode(),"未登录"); |
| | | } |
| | | }else if (handlerMethod.hasMethodAnnotation(LoginShopRequired.class)){ |
| | | //获取token |
| | | String token = request.getHeader(JwtTokenUtil.HEADER_KEY); // 从 http 请求头中取出 token |
| | | if (StringUtils.isNotBlank(token)) { |
| | | checkShopLogin(request,response); |
| | | } else { |
| | | throw new BusinessException(ResponseStatus.BE_OVERDUE.getCode(),"未登录"); |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | public Boolean checkLogin(HttpServletRequest request, HttpServletResponse response){ |
| | | public Boolean checkMemberLogin(HttpServletRequest request, HttpServletResponse response){ |
| | | String token = request.getHeader(JwtTokenUtil.HEADER_KEY); |
| | | try { |
| | | Member member = jwtTokenUtil.getUserInfoByToken(token); |
| | | |
| | | if(!token.startsWith(Constants.ZERO+"")){ |
| | | throw new BusinessException(ResponseStatus.TOKEN_EXCEED_TIME); |
| | | } |
| | | String tokenRedis = (String) redisTemplate.opsForValue().get(token); |
| | | if(StringUtils.isBlank(tokenRedis)){ |
| | | throw new BusinessException(ResponseStatus.BE_OVERDUE); |
| | | } |
| | | Member member = JSONObject.parseObject(tokenRedis, Member.class); |
| | | if(Objects.isNull(member)){ |
| | | throw new BusinessException(ResponseStatus.TOKEN_EXCEED_TIME.getCode(),"长时间未操作,请重新登录"); |
| | | throw new BusinessException(ResponseStatus.TOKEN_EXCEED_TIME); |
| | | } |
| | | Integer isDeleted = dao.queryForObject(" select COALESCE(DELETED,1) from member where id = ?", Integer.class, member.getId()); |
| | | if(isDeleted.equals(Constants.ONE)){ |
| | |
| | | } |
| | | Integer count = dao.queryForObject("select count(1) from member where id = ?", Integer.class, member.getId()); |
| | | if (count != null && count > 0) { |
| | | // jwtTokenUtil.refreshToken(token,member); |
| | | request.setAttribute(JwtTokenUtil.MEMBER_INFO, JSONObject.toJSONString(member)); |
| | | request.setAttribute(JwtTokenUtil.MEMBER_ID, member.getId()); |
| | | return true; |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | public Boolean checkShopLogin(HttpServletRequest request, HttpServletResponse response){ |
| | | String token = request.getHeader(JwtTokenUtil.HEADER_KEY); |
| | | try { |
| | | if(!token.startsWith(Constants.TWO+"")){ |
| | | throw new BusinessException(ResponseStatus.TOKEN_EXCEED_TIME); |
| | | } |
| | | String tokenRedis = (String) redisTemplate.opsForValue().get(token); |
| | | if(StringUtils.isBlank(tokenRedis)){ |
| | | throw new BusinessException(ResponseStatus.BE_OVERDUE); |
| | | } |
| | | ShopInfo shop = JSONObject.parseObject(tokenRedis, ShopInfo.class); |
| | | if(Objects.isNull(shop)){ |
| | | throw new BusinessException(ResponseStatus.BE_OVERDUE); |
| | | } |
| | | String openid = shop.getOpenid(); |
| | | Integer shopId = getTokenId(token); |
| | | Integer isDeleted = dao.queryForObject(" select COALESCE(ISDELETED,0) from shop_info where id = ?", Integer.class, shopId); |
| | | if(isDeleted== Constants.ONE){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"商户已删除,请联系管理员"); |
| | | } |
| | | Integer isForbidden = dao.queryForObject(" select COALESCE(STATUS,0) from shop_info where id = ?", Integer.class, shopId); |
| | | if(isForbidden == Constants.ONE){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"商户已禁用,请联系管理员"); |
| | | } |
| | | String dbOpenid = dao.queryForObject(" select ifnull(openid,'') from shop where id = ?", String.class, shopId); |
| | | if(StringUtils.isBlank(dbOpenid)||!openid.equals(dbOpenid)){ |
| | | throw new BusinessException(ResponseStatus.TOKEN_EXCEED_TIME); |
| | | } |
| | | Integer count = dao.queryForObject("select count(1) from shop where id = ?", Integer.class, shopId); |
| | | if (count != null && count > 0) { |
| | | request.setAttribute(JwtTokenUtil.SHOP_INFO, JSONObject.toJSONString(shop)); |
| | | request.setAttribute(JwtTokenUtil.SHOP_ID, shop.getId()); |
| | | return true; |
| | | }else{ |
| | | throw new BusinessException(ResponseStatus.BE_OVERDUE.getCode(),"用户信息出错"); |
| | | } |
| | | } catch (IllegalArgumentException | JwtException e) { |
| | | throw new BusinessException(ResponseStatus.BE_OVERDUE); |
| | | } |
| | | } |
| | | |
| | | |
| | | public Integer getTokenId(String token){ |
| | | try { |
| | | Integer lastIndex = token.lastIndexOf("_")+1; |
| | | Integer tokenId = Integer.valueOf(token.substring(lastIndex)); |
| | | return tokenId; |
| | | }catch (Exception e){ |
| | | throw new BusinessException(ResponseStatus.BE_OVERDUE); |
| | | } |
| | | } |
| | | |
| | | @Bean |
| | | public RestTemplate getRestTemplate(){ |
| | | return new RestTemplate(); |
| | |
| | | package com.doumee.core.wx; |
| | | package com.doumee.config.wx; |
| | | |
| | | import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; |
| | | import com.doumee.core.constants.ResponseStatus; |
| | | import com.doumee.core.exception.BusinessException; |
| | | import com.doumee.core.utils.ID; |
| | | import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest; |
| | | import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest; |
| | | import com.github.binarywang.wxpay.bean.result.WxPayRefundResult; |
| | | import com.github.binarywang.wxpay.exception.WxPayException; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import me.chanjar.weixin.common.error.WxErrorException; |
| | | import org.apache.commons.io.IOUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.File; |
| | | import java.io.FileInputStream; |
| | | import java.io.IOException; |
| | | import java.math.BigDecimal; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 微信小程序-公共方法 |
| | |
| | | * refundPrice;退款金额 |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public static String wxRefund(String orderNo, BigDecimal totalPrice, BigDecimal refundPrice) { |
| | | public String wxRefund(String orderNo, Long totalPrice, Long refundPrice) { |
| | | try { |
| | | // 发送退款请求 |
| | | String refNum = ID.nextGUID(); |
| | | WxPayRefundRequest request = new WxPayRefundRequest(); |
| | | request.setOutTradeNo(orderNo); |
| | | request.setOutRefundNo(refNum); |
| | | // request.setTotalFee(2); |
| | | // request.setRefundFee(1); |
| | | request.setTotalFee(1);//BaseWxPayRequest.yuanToFen(totalPrice.toString())); |
| | | request.setRefundFee(1);//BaseWxPayRequest.yuanToFen(refundPrice.toString())); |
| | | request.setTotalFee(totalPrice.intValue()); |
| | | request.setRefundFee(refundPrice.intValue()); |
| | | WxPayRefundResult response = WxMiniConfig.wxPayService.refund(request); |
| | | if ("SUCCESS".equals(response.getReturnCode()) && "SUCCESS".equals(response.getResultCode())) { |
| | | return refNum; |
| | |
| | | package com.doumee.config.annotation; |
| | | package com.doumee.core.annotation; |
| | | |
| | | import java.lang.annotation.ElementType; |
| | | import java.lang.annotation.Retention; |
| | |
| | | public static final String MEMBER_FILES = "MEMBER_FILES"; |
| | | public static final String CATEGORY_FILES = "CATEGORY_FILES"; |
| | | public static final String SHOP_FILES = "SHOP_FILES"; |
| | | public static final String DRIVER_FILES = "DRIVER_FILES"; |
| | | public static final String BANNER_FILES = "BANNER_FILES"; |
| | | public static final String ORDERS_FILES = "ORDERS_FILES"; |
| | | |
| | | // 运营配置 |
| | | public static final String OPERATION_CONFIG = "OPERATION_CONFIG"; |
| | | public static final String OP_DRIVER_DAILY_CANCEL_LIMIT = "DRIVER_DAILY_CANCEL_LIMIT"; |
| | | public static final String OP_UNPICKED_DISCOUNT = "UNPICKED_DISCOUNT"; |
| | | public static final String OP_SETTLEMENT_DATE = "SETTLEMENT_DATE"; |
| | | public static final String OP_URGENT_COEFFICIENT = "URGENT_COEFFICIENT"; |
| | | public static final String OP_AUTO_CANCEL_TIME = "AUTO_CANCEL_TIME"; |
| | | public static final String OP_INSURANCE_RATE = "INSURANCE_RATE"; |
| | | public static final String OP_ORDER_ACCEPT_LIMIT = "ORDER_ACCEPT_LIMIT"; |
| | | public static final String OP_AUTO_CONFIRM_RECEIPT = "AUTO_CONFIRM_RECEIPT"; |
| | | public static boolean WORKORDER_SHE_EMAIL_SENDING = false; |
| | | public static boolean DEALING_COMPANY_SYNC = false ; |
| | | public static boolean DEALING_MEMBER_SYNC = false ; |
| | |
| | | public static final String WORKORDER_LOG_FILE_PATH ="WORKORDER_LOG_FILE_PATH" ; |
| | | |
| | | public static final String REDIS_TOKEN_KEY = "token_"; |
| | | public static final String REDIS_VERIFY_CODE_KEY = "verify_code_"; |
| | | |
| | | |
| | | |
| | | public final static String GOODS_ORDER_CREATE_LOCK = "goods:order:create:lock:"; |
| | | |
| | | // 订单日志操作类型 |
| | | public static final int ORDER_LOG_DISPATCH = 1; // 派单 |
| | | public static final int ORDER_LOG_URGENT_FEE = 2; // 加急费 |
| | | public static final int ORDER_LOG_ASSIGN_DRIVER = 3; // 指派司机 |
| | | public static final int ORDER_LOG_CANCEL = 4; // 取消订单 |
| | | public static final int ORDER_LOG_CONFIRM_ARRIVE = 5; // 确认顾客到店 |
| | | |
| | | public static final String SUCCESS = "SUCCESS"; |
| | | public static final String FAIL = "FAIL"; |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 文件附件类型 |
| | | */ |
| | | public interface multiFileType{ |
| | | //0问题上报 1跌绊滑上报 2跌绊滑处理 3分配物业主管 4分配处理人 5DCA风险上报 6DCA风险处理 7DCA问题工单图片 |
| | | // int sheUpload = 0; |
| | | // int dbhUpload = 1; |
| | | // int dbhDeal = 2; |
| | | // int dbhAllocation = 3; |
| | | // int dbhDealUser = 4; |
| | | // int dcaUpload = 5; |
| | | // int dcaDeal = 6; |
| | | // int dcaWorkOrder= 7; |
| | | |
| | | //0工单上报 1工单处理 2工单转交 |
| | | int upload = 0; |
| | | int deal = 1; |
| | | int passOn = 2; |
| | | } |
| | | |
| | | |
| | | public enum WorkOrderStatus{ |
| | | waitConfirm( 0, "待分配WTS","{title}上报","","待分配WTS" ), |
| | |
| | | OTHER_MATERIAL(0, "门店其他材料"), |
| | | STORE_INTERIOR(1, "门店内部照片"), |
| | | ORDER_DEPOSIT(2, "订单寄存图片"), |
| | | ORDER_TAKE(3, "订单取件图片"), |
| | | ORDER_TAKE(3, "门店入库图片"), |
| | | DRIVER_TAKE(4, "司机取件图片"), |
| | | DRIVER_DONE(5, "司机完成图片"), |
| | | DRIVER_CAR(6, "司机实名认证车辆照片"), |
| | |
| | | STORE_FRONT(9, "门店门头照"), |
| | | SOCIAL_SECURITY(10, "社保缴纳证明"), |
| | | LABOR_CONTRACT(11, "有效劳动合同"), |
| | | ORDER_FILE(12,"下单图片"), |
| | | STORE_OUT(13,"门店出库图片"), |
| | | REFUND_TAKE(14,"退款取件图片") |
| | | |
| | | ; |
| | | |
| | | private final int key; |
| | | private final String name; |
| | | } |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum OrderLogType { |
| | | urgent(0, "平台加急", "平台加急,奖励金 {param} 元。"), |
| | | dispatch(1, "平台指派", "平台指派司机 {param} 接单。") |
| | | ; |
| | | private int status; |
| | | private String title; |
| | | private String statusInfo; |
| | | } |
| | | |
| | | public static String getIpAddr() { |
| | | /** |
| | | * 订单支付类型 |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum OrdersAttach { |
| | | STORAGE_ORDER("storageOrder", "寄存订单"), |
| | | SHOP_DEPOSIT("shopDeposit", "店铺押金订单"), |
| | | DRIVER_DEPOSIT("driverDeposit", "司机押金订单"), |
| | | OVERDUE_FEE("overdueFee", "逾期费用订单") |
| | | ; |
| | | |
| | | private final String key; |
| | | private final String name; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 订单状态(就地/异地统一) |
| | | * 就地寄存: 0→1→2→3→(6)→7 / 96~99 |
| | | * 异地寄存: 0→1→2→3→4→5→(6)→7 / 96~99 |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum OrderStatus { |
| | | waitPay(0, "待支付"), |
| | | waitDeposit(1, "待寄存"), |
| | | deposited(2, "已寄存"), |
| | | accepted(3, "已接单"), |
| | | delivering(4, "派送中"), |
| | | arrived(5, "已到店/已送达/待取件"), |
| | | overdue(6, "存在逾期"), //弃用 |
| | | finished(7, "已完成"), |
| | | closed(96, "订单关闭(退款)"), |
| | | cancelOverdue(97, "取消逾期"), //弃用 |
| | | cancelling(98, "取消中"), |
| | | cancelled(99, "已取消") |
| | | ; |
| | | private final int status; |
| | | private final String desc; |
| | | |
| | | public int getKey() { return status; } |
| | | public String getValue() { return desc; } |
| | | |
| | | public static OrderStatus getByKey(int index) { |
| | | for (OrderStatus c : OrderStatus.values()) { |
| | | if (c.getKey() == index) { |
| | | return c; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public static String getDescByKey(int index) { |
| | | for (OrderStatus c : OrderStatus.values()) { |
| | | if (c.getKey() == index) { |
| | | return c.getValue(); |
| | | } |
| | | } |
| | | return ""; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 会员端合并订单状态(用于分页筛选) |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum OrderCombinedStatus { |
| | | waitPay(0, "待支付", new int[]{OrderStatus.waitPay.status}), |
| | | waitDeposit(1, "待核验", new int[]{OrderStatus.waitDeposit.status}), |
| | | waitDeliver(2, "待配送", new int[]{OrderStatus.deposited.status}), |
| | | waitReceive(3, "待收货", new int[]{OrderStatus.accepted.status, OrderStatus.delivering.status, OrderStatus.arrived.status}), |
| | | finished(4, "已完成", new int[]{OrderStatus.finished.status}), |
| | | refund(5, "退款", new int[]{OrderStatus.closed.status, OrderStatus.cancelling.status}) |
| | | ; |
| | | private final int key; |
| | | private final String desc; |
| | | private final int[] statuses; |
| | | |
| | | public static OrderCombinedStatus getByKey(int key) { |
| | | for (OrderCombinedStatus c : OrderCombinedStatus.values()) { |
| | | if (c.getKey() == key) { |
| | | return c; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 得到request对象 |
| | | * |
| | | * @return |
| | | */ |
| | | public static HttpServletRequest getRequest() { |
| | | HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); |
| | | return request; |
| | | } |
| | | |
| | | |
| | | public static String getIpAddr() { |
| | | HttpServletRequest request = Constants.getRequest(); |
| | | String ipAddress = null; |
| | | try { |
| | | ipAddress = request.getHeader("x-forwarded-for"); |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 根据身份证号码获取性别 |
| | | * @param idCard 身份证号码(15位或18位) |
| | | * @return 1-男,2-女,null-无法判断 |
| | | */ |
| | | public static Integer getGenderByIdCard(String idCard) { |
| | | if (idCard == null || (idCard.length() != 15 && idCard.length() != 18)) { |
| | | return null; |
| | | } |
| | | // 15位身份证:最后一位为性别码;18位身份证:第17位(索引16)为性别码 |
| | | int genderIndex = idCard.length() == 15 ? 14 : 16; |
| | | int genderCode = Character.getNumericValue(idCard.charAt(genderIndex)); |
| | | return genderCode % 2 == 1 ? 1 : 2; |
| | | } |
| | | |
| | | public static BigDecimal formatBigdecimal4Float(BigDecimal d) { |
| | | if (d == null) { |
| | | d = new BigDecimal(0.0); |
| | | } |
| | | //保留两位小数且四舍五入 |
| | | d = d.setScale(4, BigDecimal.ROUND_HALF_UP); |
| | | return d; |
| | | } |
| | | |
| | | /** |
| | | * 司机定级:5=S 4=A 3=B 2=C 1=D |
| | | * |
| | | * @param level 等级 1-5 |
| | | * @return 等级文本 |
| | | */ |
| | | public static String getDriverLevelName(Integer level) { |
| | | if (level == null) return null; |
| | | switch (level) { |
| | | case 5: return "S"; |
| | | case 4: return "A"; |
| | | case 3: return "B"; |
| | | case 2: return "C"; |
| | | case 1: return "D"; |
| | | default: return null; |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | MASSIVE_REQUEST(5101, "请求过于频繁"), |
| | | NOT_ALLOWED(5110, "不允许的操作"), |
| | | BE_OVERDUE(5112, "未登录"), |
| | | TOKEN_EXCEED_TIME(5113, "登陆已过期"), |
| | | TOKEN_EXCEED_TIME(5113, "对不起,登录已失效!"), |
| | | ; |
| | | |
| | | private int code; |
| | |
| | | package com.doumee.core.utils.Tencent;/** |
| | | * Created by IntelliJ IDEA. |
| | | * @Author : Rk |
| | | * @create 2026/4/14 15:58 |
| | | */public class MapUtil { |
| | | package com.doumee.core.utils.Tencent; |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.doumee.core.utils.Http; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.io.IOException; |
| | | import java.net.URLEncoder; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 腾讯地图工具类 |
| | | * |
| | | * @Author : Rk |
| | | * @create 2026/4/14 15:58 |
| | | */ |
| | | @Slf4j |
| | | @Component |
| | | public class MapUtil { |
| | | |
| | | private static String tencentKey; |
| | | |
| | | /** 距离矩阵API */ |
| | | public static final String MATRIX_URL = "https://apis.map.qq.com/ws/distance/v1/matrix"; |
| | | |
| | | /** 支持的模式 */ |
| | | private static final List<String> SUPPORTED_MODES = Arrays.asList("driving", "bicycling"); |
| | | |
| | | @Value("${tencent_key}") |
| | | public void setTencentKey(String tencentKey) { |
| | | MapUtil.tencentKey = tencentKey; |
| | | } |
| | | |
| | | /** |
| | | * 批量距离矩阵计算 |
| | | * |
| | | * @param mode 模式:driving(驾车)、bicycling(自行车) |
| | | * @param fromPoints 起点列表,格式:lat,lng(最多10个) |
| | | * @param toPoints 终点列表,格式:lat,lng(最多20个) |
| | | * @return result.rows 矩阵数据,每个元素包含 distance(米) 和 duration(秒) |
| | | */ |
| | | public static JSONObject distanceMatrix(String mode, List<String> fromPoints, List<String> toPoints) { |
| | | if (!SUPPORTED_MODES.contains(mode)) { |
| | | throw new IllegalArgumentException("不支持的模式: " + mode + ",仅支持: " + SUPPORTED_MODES); |
| | | } |
| | | if (fromPoints == null || fromPoints.isEmpty() || toPoints == null || toPoints.isEmpty()) { |
| | | throw new IllegalArgumentException("起点和终点列表不能为空"); |
| | | } |
| | | |
| | | String from = String.join(";", fromPoints); |
| | | String to = String.join(";", toPoints); |
| | | |
| | | try { |
| | | String url = MATRIX_URL |
| | | + "?key=" + tencentKey |
| | | + "&mode=" + mode |
| | | + "&from=" + URLEncoder.encode(from, "UTF-8") |
| | | + "&to=" + URLEncoder.encode(to, "UTF-8"); |
| | | |
| | | log.info("腾讯地图矩阵API请求: mode={}, from={}, to={}", mode, from, to); |
| | | |
| | | JSONObject json = new Http().build(url) |
| | | .setConnectTimeout(5000) |
| | | .setReadTimeout(10000) |
| | | .get() |
| | | .toJSONObject(); |
| | | |
| | | log.info("腾讯地图矩阵API响应: {}", json); |
| | | |
| | | if (json.getIntValue("status") != 0) { |
| | | throw new RuntimeException("腾讯地图矩阵API调用失败: " + json.getString("message")); |
| | | } |
| | | |
| | | return json.getJSONObject("result"); |
| | | } catch (IOException e) { |
| | | log.error("腾讯地图矩阵API调用异常", e); |
| | | throw new RuntimeException("腾讯地图矩阵API调用异常", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 单对距离计算(便捷方法) |
| | | * |
| | | * @param mode 模式:driving(驾车)、bicycling(自行车) |
| | | * @param from 起点格式:lat,lng |
| | | * @param to 终点格式:lat,lng |
| | | * @return 第一个元素的 distance(米) 和 duration(秒) |
| | | */ |
| | | public static JSONObject distanceSingle(String mode, String from, String to) { |
| | | JSONObject result = distanceMatrix(mode, |
| | | Arrays.asList(from), |
| | | Arrays.asList(to)); |
| | | JSONArray rows = result.getJSONArray("rows"); |
| | | if (rows != null && !rows.isEmpty()) { |
| | | JSONArray elements = rows.getJSONObject(0).getJSONArray("elements"); |
| | | if (elements != null && !elements.isEmpty()) { |
| | | return elements.getJSONObject(0); |
| | | } |
| | | } |
| | | return new JSONObject(); |
| | | } |
| | | |
| | | /** |
| | | * 多起点到单终点(便捷方法) |
| | | * 返回每个起点到终点的距离和耗时,顺序与fromPoints对应 |
| | | * |
| | | * @param mode 模式 |
| | | * @param fromPoints 起点列表 |
| | | * @param to 单个终点 |
| | | * @return 距离耗时列表,顺序与fromPoints对应 |
| | | */ |
| | | public static List<JSONObject> distanceToOne(String mode, List<String> fromPoints, String to) { |
| | | JSONObject result = distanceMatrix(mode, fromPoints, Arrays.asList(to)); |
| | | JSONArray rows = result.getJSONArray("rows"); |
| | | return rows == null ? Arrays.asList() : rows.stream() |
| | | .map(row -> ((JSONObject) row).getJSONArray("elements").getJSONObject(0)) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | } |
| | |
| | | import com.aliyuncs.profile.DefaultProfile; |
| | | import com.doumee.core.constants.ResponseStatus; |
| | | import com.doumee.core.exception.BusinessException; |
| | | import com.doumee.core.utils.Constants; |
| | | |
| | | import java.security.SecureRandom; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | |
| | | // 手机号 |
| | | request.putQueryParameter("PhoneNumbers", phone); |
| | | // 短信签名 |
| | | request.putQueryParameter("SignName", "合肥鼎元旋压科技"); |
| | | request.putQueryParameter("SignName", "");//合肥鼎元旋压科技 |
| | | // 短信模版CODE |
| | | request.putQueryParameter("TemplateCode", "SMS_332555204"); |
| | | request.putQueryParameter("TemplateCode", "");//SMS_332555204 |
| | | // 构建短信验证码 |
| | | request.putQueryParameter("TemplateParam", JSONObject.toJSONString(codeMap)); |
| | | try { |
| | |
| | | package com.doumee.dao.business.model; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.doumee.core.annotation.excel.ExcelColumn; |
| | |
| | | @ApiModelProperty(value = "备注") |
| | | private String remark; |
| | | |
| | | @ApiModelProperty(value = "活动主键") |
| | | private Integer title; |
| | | @ApiModelProperty(value = "标题") |
| | | private String title; |
| | | |
| | | @ApiModelProperty(value = "排序号") |
| | | private Integer sortnum; |
| | |
| | | @ApiModelProperty(value = "列表图") |
| | | private String imgurl; |
| | | |
| | | @ApiModelProperty(value = "跳转类型 0富文本 1外链", example = "0") |
| | | @ExcelColumn(name = "跳转类型", index = 3, width = 10, valueMapping = "0=富文本;1=外链;") |
| | | @ApiModelProperty(value = "跳转类型 0无 1富文本 2外链", example = "0") |
| | | @ExcelColumn(name = "跳转类型", index = 3, width = 10, valueMapping = "0无 1富文本 2外链") |
| | | private Integer type; |
| | | |
| | | @ApiModelProperty(value = "位置 0首页 1店铺首页", example = "0") |
| | | @ExcelColumn(name = "位置", index = 4, width = 10, valueMapping = "0=首页;1=店铺首页;") |
| | | @ApiModelProperty(value = "位置 0会员端首页轮播 1司机APP引导页", example = "0") |
| | | @ExcelColumn(name = "位置", index = 4, width = 10, valueMapping = "位置 0会员端首页轮播 1司机APP引导页") |
| | | private Integer position; |
| | | |
| | | @ApiModelProperty(value = "店铺主键") |
| | |
| | | |
| | | @ApiModelProperty(value = "内容") |
| | | private String content; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "图片完整路径") |
| | | private String imgurlFull; |
| | | } |
| | |
| | | private Integer createUser; |
| | | |
| | | @ApiModelProperty(value = "创建时间") |
| | | @ExcelColumn(name = "创建时间", index = 1, width = 16, dateFormat = "yyyy-MM-dd HH:mm:ss") |
| | | @ExcelColumn(name = "创建时间", index = 7, width = 18, dateFormat = "yyyy-MM-dd HH:mm:ss") |
| | | private Date createTime; |
| | | |
| | | @ApiModelProperty(value = "更新人编码", example = "1") |
| | |
| | | private String remark; |
| | | |
| | | @ApiModelProperty(value = "姓名") |
| | | @ExcelColumn(name = "姓名", index = 2, width = 10) |
| | | @ExcelColumn(name = "司机姓名", index = 1, width = 10) |
| | | private String name; |
| | | |
| | | @ApiModelProperty(value = "手机号") |
| | | @ExcelColumn(name = "手机号", index = 3, width = 12) |
| | | private String telephone; |
| | | |
| | | @ApiModelProperty(value = "性别:1=男;2=女", example = "1") |
| | | @TableField(exist = false) |
| | | @ExcelColumn(name = "性别", index = 2, width = 6, valueMapping = "1=男;2=女") |
| | | private Integer gender; |
| | | |
| | | @ApiModelProperty(value = "身份证号码") |
| | | @ExcelColumn(name = "身份证号码", index = 4, width = 18) |
| | | private String idcard; |
| | | |
| | | @ApiModelProperty(value = "婚姻状态:0=未婚;1=已婚;2=离异;3=丧偶", example = "0") |
| | | @ExcelColumn(name = "婚姻状态", index = 5, width = 10, valueMapping = "0=未婚;1=已婚;2=离异;3=丧偶;") |
| | | private Integer maritalStatus; |
| | | |
| | | @ApiModelProperty(value = "区划主键", example = "1") |
| | |
| | | private Integer carType; |
| | | |
| | | @ApiModelProperty(value = "车牌号") |
| | | @ExcelColumn(name = "车牌号", index = 6, width = 10) |
| | | @ExcelColumn(name = "车牌号", index = 6, width = 12) |
| | | private String carCode; |
| | | |
| | | @ApiModelProperty(value = "车辆颜色") |
| | |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | private Date cardEndDate; |
| | | |
| | | @ApiModelProperty(value = "司机状态:0=注册;1=待审批;2=审批通过;3=审批驳回", example = "0") |
| | | @ExcelColumn(name = "状态", index = 7, width = 10, valueMapping = "0=注册;1=待审批;2=审批通过;3=审批驳回;") |
| | | @ApiModelProperty(value = "司机状态:0=启用;1=禁用;", example = "0") |
| | | @ExcelColumn(name = "状态", index = 8, width = 8, valueMapping = "0=启用;1=禁用;") |
| | | private Integer status; |
| | | |
| | | @ApiModelProperty(value = "审批状态:0=待审批;1=审批通过;2=审批驳回", example = "0") |
| | | @ExcelColumn(name = "审批状态", index = 9, width = 10, valueMapping = "0=待审批;1=审批通过;2=审批驳回") |
| | | private Integer auditStatus; |
| | | |
| | | @ApiModelProperty(value = "OPENID(APP)") |
| | | private String openid; |
| | |
| | | @ApiModelProperty(value = "身份证反面照") |
| | | private String idcardImgBack; |
| | | |
| | | @ApiModelProperty(value = "司机定级:( 5 - 1 S A B C D )", example = "1") |
| | | private Integer driverLevel; |
| | | |
| | | @ApiModelProperty(value = "车辆照片列表") |
| | | @TableField(exist = false) |
| | | private List<Multifile> carImgList = new ArrayList<>(); |
| | |
| | | @TableField(exist = false) |
| | | private String carTypeName; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "状态列表(查询用)", example = "0,1,2") |
| | | private List<Integer> statusList; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "当前余额(单位:分)", example = "10000") |
| | | @ExcelColumn(name = "账户余额", index = 5, width = 12) |
| | | private Long memberAmount; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "图片前缀地址") |
| | | private String imgPrefix; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "查询关键字(司机姓名/手机号)") |
| | | private String keyword; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "创建开始日期") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | private Date createTimeStart; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "创建结束日期") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | private Date createTimeEnd; |
| | | |
| | | } |
| | |
| | | @ExcelColumn(name="真实姓名",index = 4,width = 10) |
| | | private String name; |
| | | |
| | | @ApiModelProperty(value = "用工身份:0=未申请;1=申请中;2=已通过;3=未通过;", example = "1") //弃用 |
| | | private Integer workerIdentity; |
| | | |
| | | @ApiModelProperty(value = "货运身份:0=未申请;1=申请中;2=已通过;3=未通过;", example = "1") //弃用 |
| | | private Integer driverIdentity; |
| | | |
| | | @ApiModelProperty(value = "供餐身份:0=未申请;1=申请中;2=已通过;3=未通过;", example = "1") //弃用 |
| | | private Integer chefIdentity; |
| | | |
| | | @ApiModelProperty(value = "当前余额(单位:分)", example = "1") |
| | | private Long amount; |
| | | |
| | |
| | | @ApiModelProperty(value = "头像全路径") |
| | | @TableField(exist = false) |
| | | private String fullCoverImage; |
| | | |
| | | @ApiModelProperty(value = "用工身份", example = "1") |
| | | @TableField(exist = false) |
| | | private IdentityInfo workerIdentityModel; |
| | | |
| | | @ApiModelProperty(value = "司机身份信息", example = "1") |
| | | @TableField(exist = false) |
| | | private IdentityInfo driverIdentityModel; |
| | | |
| | | @ApiModelProperty(value = "送餐身份信息", example = "1") |
| | | @TableField(exist = false) |
| | | private IdentityInfo chefIdentityModel; |
| | | |
| | | @ApiModelProperty(value = "接单权重", example = "1") |
| | | @TableField(exist = false) |
| | |
| | | private Integer createUser; |
| | | |
| | | @ApiModelProperty(value = "创建时间") |
| | | @ExcelColumn(name="交易时间",index = 8,dateFormat = "yyyy-MM-dd HH:mm:ss",width = 10) |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @ExcelColumn(name = "收支时间", index = 3, dateFormat = "yyyy-MM-dd HH:mm:ss", width = 16) |
| | | private Date createTime; |
| | | |
| | | @ApiModelProperty(value = "更新人编码", example = "1") |
| | |
| | | private Integer memberId; |
| | | |
| | | @ApiModelProperty(value = "变动类型:0=用工单收入;1=货运单收入;2=供餐单收入;3=提现申请;4=提现失败退回", example = "1") |
| | | @ExcelColumn(name = "业务类型", valueMapping = "0=用工单收入;1=货运单收入;2=供餐单收入;3=提现申请;4=提现失败退回;", index = 4, width = 12) |
| | | private Integer type; |
| | | |
| | | @ApiModelProperty(value = "收支类型:1=收入;-1=支出;", example = "1") |
| | | @ExcelColumn(name="收支类型", valueMapping="1=收入;-1=支出;",index = 5,width = 5) |
| | | @ExcelColumn(name = "收入/支出", valueMapping = "1=收入;-1=支出;", index = 1, width = 8) |
| | | private Integer optType; |
| | | |
| | | @ApiModelProperty(value = "变动金额", example = "1") |
| | |
| | | private Integer objType; |
| | | |
| | | @ApiModelProperty(value = "业务状态:0=成功;1=失败;2=处理中;", example = "1") |
| | | @ExcelColumn(name = "状态", valueMapping = "0=成功;1=失败;2=处理中;", index = 6, width = 8) |
| | | private Integer status; |
| | | |
| | | @ApiModelProperty(value = "变动类型:0=用工单收入;1=货运单收入;2=供餐单收入;3=提现申请;", example = "1") |
| | | @TableField(exist = false) |
| | | @ExcelColumn(name="变动业务类型",index = 7,width = 8) |
| | | private String typeName; |
| | | |
| | | @ApiModelProperty(value = "微信交易流水号", example = "1") |
| | | @ExcelColumn(name="微信交易流水号",index = 9,width = 8) |
| | | @ExcelColumn(name = "交易号", index = 5, width = 15) |
| | | private String transactionNo; |
| | | |
| | | @ApiModelProperty(value = "变查询开始时间", example = "1") |
| | |
| | | private Date endTime; |
| | | @ApiModelProperty(value = "变动金额(元)", example = "1") |
| | | @TableField(exist = false) |
| | | @ExcelColumn(name="变动金额(元)",index = 6,width = 8) |
| | | @ExcelColumn(name = "金额(元)", index = 2, width = 10) |
| | | private Double amountInfo; |
| | | |
| | | @ApiModelProperty(value = "用户姓名", example = "1") |
| | | @TableField(exist = false) |
| | | @ExcelColumn(name="用户姓名",index = 3,width = 5) |
| | | private String memberName; |
| | | |
| | | @ApiModelProperty(value = "用户昵称", example = "1") |
| | | @TableField(exist = false) |
| | | @ExcelColumn(name="用户昵称",index = 2,width = 5) |
| | | private String memberNickname; |
| | | |
| | | @ApiModelProperty(value = "用户手机号", example = "1") |
| | | @TableField(exist = false) |
| | | @ExcelColumn(name="用户手机号",index = 4,width = 6) |
| | | private String memberPhone; |
| | | |
| | | @ApiModelProperty(value = "用户openId", example = "1") |
| | | @TableField(exist = false) |
| | | @ExcelColumn(name="用户openid" ,index = 1,width = 6) |
| | | private String openid; |
| | | @ApiModelProperty(value = "用工类型:0=采摘工;1=分拣工;2=包装工", example = "1") |
| | | @TableField(exist = false) |
| | |
| | | @ApiModelProperty(value = "类型0图片 1视频 2其他", example = "1") |
| | | private Integer type; |
| | | |
| | | @ApiModelProperty(value = "关联对象类型:0=门店其他材料;1=门店内部照片;2=订单寄存图片;3=订单取件图片;4=司机取件图片;5=司机完成图片;6=司机实名认证车辆照片;" + |
| | | @ApiModelProperty(value = "关联对象类型:0=门店其他材料;1=门店内部照片;2=订单寄存图片;3=门店入库图片;4=司机取件图片;5=司机完成图片;6=司机实名认证车辆照片;" + |
| | | "7=司机实名认证驾驶证照片;8=司机实名认证其他图片;" + |
| | | "9=门店门头照;10=社保缴纳证明;11=有效劳动合同;", example = "1") |
| | | "9=门店门头照;10=社保缴纳证明;11=有效劳动合同;12=下单图片;13=门店出库图片;", example = "1") |
| | | private Integer objType; |
| | | |
| | | @ApiModelProperty(value = "文件地址") |
| | |
| | | @ApiModelProperty(value = "操作后数据") |
| | | private String afterInfo; |
| | | |
| | | @ApiModelProperty(value = "订单状态:0=待接单;1=已接单;2=进行中;3=已完成;99=已取消;", example = "0") |
| | | @ApiModelProperty(value = "订单状态:就地寄存状态:0=待支付;1=待寄存;2=已寄存;3=待取件;6=存在逾期;7=已完成;96:订单关闭(退款);97:取消逾期;98=取消中;99=已取消; " + |
| | | " 异地寄存状态:0=待支付;1=待寄存;2=已寄存;3=已接单;4=派送中;5=已到店/已送达;6=存在逾期;7=已完成;96:订单关闭(退款);97:取消逾期;98=取消中;99=已取消;", example = "0") |
| | | private Integer orderStatus; |
| | | |
| | | @ApiModelProperty(value = "操作人类型:0=用户;1=司机;2=门店;3=系统管理员", example = "0") |
| | |
| | | private Integer selfTake; |
| | | |
| | | @ApiModelProperty(value = "订单状态", example = "0") |
| | | @ExcelColumn(name = "订单状态", valueMapping = "0=待支付;1=待寄存;2=已寄存;3=待取件;6=存在逾期;7=已完成;98=已挂起;99=已取消;") |
| | | @ExcelColumn(name = "订单状态", valueMapping = "就地寄存状态:0=待支付;1=待寄存;2=已寄存;5=待取件;6=存在逾期;7=已完成;96:订单关闭(退款);97:取消逾期;98=取消中;99=已取消;" + |
| | | "异地寄存状态:0=待支付;1=待寄存;2=已寄存;3=已接单;4=派送中;5=已到店/已送达;6=存在逾期;7=已完成;96:订单关闭(退款);97:取消逾期;98=取消中;99=已取消;") |
| | | private Integer status; |
| | | |
| | | @ApiModelProperty(value = "是否异常订单:0=否;1=是", example = "0") |
| | |
| | | @ExcelColumn(name = "存件店铺") |
| | | private Integer depositShopId; |
| | | |
| | | @ApiModelProperty(value = "预计到店存件时间起") |
| | | @ApiModelProperty(value = "预计到店存件时间") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date arriveStartTime; |
| | | private Date expectedDepositTime; |
| | | |
| | | @ApiModelProperty(value = "预计到店存件时间止") |
| | | @ApiModelProperty(value = "预计到店取件时间止") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date arriveEndTime; |
| | | private Date expectedTakeTime; |
| | | |
| | | @ApiModelProperty(value = "存件地点") |
| | | @ExcelColumn(name = "存件地点") |
| | |
| | | |
| | | @ApiModelProperty(value = "存件地点描述") |
| | | @ExcelColumn(name = "存件地点描述") |
| | | private String depositLocationReamrk; |
| | | private String depositLocationRemark; |
| | | |
| | | @ApiModelProperty(value = "存件点经度") |
| | | private BigDecimal depositLat; |
| | |
| | | |
| | | @ApiModelProperty(value = "取件地点详细地址") |
| | | @ExcelColumn(name = "取件地点详细地址") |
| | | private String takeLocationReamrk; |
| | | private String takeLocationRemark; |
| | | |
| | | @ApiModelProperty(value = "取件经度") |
| | | private BigDecimal takeLat; |
| | |
| | | @ExcelColumn(name = "指派司机") |
| | | private Integer assignDriverId; |
| | | |
| | | @ApiModelProperty(value = "基础寄存费用(分)") |
| | | @ExcelColumn(name = "基础寄存费用") |
| | | private Long basicAmount; |
| | | |
| | | @ApiModelProperty(value = "订单总费用(分)") |
| | | @ExcelColumn(name = "订单总费用") |
| | | private Long totalAmount; |
| | |
| | | @ApiModelProperty(value = "逾期天数") |
| | | @ExcelColumn(name = "逾期天数") |
| | | private Integer overdueDays; |
| | | |
| | | @ApiModelProperty(value = "是否逾期: 0=否 1=是 2=已支付") |
| | | @ExcelColumn(name = "是否逾期", valueMapping = "0=否;1=是;2=已支付;") |
| | | private Integer overdueStatus; |
| | | |
| | | @ApiModelProperty(value = "会员订单核销码") |
| | | private String memberVerifyCode; |
| | | |
| | | @ApiModelProperty(value = "司机订单核销码") |
| | | private String driverVerifyCode; |
| | | |
| | | @ApiModelProperty(value = "支付状态:0=未支付;1=已支付", example = "0") |
| | | @ExcelColumn(name = "支付状态", valueMapping = "0=未支付;1=已支付;") |
| | |
| | | @ApiModelProperty(value = "结算状态:0=待结算;1=已结算;") |
| | | private Integer settlementStatus; |
| | | |
| | | @ApiModelProperty(value = "三方订单号") |
| | | private String outTradeNo; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "创建开始时间(查询用)", example = "2026-01-01") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | |
| | | @ApiModelProperty(value = "订单级别") |
| | | private String orderLevel; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "司机关键字(姓名/手机号)") |
| | | private String driverKeyword; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "寄件门店名称(关联查询)") |
| | | private String depositShopName; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "寄件门店联系人(关联查询)") |
| | | private String depositShopLinkName; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "寄件门店联系电话(关联查询)") |
| | | private String depositShopLinkPhone; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "寄件门店地址(关联查询)") |
| | | private String depositShopAddress; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "取件门店名称(关联查询)") |
| | | private String takeShopName; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "取件门店地址(关联查询)") |
| | | private String takeShopAddress; |
| | | |
| | | } |
| | |
| | | @ExcelColumn(name = "尺寸名称") |
| | | private String luggageName; |
| | | |
| | | @ApiModelProperty(value = "尺寸详情") |
| | | @ExcelColumn(name = "尺寸详情") |
| | | private String luggageDetail; |
| | | |
| | | |
| | | @ApiModelProperty(value = "数量", example = "1") |
| | | @ExcelColumn(name = "数量") |
| | | private Integer num; |
| | | |
| | | @ApiModelProperty(value = "就地存取 - 单价(分)") |
| | | @ApiModelProperty(value = "单价(分)") |
| | | @ExcelColumn(name = "单价") |
| | | private Long unitPrice; |
| | | |
| | |
| | | @ExcelColumn(name = "超出首单里程单价") |
| | | private Long extraPrice; |
| | | |
| | | @ApiModelProperty(value = "就地存取 - 单价(分)") |
| | | @ExcelColumn(name = "就地存取 - 单价") |
| | | private Long locallyPrice; |
| | | |
| | | } |
| | |
| | | @ExcelColumn(name = "类型", index = 2, width = 10, valueMapping = "0=就地存取规则;1=异地存取规则;2=预计失效;3=门店注册押金;4=分成比例;") |
| | | private Integer type; |
| | | |
| | | @ApiModelProperty(value = "参数1:type (0/1)= 关联 物品尺寸(category type =4);type (2)= 默认 1 ; type (3) = 企业类型(0=企业;1=个人);type (4) = 类型(企业/个人/配送员)") |
| | | @ApiModelProperty(value = "参数1:type (0/1)= 关联 物品尺寸(category type =4);type (2) (默认 1标速达;2=极速达) ; type (3) = 企业类型(0=企业;1=个人);type (4) = 类型(企业/个人/配送员)") |
| | | private String fieldA; |
| | | |
| | | @ApiModelProperty(value = "参数2:type (0)= 收费单价 ;type (1)= 配送起步里程公里数 ;type (2)= 起送里程 km ; type (3) = 押金;type (4) = 地点类型(寄件点/取件点/分成比例)") |
| | |
| | | |
| | | @ApiModelProperty(value = "创建时间") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @ExcelColumn(name = "创建时间", index = 6, width = 16, dateFormat = "yyyy-MM-dd HH:mm:ss") |
| | | @ExcelColumn(name = "收支时间", index = 3, width = 16, dateFormat = "yyyy-MM-dd HH:mm:ss") |
| | | private Date createTime; |
| | | |
| | | @ApiModelProperty(value = "更新人编码", example = "1") |
| | |
| | | private Integer memberType; |
| | | |
| | | @ApiModelProperty(value = "是否生效:0=入账中;1=已入账;") |
| | | @ExcelColumn(name = "是否生效", valueMapping = "0=入账中;1=已入账;", index = 5, width = 8) |
| | | @ExcelColumn(name = "状态", valueMapping = "0=入账中;1=已入账;", index = 6, width = 8) |
| | | private Integer vaildStatus; |
| | | |
| | | @ApiModelProperty(value = "类型:0=完成订单;1=提现支出;2=提现退回;3=平台奖励", example = "0") |
| | | @ExcelColumn(name = "变动类型", valueMapping = "0=完成订单;1=提现支出;2=提现退回;3=平台奖励;", index = 3, width = 10) |
| | | @ExcelColumn(name = "业务类型", valueMapping = "0=完成订单;1=提现支出;2=提现退回;3=平台奖励;", index = 4, width = 12) |
| | | private Integer type; |
| | | |
| | | @ApiModelProperty(value = "收支类型:1=收入;-1=支出", example = "1") |
| | | @ExcelColumn(name = "收支类型", valueMapping = "1=收入;-1=支出;", index = 1, width = 8) |
| | | @ExcelColumn(name = "收入/支出", valueMapping = "1=收入;-1=支出;", index = 1, width = 8) |
| | | private Integer optType; |
| | | |
| | | @ApiModelProperty(value = "金额(分)") |
| | |
| | | private Integer status; |
| | | |
| | | @ApiModelProperty(value = "订单号") |
| | | @ExcelColumn(name = "订单号", index = 4, width = 16) |
| | | @ExcelColumn(name = "交易号", index = 5, width = 16) |
| | | private String orderNo; |
| | | |
| | | @ApiModelProperty(value = "查询开始时间") |
| | |
| | | |
| | | @ApiModelProperty(value = "变动金额(元)") |
| | | @TableField(exist = false) |
| | | @ExcelColumn(name = "变动金额(元)", index = 2, width = 10) |
| | | @ExcelColumn(name = "金额(元)", index = 2, width = 10) |
| | | private Double amountInfo; |
| | | |
| | | } |
| | |
| | | @ApiModelProperty(value = "审批备注") |
| | | private String auditRemark; |
| | | |
| | | @ApiModelProperty(value = "OPENID") |
| | | @ApiModelProperty(value = "当前登录用户openid") |
| | | private String openid; |
| | | |
| | | @ApiModelProperty(value = "支付状态:0=待支付;1=已支付", example = "0") |
| | |
| | | |
| | | @ApiModelProperty(value = "配送范围(km)") |
| | | private BigDecimal deliveryArea; |
| | | |
| | | @ApiModelProperty(value = "支付宝提现账户") |
| | | private String aliAccount; |
| | | |
| | | @ApiModelProperty(value = "营业时间") |
| | | private String shopHours; |
| | | |
| | | @ApiModelProperty(value = "门店介绍") |
| | | private String content; |
| | | |
| | | @ApiModelProperty(value = "门店头像") |
| | | private String coverImg; |
| | | |
| | | @ApiModelProperty(value = "寄存类型(逗号分隔的category主键)") |
| | | private String depositTypes; |
| | | |
| | | @ApiModelProperty(value = "收费标准") |
| | | private String feeStandard; |
| | | |
| | | @ApiModelProperty(value = "门店营业类型:0=非全天;1=全天", example = "0") |
| | | private Integer businessType; |
| | | |
| | | |
| | | // 非持久化:附件列表 |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "门店门头照", hidden = true) |
| | |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | private Date createEndTime; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "审批状态列表(查询用,逗号分隔)", example = "0,1,2") |
| | | private List<Integer> auditStatusList; |
| | | |
| | | } |
| | |
| | | private String remark; |
| | | |
| | | @ApiModelProperty(value = "手机号") |
| | | private Integer memberId; |
| | | |
| | | @ApiModelProperty(value = "手机号") |
| | | @ExcelColumn(name = "手机号", index = 2, width = 12) |
| | | private String phone; |
| | | |
| | |
| | | @ExcelColumn(name = "会员主键") |
| | | private Integer memberId; |
| | | |
| | | @ApiModelProperty(value = "用户类型:1= 司机;2=店铺;", example = "1") |
| | | @ExcelColumn(name = "用户类型:1= 司机;2=店铺;") |
| | | private Integer memberType; |
| | | |
| | | |
| | | @ApiModelProperty(value = "提现金额(单位:分)") |
| | | @ExcelColumn(name = "提现金额") |
| | | private Long amount; |
| | |
| | | @ExcelColumn(name = "提现申请单号") |
| | | private String outBillNo; |
| | | |
| | | @ApiModelProperty(value = "支付宝提现账户") |
| | | private String aliAccount; |
| | | |
| | | @ApiModelProperty(value = "审批操作人(关联system_user)", example = "1") |
| | | private Integer userId; |
| | | |
| | | @ApiModelProperty(value = "审批时间") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date approveTime; |
| | | |
| | | @ApiModelProperty(value = "审批备注") |
| | | private String approveRemark; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "创建开始时间(查询用)", example = "2026-01-01") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | private Date createEndTime; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "审批人名称") |
| | | private String updateUserName; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "司机姓名") |
| | | private String memberName; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "司机联系电话") |
| | | private String memberTelephone; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "门店名称") |
| | | private String shopName; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "联系人") |
| | | private String linkName; |
| | | |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "门店详情") |
| | | private ShopInfo shopInfo; |
| | | |
| | | } |
| | |
| | | @ApiModelProperty(value = "审批描述") |
| | | private String auditRemark; |
| | | |
| | | @ApiModelProperty(value = "司机定级:5=S;4=A;3=B;2=C;1=D(审批通过时必填)", example = "5") |
| | | private Integer driverLevel; |
| | | |
| | | @ApiModelProperty(value = "审批人编码(服务端填充)", hidden = true) |
| | | private Integer auditUser; |
| | | |
| | |
| | | |
| | | import javax.validation.constraints.NotNull; |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 预计时效配置保存请求 |
| | |
| | | @NotNull(message = "城市主键不能为空") |
| | | private Integer cityId; |
| | | |
| | | @ApiModelProperty(value = "起送里程(公里)", required = true, example = "10") |
| | | @NotNull(message = "起送里程不能为空") |
| | | private String startDistance; |
| | | @ApiModelProperty(value = "时效配置列表(fieldA=1标速达,fieldA=2极速达)") |
| | | @NotNull(message = "时效配置列表不能为空") |
| | | private List<EstimatedDeliveryItem> items; |
| | | |
| | | @ApiModelProperty(value = "起送时长", required = true, example = "2") |
| | | @NotNull(message = "起送时长不能为空") |
| | | private String startTime; |
| | | @Data |
| | | @ApiModel("预计时效配置项") |
| | | public static class EstimatedDeliveryItem implements Serializable { |
| | | |
| | | @ApiModelProperty(value = "续送里程(公里)", required = true, example = "5") |
| | | @NotNull(message = "续送里程不能为空") |
| | | private String continueDistance; |
| | | @ApiModelProperty(value = "类型:1=标速达;2=极速达", required = true, example = "1") |
| | | @NotNull(message = "类型不能为空") |
| | | private Integer fieldA; |
| | | |
| | | @ApiModelProperty(value = "续送时长", required = true, example = "1") |
| | | @NotNull(message = "续送时长不能为空") |
| | | private String continueTime; |
| | | @ApiModelProperty(value = "起送里程(公里)", required = true, example = "10") |
| | | @NotNull(message = "起送里程不能为空") |
| | | private String startDistance; |
| | | |
| | | @ApiModelProperty(value = "起送时长", required = true, example = "2") |
| | | @NotNull(message = "起送时长不能为空") |
| | | private String startTime; |
| | | |
| | | @ApiModelProperty(value = "续送里程(公里)", required = true, example = "5") |
| | | @NotNull(message = "续送里程不能为空") |
| | | private String continueDistance; |
| | | |
| | | @ApiModelProperty(value = "续送时长", required = true, example = "1") |
| | | @NotNull(message = "续送时长不能为空") |
| | | private String continueTime; |
| | | } |
| | | } |
| | |
| | | @ApiModelProperty(value = "司机每日取消次数", required = true) |
| | | private String driverDailyCancelLimit; |
| | | |
| | | @ApiModelProperty(value = "未取件折扣", required = true) |
| | | @ApiModelProperty(value = "未取件逾期折扣", required = true) |
| | | private String unpickedDiscount; |
| | | |
| | | @ApiModelProperty(value = "订单结算日期", required = true) |
| | |
| | | package com.doumee.dao.web.dto; |
| | | package com.doumee.dao.dto; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel("经销商登录请求对象") |
| | | @ApiModel("门店登录请求对象") |
| | | public class ShopLoginDTO { |
| | | |
| | | // @ApiModelProperty(value = "关联用户主键") |
| | | // private Integer memberId; |
| | | |
| | | @ApiModelProperty(value = "openid") |
| | | private String openid; |
| | | |
| | | @ApiModelProperty(value = "用户名称") |
| | | private String userName; |
| | | @ApiModelProperty(value = "登录手机号") |
| | | private String telephone; |
| | | |
| | | @ApiModelProperty(value = "密码") |
| | | private String password; |
| | |
| | | package com.doumee.dao.web.request; |
| | | package com.doumee.dao.dto; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * Created by IntelliJ IDEA. |
| | |
| | | @ApiModelProperty(value = "用户信息") |
| | | private Member member; |
| | | |
| | | @ApiModelProperty(value = "我注册的门店主键(门店用户时返回)") |
| | | private Integer shopId; |
| | | |
| | | @ApiModelProperty(value = "我注册的门店审核状态(门店用户时返回): 0=待审核 1=已通过 2=已驳回 3=已缴纳保证金") |
| | | private Integer shopAuditStatus; |
| | | |
| | | @ApiModelProperty(value = "门店token") |
| | | private String loginShopToken; |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | @ApiModelProperty(value = "城市主键") |
| | | private Integer cityId; |
| | | |
| | | @ApiModelProperty(value = "类型:1=标速达;2=极速达") |
| | | private Integer fieldA; |
| | | |
| | | @ApiModelProperty(value = "起送里程(公里)") |
| | | private String startDistance; |
| | | |
| | |
| | | @ApiModelProperty("物品类型名称") |
| | | private String categoryName; |
| | | |
| | | @ApiModelProperty("物品类型详情(寄存说明)") |
| | | private String detail; |
| | | |
| | | @ApiModelProperty("数量") |
| | | private Integer quantity; |
| | | |
| | |
| | | |
| | | @ApiModelProperty("超出距离单价(分)") |
| | | private Long extraPrice; |
| | | |
| | | @ApiModelProperty("就地存取单价(分/天)") |
| | | private Long locallyPrice; |
| | | } |
| | |
| | | @ApiModelProperty(value = "会员姓名") |
| | | private String name; |
| | | |
| | | @ApiModelProperty(value = "openid") |
| | | private String openid; |
| | | |
| | | @ApiModelProperty(value = "授权手机号") |
| | | private String telephone; |
| | | |
| | |
| | | package com.doumee.dao.vo; |
| | | |
| | | import com.doumee.dao.business.model.Orders; |
| | | import com.doumee.dao.business.model.OrdersRefund; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | |
| | | private List<String> storeOutImages; |
| | | |
| | | @ApiModelProperty(value = "物品明细列表") |
| | | private List<OrderDetailItemVO> detailList; |
| | | private List<OrderItemVO> detailList; |
| | | |
| | | /** |
| | | * 物品明细项 |
| | | */ |
| | | @Data |
| | | @ApiModel("物品明细项") |
| | | public static class OrderDetailItemVO { |
| | | @ApiModelProperty(value = "退款记录(订单状态为取消/退款时返回)") |
| | | private OrdersRefund ordersRefund; |
| | | |
| | | @ApiModelProperty(value = "尺寸名称") |
| | | private String luggageName; |
| | | @ApiModelProperty(value = "退款取件图片(已存件申请取消时返回)") |
| | | private List<String> refundTakeImages; |
| | | |
| | | @ApiModelProperty(value = "数量") |
| | | private Integer num; |
| | | @ApiModelProperty(value = "平台操作人名称(平台直接取消时返回)") |
| | | private String platformUserName; |
| | | |
| | | @ApiModelProperty(value = "单价(元)") |
| | | private Double unitPriceYuan; |
| | | |
| | | @ApiModelProperty(value = "小计费用(元)") |
| | | private Double subtotal; |
| | | } |
| | | @ApiModelProperty(value = "接单司机姓名") |
| | | private String driverName; |
| | | } |
| | |
| | | private String typeDesc; |
| | | |
| | | @ApiModelProperty(value = "订单物品详情") |
| | | private List<DispatchItemVO> detailList; |
| | | |
| | | /** |
| | | * 物品明细项 |
| | | */ |
| | | @Data |
| | | @ApiModel("派单物品明细项") |
| | | public static class DispatchItemVO { |
| | | |
| | | @ApiModelProperty(value = "尺寸名称") |
| | | private String luggageName; |
| | | |
| | | @ApiModelProperty(value = "数量") |
| | | private Integer num; |
| | | |
| | | @ApiModelProperty(value = "单价(元)") |
| | | private Double unitPriceYuan; |
| | | |
| | | @ApiModelProperty(value = "小计费用(元)") |
| | | private Double subtotal; |
| | | } |
| | | private List<OrderItemVO> detailList; |
| | | } |
| | |
| | | @ApiModel("订单物品明细项") |
| | | public class OrderItemVO { |
| | | |
| | | @ApiModelProperty(value = "分类名称") |
| | | private String typeName; |
| | | |
| | | @ApiModelProperty(value = "尺寸名称") |
| | | private String luggageName; |
| | | |
| | | @ApiModelProperty(value = "尺寸详情") |
| | | private String luggageDetail; |
| | | |
| | | @ApiModelProperty(value = "数量") |
| | | private Integer num; |
| | | |
| | |
| | | package com.doumee.dao.web.response.goods; |
| | | package com.doumee.dao.vo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | |
| | | |
| | | @ApiModelProperty(value = "支付订单主键") |
| | | private Integer orderId; |
| | | |
| | | @ApiModelProperty(value = "支付类型:0=现金支付;1=纯积分支付") |
| | | private Integer payType; |
| | | |
| | | @ApiModelProperty(value = "微信调起业务") |
| | | private Object response; |
| | |
| | | @ApiModelProperty(value = "身份证正面照") |
| | | private String idcardImg; |
| | | |
| | | @ApiModelProperty(value = "身份证正面照(全路径)") |
| | | private String idcardImgUrl; |
| | | |
| | | @ApiModelProperty(value = "身份证反面照") |
| | | private String idcardImgBack; |
| | | |
| | | @ApiModelProperty(value = "身份证反面照(全路径)") |
| | | private String idcardImgBackUrl; |
| | | |
| | | @ApiModelProperty(value = "营业执照") |
| | | private String businessImg; |
| | | |
| | | @ApiModelProperty(value = "营业执照(全路径)") |
| | | private String businessImgUrl; |
| | | |
| | | @ApiModelProperty(value = "审批状态:0=待审批;1=审批通过;2=审批未通过;3=已支付押金") |
| | | private Integer auditStatus; |
| | |
| | | |
| | | @ApiModelProperty(value = "审批备注") |
| | | private String auditRemark; |
| | | |
| | | @ApiModelProperty(value = "审批人名称") |
| | | private String auditName; |
| | | |
| | | |
| | | @ApiModelProperty(value = "OPENID") |
| | | private String openid; |
| | |
| | | |
| | | @ApiModelProperty(value = "配送范围(km)") |
| | | private BigDecimal deliveryArea; |
| | | // 附件列表 |
| | | // 附件列表(半路径) |
| | | @ApiModelProperty(value = "门店门头照") |
| | | private List<String> storeFrontImgs; |
| | | |
| | |
| | | @ApiModelProperty(value = "社保缴纳证明") |
| | | private List<String> socialSecurityImgs; |
| | | |
| | | // 附件列表(全路径) |
| | | @ApiModelProperty(value = "门店门头照(全路径)") |
| | | private List<String> storeFrontImgUrls; |
| | | |
| | | @ApiModelProperty(value = "门店内部照(全路径)") |
| | | private List<String> storeInteriorImgUrls; |
| | | |
| | | @ApiModelProperty(value = "其他材料(全路径)") |
| | | private List<String> otherMaterialImgUrls; |
| | | |
| | | @ApiModelProperty(value = "有效劳动合同(全路径)") |
| | | private List<String> laborContractImgUrls; |
| | | |
| | | @ApiModelProperty(value = "社保缴纳证明(全路径)") |
| | | private List<String> socialSecurityImgUrls; |
| | | |
| | | @ApiModelProperty(value = "图片前缀地址") |
| | | private String imgPrefix; |
| | | |
| | |
| | | @ApiModelProperty(value = "服务介绍") |
| | | private String serverIntroduce; |
| | | |
| | | @ApiModelProperty(value = "收费标准") |
| | | private String feeStandards; |
| | | |
| | | @ApiModelProperty(value = "关于我们") |
| | | private String aboutUs; |
| | | |
| | |
| | | * 根据ID查询地址(含省市区信息) |
| | | */ |
| | | Addr findByIdWithArea(Integer id); |
| | | |
| | | /** |
| | | * 小程序端新增地址 |
| | | */ |
| | | Integer createByMember(Addr addr, Integer memberId); |
| | | |
| | | /** |
| | | * 小程序端修改地址 |
| | | */ |
| | | void updateByMember(Addr addr, Integer memberId); |
| | | } |
| | |
| | | |
| | | List<Areas> getCityList(Areas areas); |
| | | |
| | | /** |
| | | * 查询已开放的城市列表(status=1,type=1),附带首字母并按首字母排序 |
| | | * |
| | | * @return 城市列表 |
| | | */ |
| | | List<Areas> getOpenCityList(); |
| | | |
| | | } |
| | |
| | | |
| | | PageData<Banner> findPage(PageWrap<Banner> pageWrap); |
| | | |
| | | void updateStatus(Banner banner); |
| | | |
| | | long count(Banner banner); |
| | | |
| | | /** |
| | | * 根据位置获取轮播图列表(含图片全路径) |
| | | * @param position 位置 |
| | | */ |
| | | List<Banner> findListByPosition(Integer position); |
| | | } |
| | |
| | | |
| | | |
| | | List<Category> getCategoryList(Integer type); |
| | | |
| | | /** |
| | | * 根据城市主键查询已开通的物品尺寸(category type=4) |
| | | * 通过 pricing_rule type=1 city_id 关联 category.id = pricing_rule.fieldA |
| | | * @param cityId 城市主键 |
| | | * @return 物品尺寸列表 |
| | | */ |
| | | List<Category> getCitySizeList(Integer cityId); |
| | | } |
| | |
| | | */ |
| | | void auditVerify(com.doumee.dao.dto.AuditDTO auditDTO); |
| | | |
| | | /** |
| | | * 管理端查询司机详情(含附件图片、车辆类型名称) |
| | | * |
| | | * @param id 司机主键 |
| | | * @return DriverInfo |
| | | */ |
| | | DriverInfo getDetail(Integer id); |
| | | |
| | | /** |
| | | * 修改司机状态(启用/禁用) |
| | | * |
| | | * @param dto 修改状态请求 |
| | | */ |
| | | void changeStatus(com.doumee.dao.dto.ChangeStatusDTO dto); |
| | | |
| | | } |
| | |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.dao.business.model.Member; |
| | | import com.doumee.dao.dto.MemberListQueryDTO; |
| | | import com.doumee.dao.dto.UpdMobileRequest; |
| | | import com.doumee.dao.dto.WxPhoneRequest; |
| | | import com.doumee.dao.vo.AccountResponse; |
| | | import com.doumee.dao.vo.MemberDetailVO; |
| | | import com.doumee.dao.vo.MemberListVO; |
| | | import com.doumee.dao.vo.UserCenterVO; |
| | | import me.chanjar.weixin.common.error.WxErrorException; |
| | | import org.apache.commons.lang3.StringUtils; |
| | |
| | | */ |
| | | void editMemberInfo(Member member); |
| | | |
| | | // /** |
| | | // * 切换用工身份 |
| | | // * @param member |
| | | // */ |
| | | // void editUseIdentity(Member member); |
| | | |
| | | /** |
| | | * 个人信息 |
| | | * @param memberId |
| | |
| | | void logOut(String token,Integer memberId); |
| | | |
| | | void logOff(String token,Integer memberId); |
| | | |
| | | |
| | | /** |
| | | * 验证手机号 |
| | | * @param request |
| | | */ |
| | | void verifyUserPhone(UpdMobileRequest request); |
| | | |
| | | /** |
| | | * 换绑手机号 |
| | | * @param request |
| | | */ |
| | | void updateUserPhone(UpdMobileRequest request); |
| | | |
| | | |
| | | /***************管理端会员列表接口*************/ |
| | | |
| | | /** |
| | | * 会员列表分页查询 |
| | | * |
| | | * @param pageWrap 分页对象(model为MemberListQueryDTO) |
| | | * @return PageData<MemberListVO> |
| | | */ |
| | | PageData<MemberListVO> findMemberListPage(PageWrap<MemberListQueryDTO> pageWrap); |
| | | |
| | | /** |
| | | * 查询会员详情 |
| | | * |
| | | * @param id 会员ID |
| | | * @return MemberDetailVO |
| | | */ |
| | | MemberDetailVO findMemberDetail(Integer id); |
| | | } |
| | |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.dao.business.model.Orders; |
| | | import com.doumee.dao.dto.CalculateLocalPriceDTO; |
| | | import com.doumee.dao.dto.CalculateRemotePriceDTO; |
| | | import com.doumee.dao.dto.CreateOrderDTO; |
| | | import com.doumee.dao.dto.DispatchDTO; |
| | | import com.doumee.dao.dto.MyOrderDTO; |
| | | import com.doumee.dao.vo.MyOrderDetailVO; |
| | | import com.doumee.dao.vo.MyOrderVO; |
| | | import com.doumee.dao.vo.OrderDetailVO; |
| | | import com.doumee.dao.vo.OrderDispatchVO; |
| | | import com.doumee.dao.vo.OrderSummaryVO; |
| | | import com.doumee.dao.vo.OverdueFeeVO; |
| | | import com.doumee.dao.vo.PayResponse; |
| | | import com.doumee.dao.vo.PriceCalculateVO; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | */ |
| | | long count(Orders orders); |
| | | |
| | | /** |
| | | * 查询订单详情 |
| | | * |
| | | * @param id 主键 |
| | | * @return OrderDetailVO |
| | | */ |
| | | OrderDetailVO findDetail(Integer id); |
| | | |
| | | /** |
| | | * 会员端订单详情 |
| | | * |
| | | * @param id 订单主键 |
| | | * @param memberId 会员主键 |
| | | * @return MyOrderDetailVO |
| | | */ |
| | | MyOrderDetailVO findMyOrderDetail(Integer id, Integer memberId); |
| | | |
| | | /** |
| | | * 会员取消订单(仅异地寄存) |
| | | * |
| | | * @param orderId 订单主键 |
| | | * @param memberId 会员主键 |
| | | * @param reason 取消原因 |
| | | */ |
| | | void cancelOrder(Integer orderId, Integer memberId, String reason); |
| | | |
| | | /** |
| | | * 寄存订单支付回调处理 |
| | | * |
| | | * @param outTradeNo 商户订单号 |
| | | * @param wxTradeNo 微信订单号 |
| | | */ |
| | | void handleStorageOrderPayNotify(String outTradeNo, String wxTradeNo); |
| | | |
| | | /** |
| | | * 门店核销收件 |
| | | * |
| | | * @param verifyCode 核销码 |
| | | * @param shopId 门店主键 |
| | | * @param images 图片地址列表(最多3张) |
| | | * @param remark 备注 |
| | | */ |
| | | void shopVerifyOrder(String verifyCode, Integer shopId, List<String> images, String remark); |
| | | |
| | | /** |
| | | * 门店端查询订单详情 |
| | | * 支持按订单主键或核销码查询,复用会员端详情逻辑 |
| | | * |
| | | * @param orderId 订单主键(与verifyCode二选一) |
| | | * @param verifyCode 核销码(与orderId二选一) |
| | | * @return 订单详情 |
| | | */ |
| | | MyOrderDetailVO findShopOrderDetail(Integer orderId, String verifyCode); |
| | | |
| | | /** |
| | | * 查询手动派单信息 |
| | | * |
| | | * @param id 订单主键 |
| | | * @return OrderDispatchVO |
| | | */ |
| | | OrderDispatchVO findDispatchInfo(Integer id); |
| | | |
| | | /** |
| | | * 订单派单 |
| | | * |
| | | * @param dto 派单参数 |
| | | */ |
| | | void dispatch(DispatchDTO dto); |
| | | |
| | | /** |
| | | * 根据分页查询条件统计订单汇总 |
| | | * |
| | | * @param pageWrap 分页查询条件 |
| | | * @return OrderSummaryVO |
| | | */ |
| | | OrderSummaryVO findSummary(PageWrap<Orders> pageWrap); |
| | | |
| | | /** |
| | | * 计算保价费用 |
| | | * @param declaredValue 报价金额 |
| | | * @return 保价费用 |
| | | */ |
| | | BigDecimal calculateInsuranceFee(BigDecimal declaredValue); |
| | | |
| | | /** |
| | | * 计算就地存取预估费用 |
| | | * @param dto 就地存取计价请求参数 |
| | | * @return 价格计算结果 |
| | | */ |
| | | PriceCalculateVO calculateLocalPrice(CalculateLocalPriceDTO dto); |
| | | |
| | | /** |
| | | * 计算异地存取预估费用 |
| | | * @param dto 异地存取计价请求参数 |
| | | * @return 价格计算结果 |
| | | */ |
| | | PriceCalculateVO calculateRemotePrice(CalculateRemotePriceDTO dto); |
| | | |
| | | /** |
| | | * 创建订单并唤起微信支付 |
| | | * @param dto 创建订单请求参数 |
| | | * @param memberId 当前登录会员ID |
| | | * @return 支付响应 |
| | | */ |
| | | PayResponse createOrder(CreateOrderDTO dto, Integer memberId); |
| | | |
| | | /** |
| | | * 继续支付(待支付订单重新唤起微信支付) |
| | | * @param orderId 订单主键 |
| | | * @param memberId 当前登录会员ID |
| | | * @return 支付响应 |
| | | */ |
| | | PayResponse continuePay(Integer orderId, Integer memberId); |
| | | |
| | | /** |
| | | * 小程序端-查询我的订单分页 |
| | | * @param pageWrap 分页查询参数(model含status) |
| | | * @param memberId 会员主键 |
| | | * @return 分页结果 |
| | | */ |
| | | PageData<MyOrderVO> findMyOrderPage(PageWrap<MyOrderDTO> pageWrap, Integer memberId); |
| | | |
| | | /** |
| | | * 查询订单超时费用 |
| | | * @param orderId 订单主键 |
| | | * @return 超时费用计算结果 |
| | | */ |
| | | OverdueFeeVO calculateOverdueFee(Integer orderId); |
| | | |
| | | /** |
| | | * 司机核销(异地寄存且有取件门店) |
| | | * 派送中(4) → 已到店(5),校验司机核销码 |
| | | * |
| | | * @param verifyCode 司机核销码 |
| | | * @param images 图片地址列表(最多3张) |
| | | * @param remark 备注 |
| | | * @param driverId 司机(会员)主键 |
| | | */ |
| | | void driverVerifyOrder(String verifyCode, List<String> images, String remark, Integer driverId); |
| | | |
| | | /** |
| | | * 确认顾客已到店 |
| | | * 就地寄存/异地寄存,且存在取件门店,状态为待取件(5) |
| | | * 检查逾期状态:逾期则标记逾期,未逾期则完成订单 |
| | | * |
| | | * @param orderId 订单主键 |
| | | * @param shopId 当前操作门店主键 |
| | | */ |
| | | void confirmCustomerArrived(Integer orderId, Integer shopId); |
| | | |
| | | } |
| | |
| | | import com.doumee.dao.vo.StoreDepositVO; |
| | | import com.doumee.dao.vo.RevenueShareVO; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | List<RemoteDeliveryPricingVO> listRemoteDeliveryPricing(Integer cityId); |
| | | |
| | | /** |
| | | * 保存预计时效配置(有则更新,无则新增) |
| | | * 保存预计时效配置(标速达fieldA=1 + 极速达fieldA=2,有则更新无则新增) |
| | | * @param request 保存请求 |
| | | */ |
| | | void saveEstimatedDelivery(EstimatedDeliverySaveDTO request); |
| | | |
| | | /** |
| | | * 查询预计时效配置(有且只有一条,无数据返回空对象) |
| | | * 查询预计时效配置列表(标速达fieldA=1 + 极速达fieldA=2) |
| | | * @param cityId 城市主键 |
| | | * @return 预计时效配置 |
| | | * @return 预计时效配置列表 |
| | | */ |
| | | EstimatedDeliveryVO getEstimatedDelivery(Integer cityId); |
| | | List<EstimatedDeliveryVO> getEstimatedDelivery(Integer cityId); |
| | | |
| | | /** |
| | | * 根据城市、类型、距离计算预计时效时长 |
| | | * @param cityId 城市主键 |
| | | * @param fieldA 类型:1=标速达;2=极速达 |
| | | * @param distance 距离(公里) |
| | | * @return 预计时长(小时),未找到配置返回null |
| | | */ |
| | | BigDecimal calculateEstimatedTime(Integer cityId, Integer fieldA, BigDecimal distance); |
| | | |
| | | /** |
| | | * 批量保存门店注册押金 |
| | |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.dao.business.model.ShopInfo; |
| | | import com.doumee.dao.business.model.Member; |
| | | import com.doumee.dao.dto.AuditDTO; |
| | | import com.doumee.dao.dto.ChangeStatusDTO; |
| | | import com.doumee.dao.dto.ResetPasswordDTO; |
| | | import com.doumee.dao.dto.ShopApplyDTO; |
| | | import com.doumee.dao.dto.ShopUpdateDTO; |
| | | import com.doumee.dao.dto.*; |
| | | import com.doumee.dao.vo.ShopLoginVO; |
| | | import com.doumee.dao.vo.ShopDetailVO; |
| | | import com.doumee.dao.vo.ShopNearbyVO; |
| | | import com.doumee.dao.vo.ShopWebDetailVO; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | */ |
| | | void updateShop(ShopUpdateDTO dto); |
| | | |
| | | /** |
| | | * 根据经纬度查询附近门店分页列表(启用+已交付押金,按距离升序) |
| | | * @param dto 查询请求 |
| | | * @return 附近门店分页列表 |
| | | */ |
| | | PageData<ShopNearbyVO> findNearbyShops(PageWrap<ShopNearbyDTO> pageWrap); |
| | | |
| | | /** |
| | | * 查询门店详情(小程序端,含照片集合和可选距离) |
| | | * @param dto 查询请求 |
| | | * @return 门店详情 |
| | | */ |
| | | ShopWebDetailVO getShopWebDetail(ShopDetailQueryDTO dto); |
| | | |
| | | /** |
| | | * 维护门店信息(支付押金后可操作) |
| | | * @param memberId 会员主键 |
| | | * @param dto 维护请求 |
| | | */ |
| | | void maintainShopInfo(Integer memberId, ShopInfoMaintainDTO dto); |
| | | |
| | | /** |
| | | * 查询门店维护信息(小程序端) |
| | | * @param memberId 会员主键 |
| | | * @return 门店信息,无则返回null |
| | | */ |
| | | ShopInfoMaintainDTO getShopMaintainInfo(Integer memberId); |
| | | |
| | | |
| | | /** |
| | | * 门店密码登录 |
| | | * @param dto 登录请求 |
| | | * @return 登录结果 |
| | | */ |
| | | ShopLoginVO shopPasswordLogin(ShopLoginDTO dto); |
| | | |
| | | /** |
| | | * 门店静默登录(根据openid) |
| | | * @param openid |
| | | * @return 登录结果 |
| | | */ |
| | | ShopLoginVO shopSilentLogin(String openid); |
| | | |
| | | } |
| | |
| | | */ |
| | | long count(Smsrecord smsrecord); |
| | | |
| | | |
| | | void sendSms(Integer memberId,String phone); |
| | | |
| | | |
| | | void verifyCode(Integer memberId,String phone,String code); |
| | | |
| | | } |
| | |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.dao.business.model.WithdrawalOrders; |
| | | import com.doumee.dao.dto.WithdrawalApproveDTO; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | */ |
| | | long count(WithdrawalOrders withdrawalOrders); |
| | | |
| | | /** |
| | | * 已提现统计金额(status=0/1),使用与分页查询相同的条件 |
| | | * |
| | | * @param pageWrap 分页查询条件 |
| | | * @return 已提现总金额(单位:分) |
| | | */ |
| | | Long totalAmount(PageWrap<WithdrawalOrders> pageWrap); |
| | | |
| | | /** |
| | | * 提现审批 |
| | | * |
| | | * @param dto 审批参数 |
| | | */ |
| | | void approve(WithdrawalApproveDTO dto); |
| | | |
| | | } |
| | |
| | | import com.doumee.dao.business.AddrMapper; |
| | | import com.doumee.dao.business.model.Addr; |
| | | import com.doumee.service.business.AddrService; |
| | | import com.github.yulichang.wrapper.MPJLambdaWrapper; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.apache.shiro.SecurityUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | QueryWrapper<Addr> wrapper = new QueryWrapper<>(addr); |
| | | return addrMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | @Override |
| | | public List<Addr> findListWithArea(Integer memberId) { |
| | | MPJLambdaWrapper<Addr> wrapper = new MPJLambdaWrapper<Addr>() |
| | | .selectAll(Addr.class) |
| | | .select("a3.name", Addr::getDistrictName) |
| | | .select("a3.code", Addr::getDistrictCode) |
| | | .select("a2.id", Addr::getCityId) |
| | | .select("a2.name", Addr::getCityName) |
| | | .select("a2.code", Addr::getCityCode) |
| | | .select("a1.id", Addr::getProvinceId) |
| | | .select("a1.name", Addr::getProvinceName) |
| | | .select("a1.code", Addr::getProvinceCode) |
| | | .leftJoin("areas a3 on a3.id = t.AREA_ID") |
| | | .leftJoin("areas a2 on a2.id = a3.PARENT_ID") |
| | | .leftJoin("areas a1 on a1.id = a2.PARENT_ID") |
| | | .eq(Addr::getDeleted, Constants.ZERO) |
| | | .eq(Addr::getMemberId, memberId) |
| | | .orderByDesc(Addr::getIsDefault) |
| | | .orderByDesc(Addr::getCreateTime); |
| | | return addrMapper.selectJoinList(Addr.class, wrapper); |
| | | } |
| | | |
| | | @Override |
| | | public Addr findByIdWithArea(Integer id) { |
| | | MPJLambdaWrapper<Addr> wrapper = new MPJLambdaWrapper<Addr>() |
| | | .selectAll(Addr.class) |
| | | .select("a3.name", Addr::getDistrictName) |
| | | .select("a3.code", Addr::getDistrictCode) |
| | | .select("a2.id", Addr::getCityId) |
| | | .select("a2.name", Addr::getCityName) |
| | | .select("a2.code", Addr::getCityCode) |
| | | .select("a1.id", Addr::getProvinceId) |
| | | .select("a1.name", Addr::getProvinceName) |
| | | .select("a1.code", Addr::getProvinceCode) |
| | | .leftJoin("areas a3 on a3.id = t.AREA_ID") |
| | | .leftJoin("areas a2 on a2.id = a3.PARENT_ID") |
| | | .leftJoin("areas a1 on a1.id = a2.PARENT_ID") |
| | | .eq(Addr::getId, id); |
| | | Addr addr = addrMapper.selectJoinOne(Addr.class, wrapper); |
| | | if (Objects.isNull(addr)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | return addr; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = {Exception.class, BusinessException.class}) |
| | | public Integer createByMember(Addr addr, Integer memberId) { |
| | | validateAddr(addr); |
| | | // 设为默认时,先清除该用户原有的默认地址 |
| | | if (Constants.equalsInteger(addr.getIsDefault(), Constants.ONE)) { |
| | | clearDefault(memberId); |
| | | } |
| | | addr.setMemberId(memberId); |
| | | addr.setDeleted(Constants.ZERO); |
| | | addr.setCreateTime(new Date()); |
| | | addr.setCreateUser(memberId); |
| | | addr.setUpdateTime(new Date()); |
| | | addr.setUpdateUser(memberId); |
| | | addrMapper.insert(addr); |
| | | return addr.getId(); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = {Exception.class, BusinessException.class}) |
| | | public void updateByMember(Addr addr, Integer memberId) { |
| | | if (Objects.isNull(addr) || Objects.isNull(addr.getId())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST); |
| | | } |
| | | validateAddr(addr); |
| | | // 设为默认时,先清除该用户原有的默认地址 |
| | | if (Constants.equalsInteger(addr.getIsDefault(), Constants.ONE)) { |
| | | clearDefault(memberId); |
| | | } |
| | | addr.setMemberId(memberId); |
| | | addr.setUpdateTime(new Date()); |
| | | addr.setUpdateUser(memberId); |
| | | addrMapper.updateById(addr); |
| | | } |
| | | |
| | | private void validateAddr(Addr addr) { |
| | | if (Objects.isNull(addr.getAreaId())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "区域不能为空"); |
| | | } |
| | | if (StringUtils.isBlank(addr.getAddr())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "详细地址不能为空"); |
| | | } |
| | | if (Objects.isNull(addr.getIsDefault())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "是否默认不能为空"); |
| | | } |
| | | if (StringUtils.isBlank(addr.getName())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "姓名不能为空"); |
| | | } |
| | | if (StringUtils.isBlank(addr.getPhone())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "电话不能为空"); |
| | | } |
| | | if (Objects.isNull(addr.getLongitude())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "经度不能为空"); |
| | | } |
| | | if (Objects.isNull(addr.getLatitude())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "纬度不能为空"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 清除该用户所有地址的默认标记 |
| | | */ |
| | | private void clearDefault(Integer memberId) { |
| | | addrMapper.update(new UpdateWrapper<Addr>().lambda() |
| | | .set(Addr::getIsDefault, Constants.ZERO) |
| | | .eq(Addr::getMemberId, memberId) |
| | | .eq(Addr::getDeleted, Constants.ZERO) |
| | | .eq(Addr::getIsDefault, Constants.ONE)); |
| | | } |
| | | } |
| | |
| | | return dataList; |
| | | } |
| | | |
| | | @Override |
| | | public List<Areas> getOpenCityList() { |
| | | QueryWrapper<Areas> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(Areas::getType, Constants.ONE) |
| | | .eq(Areas::getStatus, Constants.ONE) |
| | | .eq(Areas::getIsdeleted, Constants.ZERO) |
| | | .orderByAsc(Areas::getSortnum); |
| | | List<Areas> list = areasMapper.selectList(qw); |
| | | if (list != null) { |
| | | for (Areas c : list) { |
| | | c.setFullspell(PinYinUtil.getFullSpell(c.getName())); |
| | | c.setFirstSpell(PinYinUtil.getFirstFirstSpell(c.getName())); |
| | | } |
| | | Collections.sort(list); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.doumee.biz.system.SystemDictDataBiz; |
| | | import com.doumee.core.constants.Constants; |
| | | import com.doumee.core.constants.ResponseStatus; |
| | | import com.doumee.core.exception.BusinessException; |
| | | import com.doumee.core.model.LoginUserInfo; |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.core.utils.Utils; |
| | | import com.doumee.dao.business.BannerMapper; |
| | | import com.doumee.dao.business.model.Banner; |
| | | import com.doumee.service.business.BannerService; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.apache.shiro.SecurityUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | |
| | | @Autowired |
| | | private BannerMapper bannerMapper; |
| | | |
| | | @Autowired |
| | | private SystemDictDataBiz systemDictDataBiz; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = {Exception.class, BusinessException.class}) |
| | | public Integer create(Banner banner) { |
| | | validateBanner(banner, false); |
| | | LoginUserInfo loginUserInfo = (LoginUserInfo) SecurityUtils.getSubject().getPrincipal(); |
| | | banner.setDeleted(Constants.ZERO); |
| | | banner.setCreateTime(new Date()); |
| | | banner.setCreateUser(loginUserInfo.getId()); |
| | | banner.setUpdateTime(new Date()); |
| | | banner.setUpdateUser(loginUserInfo.getId()); |
| | | bannerMapper.insert(banner); |
| | | return banner.getId(); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteById(Integer id) { |
| | | bannerMapper.deleteById(id); |
| | | bannerMapper.update(new UpdateWrapper<Banner>().lambda() |
| | | .set(Banner::getDeleted, Constants.ONE) |
| | | .eq(Banner::getId, id)); |
| | | } |
| | | |
| | | @Override |
| | |
| | | if (CollectionUtils.isEmpty(ids)) { |
| | | return; |
| | | } |
| | | bannerMapper.deleteBatchIds(ids); |
| | | for (Integer id : ids) { |
| | | this.deleteById(id); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = {Exception.class, BusinessException.class}) |
| | | public void updateById(Banner banner) { |
| | | validateBanner(banner, true); |
| | | LoginUserInfo loginUserInfo = (LoginUserInfo) SecurityUtils.getSubject().getPrincipal(); |
| | | banner.setUpdateTime(new Date()); |
| | | banner.setUpdateUser(loginUserInfo.getId()); |
| | | bannerMapper.updateById(banner); |
| | | } |
| | | |
| | | @Override |
| | | public void updateStatus(Banner banner) { |
| | | if (Objects.isNull(banner) || Objects.isNull(banner.getId()) || Objects.isNull(banner.getStatus())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST); |
| | | } |
| | | LoginUserInfo loginUserInfo = (LoginUserInfo) SecurityUtils.getSubject().getPrincipal(); |
| | | banner.setUpdateTime(new Date()); |
| | | banner.setUpdateUser(loginUserInfo.getId()); |
| | | bannerMapper.updateById(banner); |
| | | } |
| | | |
| | |
| | | Banner banner = bannerMapper.selectById(id); |
| | | if (Objects.isNull(banner)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | if (StringUtils.isNotBlank(banner.getImgurl())) { |
| | | String path = getBannerPath(); |
| | | banner.setImgurlFull(path + banner.getImgurl()); |
| | | } |
| | | return banner; |
| | | } |
| | |
| | | QueryWrapper<Banner> queryWrapper = new QueryWrapper<>(); |
| | | Utils.MP.blankToNull(pageWrap.getModel()); |
| | | pageWrap.getModel().setDeleted(Constants.ZERO); |
| | | if (pageWrap.getModel().getId() != null) { |
| | | queryWrapper.lambda().eq(Banner::getId, pageWrap.getModel().getId()); |
| | | } |
| | | if (pageWrap.getModel().getDeleted() != null) { |
| | | queryWrapper.lambda().eq(Banner::getDeleted, pageWrap.getModel().getDeleted()); |
| | | } |
| | | if (pageWrap.getModel().getCreateUser() != null) { |
| | | queryWrapper.lambda().eq(Banner::getCreateUser, pageWrap.getModel().getCreateUser()); |
| | | } |
| | | if (pageWrap.getModel().getCreateTime() != null) { |
| | | queryWrapper.lambda().ge(Banner::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateTime())); |
| | | queryWrapper.lambda().le(Banner::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateTime())); |
| | | } |
| | | if (pageWrap.getModel().getUpdateUser() != null) { |
| | | queryWrapper.lambda().eq(Banner::getUpdateUser, pageWrap.getModel().getUpdateUser()); |
| | | } |
| | | if (pageWrap.getModel().getUpdateTime() != null) { |
| | | queryWrapper.lambda().ge(Banner::getUpdateTime, Utils.Date.getStart(pageWrap.getModel().getUpdateTime())); |
| | | queryWrapper.lambda().le(Banner::getUpdateTime, Utils.Date.getEnd(pageWrap.getModel().getUpdateTime())); |
| | | } |
| | | if (pageWrap.getModel().getStatus() != null) { |
| | | queryWrapper.lambda().eq(Banner::getStatus, pageWrap.getModel().getStatus()); |
| | | } |
| | | if (pageWrap.getModel().getType() != null) { |
| | | queryWrapper.lambda().eq(Banner::getType, pageWrap.getModel().getType()); |
| | | } |
| | | if (pageWrap.getModel().getPosition() != null) { |
| | | queryWrapper.lambda().eq(Banner::getPosition, pageWrap.getModel().getPosition()); |
| | | } |
| | | if (pageWrap.getModel().getShopId() != null) { |
| | | queryWrapper.lambda().eq(Banner::getShopId, pageWrap.getModel().getShopId()); |
| | | if (StringUtils.isNotBlank(pageWrap.getModel().getTitle())) { |
| | | queryWrapper.lambda().like(Banner::getTitle, pageWrap.getModel().getTitle()); |
| | | } |
| | | if (pageWrap.getModel().getType() != null) { |
| | | queryWrapper.lambda().eq(Banner::getType, pageWrap.getModel().getType()); |
| | | } |
| | | for (PageWrap.SortData sortData : pageWrap.getSorts()) { |
| | | if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) { |
| | |
| | | queryWrapper.orderByAsc(sortData.getProperty()); |
| | | } |
| | | } |
| | | return PageData.from(bannerMapper.selectPage(page, queryWrapper)); |
| | | PageData<Banner> result = PageData.from(bannerMapper.selectPage(page, queryWrapper)); |
| | | if (result != null && result.getRecords() != null) { |
| | | String path = getBannerPath(); |
| | | for (Banner b : result.getRecords()) { |
| | | if (StringUtils.isNotBlank(b.getImgurl())) { |
| | | b.setImgurlFull(path + b.getImgurl()); |
| | | } |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | |
| | | QueryWrapper<Banner> wrapper = new QueryWrapper<>(banner); |
| | | return bannerMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | @Override |
| | | public List<Banner> findListByPosition(Integer position) { |
| | | QueryWrapper<Banner> wrapper = new QueryWrapper<>(); |
| | | wrapper.lambda() |
| | | .eq(Banner::getDeleted, Constants.ZERO) |
| | | .eq(Banner::getStatus, Constants.ZERO) |
| | | .eq(Banner::getPosition, position) |
| | | .orderByAsc(Banner::getSortnum); |
| | | List<Banner> list = bannerMapper.selectList(wrapper); |
| | | if (list != null && !list.isEmpty()) { |
| | | String path = getBannerPath(); |
| | | for (Banner b : list) { |
| | | if (StringUtils.isNotBlank(b.getImgurl())) { |
| | | b.setImgurlFull(path + b.getImgurl()); |
| | | } |
| | | } |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | private void validateBanner(Banner banner, boolean requireId) { |
| | | if (Objects.isNull(banner)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST); |
| | | } |
| | | if (requireId && Objects.isNull(banner.getId())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST); |
| | | } |
| | | if (StringUtils.isBlank(banner.getTitle())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "标题不能为空"); |
| | | } |
| | | if (StringUtils.isBlank(banner.getImgurl())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "图片不能为空"); |
| | | } |
| | | if (Objects.isNull(banner.getStatus())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "状态不能为空"); |
| | | } |
| | | if (Objects.isNull(banner.getPosition())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "显示位置不能为空"); |
| | | } |
| | | if (Objects.isNull(banner.getType())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "跳转类型不能为空"); |
| | | } |
| | | // 跳转类型为1(富文本)或2(外链)时,内容必填 |
| | | if (!Constants.equalsInteger(banner.getType(), Constants.ZERO) && StringUtils.isBlank(banner.getContent())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "内容不能为空"); |
| | | } |
| | | } |
| | | |
| | | private String getBannerPath() { |
| | | return systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.RESOURCE_PATH).getCode() |
| | | + systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.BANNER_FILES).getCode(); |
| | | } |
| | | } |
| | |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.core.utils.Utils; |
| | | import com.doumee.dao.business.CategoryMapper; |
| | | import com.doumee.dao.business.PricingRuleMapper; |
| | | import com.doumee.dao.business.model.Category; |
| | | import com.doumee.dao.business.model.PricingRule; |
| | | import com.doumee.dao.system.model.SystemUser; |
| | | import com.doumee.service.business.CategoryService; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | |
| | | |
| | | @Autowired |
| | | private CategoryMapper categoryMapper; |
| | | |
| | | @Autowired |
| | | private PricingRuleMapper pricingRuleMapper; |
| | | |
| | | @Autowired |
| | | private SystemDictDataBiz systemDictDataBiz; |
| | |
| | | return categoryList; |
| | | } |
| | | |
| | | @Override |
| | | public List<Category> getCitySizeList(Integer cityId) { |
| | | // 1. 查询该城市已配置的异地寄送规则(pricing_rule type=1),获取fieldA(物品尺寸主键) |
| | | List<PricingRule> rules = pricingRuleMapper.selectList(new QueryWrapper<PricingRule>().lambda() |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .eq(PricingRule::getType, Constants.ONE) |
| | | .eq(PricingRule::getCityId, cityId)); |
| | | if (CollectionUtils.isEmpty(rules)) { |
| | | return java.util.Collections.emptyList(); |
| | | } |
| | | List<Integer> sizeIds = new java.util.ArrayList<>(); |
| | | for (PricingRule rule : rules) { |
| | | if (StringUtils.isNotBlank(rule.getFieldA())) { |
| | | sizeIds.add(Integer.parseInt(rule.getFieldA())); |
| | | } |
| | | } |
| | | if (sizeIds.isEmpty()) { |
| | | return java.util.Collections.emptyList(); |
| | | } |
| | | // 2. 查询对应的物品尺寸(category type=4) |
| | | List<Category> sizeList = categoryMapper.selectList(new QueryWrapper<Category>().lambda() |
| | | .eq(Category::getDeleted, Constants.ZERO) |
| | | .eq(Category::getStatus, Constants.ZERO) |
| | | .eq(Category::getType, Constants.FOUR) |
| | | .in(Category::getId, sizeIds) |
| | | .orderByAsc(Category::getSortnum)); |
| | | // 3. 拼接图标全路径 |
| | | if (!CollectionUtils.isEmpty(sizeList)) { |
| | | String path = systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.RESOURCE_PATH).getCode() |
| | | + systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.CATEGORY_FILES).getCode(); |
| | | for (Category cate : sizeList) { |
| | | if (StringUtils.isNotBlank(cate.getIcon())) { |
| | | cate.setIconFull(path + cate.getIcon()); |
| | | } |
| | | } |
| | | } |
| | | return sizeList; |
| | | } |
| | | |
| | | private void validateByType(Category category) { |
| | | if (Constants.equalsInteger(category.getType(), Constants.ONE)) { |
| | | if (StringUtils.isBlank(category.getOtherField())) { |
| | |
| | | import com.doumee.dao.business.MultifileMapper; |
| | | import com.doumee.dao.business.SmsrecordMapper; |
| | | import com.doumee.dao.business.CategoryMapper; |
| | | import com.doumee.biz.system.SystemDictDataBiz; |
| | | import com.doumee.dao.business.model.Category; |
| | | import com.doumee.dao.business.model.DriverInfo; |
| | | import com.doumee.dao.business.model.Member; |
| | |
| | | import com.doumee.dao.business.model.Smsrecord; |
| | | import com.doumee.dao.vo.AccountResponse; |
| | | import com.doumee.dao.dto.AuditDTO; |
| | | import com.doumee.dao.dto.ChangeStatusDTO; |
| | | import com.doumee.dao.dto.DriverLoginRequest; |
| | | import com.doumee.dao.dto.DriverRegisterRequest; |
| | | import com.doumee.dao.dto.DriverVerifyRequest; |
| | | import com.doumee.service.business.AliSmsService; |
| | | import com.doumee.service.business.DriverInfoService; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.github.yulichang.wrapper.MPJLambdaWrapper; |
| | | import org.apache.commons.lang3.RandomStringUtils; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | |
| | | @Autowired |
| | | private CategoryMapper categoryMapper; |
| | | |
| | | @Autowired |
| | | private SystemDictDataBiz systemDictDataBiz; |
| | | |
| | | @Override |
| | | public Integer create(DriverInfo driverInfo) { |
| | |
| | | @Override |
| | | public PageData<DriverInfo> findPage(PageWrap<DriverInfo> pageWrap) { |
| | | IPage<DriverInfo> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); |
| | | QueryWrapper<DriverInfo> queryWrapper = new QueryWrapper<>(); |
| | | MPJLambdaWrapper<DriverInfo> queryWrapper = new MPJLambdaWrapper<>(); |
| | | Utils.MP.blankToNull(pageWrap.getModel()); |
| | | pageWrap.getModel().setDeleted(Constants.ZERO); |
| | | if (pageWrap.getModel().getId() != null) { |
| | | queryWrapper.lambda().eq(DriverInfo::getId, pageWrap.getModel().getId()); |
| | | |
| | | // 司机姓名/手机号(关键字模糊查询) |
| | | if (StringUtils.isNotBlank(pageWrap.getModel().getKeyword())) { |
| | | queryWrapper.and(w -> w |
| | | .like(DriverInfo::getName, pageWrap.getModel().getKeyword()) |
| | | .or() |
| | | .like(DriverInfo::getTelephone, pageWrap.getModel().getKeyword())); |
| | | } |
| | | if (pageWrap.getModel().getDeleted() != null) { |
| | | queryWrapper.lambda().eq(DriverInfo::getDeleted, pageWrap.getModel().getDeleted()); |
| | | // 车牌号 |
| | | if (StringUtils.isNotBlank(pageWrap.getModel().getCarCode())) { |
| | | queryWrapper.like(DriverInfo::getCarCode, pageWrap.getModel().getCarCode()); |
| | | } |
| | | if (pageWrap.getModel().getCreateUser() != null) { |
| | | queryWrapper.lambda().eq(DriverInfo::getCreateUser, pageWrap.getModel().getCreateUser()); |
| | | } |
| | | if (pageWrap.getModel().getCreateTime() != null) { |
| | | queryWrapper.lambda().ge(DriverInfo::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateTime())); |
| | | queryWrapper.lambda().le(DriverInfo::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateTime())); |
| | | } |
| | | if (pageWrap.getModel().getUpdateUser() != null) { |
| | | queryWrapper.lambda().eq(DriverInfo::getUpdateUser, pageWrap.getModel().getUpdateUser()); |
| | | } |
| | | if (pageWrap.getModel().getUpdateTime() != null) { |
| | | queryWrapper.lambda().ge(DriverInfo::getUpdateTime, Utils.Date.getStart(pageWrap.getModel().getUpdateTime())); |
| | | queryWrapper.lambda().le(DriverInfo::getUpdateTime, Utils.Date.getEnd(pageWrap.getModel().getUpdateTime())); |
| | | } |
| | | if (pageWrap.getModel().getRemark() != null) { |
| | | queryWrapper.lambda().eq(DriverInfo::getRemark, pageWrap.getModel().getRemark()); |
| | | } |
| | | if (pageWrap.getModel().getName() != null) { |
| | | queryWrapper.lambda().like(DriverInfo::getName, pageWrap.getModel().getName()); |
| | | } |
| | | if (pageWrap.getModel().getTelephone() != null) { |
| | | queryWrapper.lambda().like(DriverInfo::getTelephone, pageWrap.getModel().getTelephone()); |
| | | } |
| | | if (pageWrap.getModel().getIdcard() != null) { |
| | | queryWrapper.lambda().eq(DriverInfo::getIdcard, pageWrap.getModel().getIdcard()); |
| | | } |
| | | if (pageWrap.getModel().getMaritalStatus() != null) { |
| | | queryWrapper.lambda().eq(DriverInfo::getMaritalStatus, pageWrap.getModel().getMaritalStatus()); |
| | | } |
| | | if (pageWrap.getModel().getCarType() != null) { |
| | | queryWrapper.lambda().eq(DriverInfo::getCarType, pageWrap.getModel().getCarType()); |
| | | } |
| | | if (pageWrap.getModel().getCarCode() != null) { |
| | | queryWrapper.lambda().like(DriverInfo::getCarCode, pageWrap.getModel().getCarCode()); |
| | | } |
| | | if (pageWrap.getModel().getCardStartDate() != null) { |
| | | queryWrapper.lambda().ge(DriverInfo::getCardStartDate, Utils.Date.getStart(pageWrap.getModel().getCardStartDate())); |
| | | queryWrapper.lambda().le(DriverInfo::getCardStartDate, Utils.Date.getEnd(pageWrap.getModel().getCardStartDate())); |
| | | } |
| | | if (pageWrap.getModel().getCardEndDate() != null) { |
| | | queryWrapper.lambda().ge(DriverInfo::getCardEndDate, Utils.Date.getStart(pageWrap.getModel().getCardEndDate())); |
| | | queryWrapper.lambda().le(DriverInfo::getCardEndDate, Utils.Date.getEnd(pageWrap.getModel().getCardEndDate())); |
| | | } |
| | | // 状态 |
| | | if (pageWrap.getModel().getStatus() != null) { |
| | | queryWrapper.lambda().eq(DriverInfo::getStatus, pageWrap.getModel().getStatus()); |
| | | queryWrapper.eq(DriverInfo::getStatus, pageWrap.getModel().getStatus()); |
| | | } |
| | | if (pageWrap.getModel().getAuditTime() != null) { |
| | | queryWrapper.lambda().ge(DriverInfo::getAuditTime, Utils.Date.getStart(pageWrap.getModel().getAuditTime())); |
| | | queryWrapper.lambda().le(DriverInfo::getAuditTime, Utils.Date.getEnd(pageWrap.getModel().getAuditTime())); |
| | | // 审批状态 |
| | | if (pageWrap.getModel().getAuditStatus() != null) { |
| | | queryWrapper.eq(DriverInfo::getAuditStatus, pageWrap.getModel().getAuditStatus()); |
| | | } |
| | | if (pageWrap.getModel().getAuditUser() != null) { |
| | | queryWrapper.lambda().eq(DriverInfo::getAuditUser, pageWrap.getModel().getAuditUser()); |
| | | // 创建日期范围 |
| | | if (pageWrap.getModel().getCreateTimeStart() != null) { |
| | | queryWrapper.ge(DriverInfo::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateTimeStart())); |
| | | } |
| | | if (pageWrap.getModel().getMemberId() != null) { |
| | | queryWrapper.lambda().eq(DriverInfo::getMemberId, pageWrap.getModel().getMemberId()); |
| | | if (pageWrap.getModel().getCreateTimeEnd() != null) { |
| | | queryWrapper.le(DriverInfo::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateTimeEnd())); |
| | | } |
| | | // 子查询:余额 |
| | | queryWrapper.selectAll(DriverInfo.class) |
| | | .select(" ( select ifnull(sum(r.OPT_TYPE * r.AMOUNT),0) from revenue r where r.MEMBER_TYPE = 1 and r.MEMBER_ID= t.id and r.VAILD_STATUS = 1 ) as memberAmount ") |
| | | .selectAs(Category::getName,DriverInfo::getCarTypeName) |
| | | .leftJoin(Category.class, Category::getId,DriverInfo::getCarType); |
| | | for (PageWrap.SortData sortData : pageWrap.getSorts()) { |
| | | if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) { |
| | | queryWrapper.orderByDesc(sortData.getProperty()); |
| | |
| | | queryWrapper.orderByAsc(sortData.getProperty()); |
| | | } |
| | | } |
| | | return PageData.from(driverInfoMapper.selectPage(page, queryWrapper)); |
| | | PageData<DriverInfo> pageData = PageData.from(driverInfoMapper.selectPage(page, queryWrapper)); |
| | | for (DriverInfo d : pageData.getRecords()) { |
| | | d.setGender(Constants.getGenderByIdCard(d.getIdcard())); |
| | | } |
| | | return pageData; |
| | | } |
| | | |
| | | @Override |
| | |
| | | member.setBusinessStatus(Constants.ZERO); |
| | | member.setPassword(secure.encryptPassword(defaultPassword, salt)); |
| | | member.setSalt(salt); |
| | | member.setWorkerIdentity(Constants.ZERO); |
| | | member.setDriverIdentity(Constants.ZERO); |
| | | member.setChefIdentity(Constants.ZERO); |
| | | member.setAmount(Constants.ZERO.longValue()); |
| | | member.setTotalAmount(Constants.ZERO.longValue()); |
| | | member.setStatus(Constants.ZERO); |
| | |
| | | member.setUseIdentity(Constants.ZERO); |
| | | memberMapper.insert(member); |
| | | |
| | | // 创建司机基础信息(status=0,注册状态) |
| | | // 创建司机基础信息 |
| | | DriverInfo driverInfo = new DriverInfo(); |
| | | driverInfo.setDeleted(Constants.ZERO); |
| | | driverInfo.setCreateTime(now); |
| | |
| | | driverInfo.setTelephone(telephone); |
| | | driverInfo.setMemberId(member.getId()); |
| | | driverInfo.setStatus(Constants.ZERO); |
| | | driverInfo.setAuditStatus(null); |
| | | driverInfoMapper.insert(driverInfo); |
| | | } |
| | | |
| | |
| | | if (Objects.isNull(driverInfo)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | // 状态校验:status=0(注册)或status=3(审批驳回)可提交认证 |
| | | if (driverInfo.getStatus() != null |
| | | && !Constants.equalsInteger(driverInfo.getStatus(), Constants.ZERO) |
| | | && !Constants.equalsInteger(driverInfo.getStatus(), Constants.THREE)) { |
| | | // 状态校验:auditStatus=null(未提交)或auditStatus=2(审批驳回)可提交认证 |
| | | if (driverInfo.getAuditStatus() != null |
| | | && !Constants.equalsInteger(driverInfo.getAuditStatus(), Constants.TWO)) { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "当前状态不允许提交认证"); |
| | | } |
| | | // 根据车辆类型判断是否需要驾驶证 |
| | |
| | | .set(DriverInfo::getCardEndDate, request.getCardEndDate()) |
| | | .set(DriverInfo::getIdcardImg, request.getIdcardImg()) |
| | | .set(DriverInfo::getIdcardImgBack, request.getIdcardImgBack()) |
| | | .set(DriverInfo::getStatus, Constants.ONE) |
| | | .set(DriverInfo::getAuditStatus, Constants.ZERO) |
| | | .set(DriverInfo::getUpdateTime, now) |
| | | .set(DriverInfo::getAuditRemark, null) |
| | | .set(DriverInfo::getAuditTime, null) |
| | |
| | | if (Objects.isNull(driverInfo)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | // 只有状态为1(待审批)且已填写认证信息才能审批 |
| | | if (!Constants.equalsInteger(driverInfo.getStatus(), Constants.ONE) |
| | | // 只有审批状态为0(待审批)且已填写认证信息才能审批 |
| | | if (!Constants.equalsInteger(driverInfo.getAuditStatus(), Constants.ZERO) |
| | | || StringUtils.isBlank(driverInfo.getIdcard())) { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "当前状态不允许审批"); |
| | | } |
| | | Date now = new Date(); |
| | | // 审批结果:auditDTO.auditStatus 0=通过→driverInfo.status=2,1=拒绝→driverInfo.status=3 |
| | | Integer newStatus; |
| | | // 审批结果:auditDTO.auditStatus 0=通过→auditStatus=1,1=拒绝→auditStatus=2 |
| | | Integer newAuditStatus; |
| | | if (Constants.equalsInteger(auditDTO.getAuditStatus(), Constants.ZERO)) { |
| | | newStatus = Constants.TWO; // 审批通过 |
| | | newAuditStatus = Constants.ONE; // 审批通过 |
| | | // 审批通过时司机定级为必填 |
| | | if (auditDTO.getDriverLevel() == null || auditDTO.getDriverLevel() < 1 || auditDTO.getDriverLevel() > 5) { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "审批通过时必须填写司机定级"); |
| | | } |
| | | } else if (Constants.equalsInteger(auditDTO.getAuditStatus(), Constants.ONE)) { |
| | | newStatus = Constants.THREE; // 审批驳回 |
| | | newAuditStatus = Constants.TWO; // 审批驳回 |
| | | } else { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "审批状态参数错误"); |
| | | } |
| | | // 更新司机状态 |
| | | // 更新司机审批状态 |
| | | driverInfoMapper.update(new UpdateWrapper<DriverInfo>().lambda() |
| | | .set(DriverInfo::getStatus, newStatus) |
| | | .set(DriverInfo::getAuditStatus, newAuditStatus) |
| | | .set(DriverInfo::getAuditTime, now) |
| | | .set(DriverInfo::getAuditRemark, auditDTO.getAuditRemark()) |
| | | .set(DriverInfo::getAuditUser, auditDTO.getAuditUser()) |
| | | .set(auditDTO.getDriverLevel() != null, DriverInfo::getDriverLevel, auditDTO.getDriverLevel()) |
| | | .set(DriverInfo::getUpdateTime, now) |
| | | .eq(DriverInfo::getId, auditDTO.getId())); |
| | | // 更新会员司机认证状态:通过=2,驳回=3 |
| | | Integer driverStatus = Constants.equalsInteger(newStatus, Constants.TWO) ? Constants.TWO : Constants.THREE; |
| | | Integer driverStatus = Constants.equalsInteger(newAuditStatus, Constants.ONE) ? Constants.TWO : Constants.THREE; |
| | | memberMapper.update(new UpdateWrapper<Member>().lambda() |
| | | .set(Member::getBusinessStatus, driverStatus) |
| | | .set(Member::getUpdateTime, now) |
| | | .eq(Member::getId, driverInfo.getMemberId())); |
| | | } |
| | | |
| | | @Override |
| | | public DriverInfo getDetail(Integer id) { |
| | | DriverInfo driverInfo = driverInfoMapper.selectById(id); |
| | | if (Objects.isNull(driverInfo) || Constants.equalsInteger(driverInfo.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | // 拼接图片前缀 |
| | | String imgPrefix = ""; |
| | | try { |
| | | imgPrefix = systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.RESOURCE_PATH).getCode() |
| | | + systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.DRIVER_FILES).getCode(); |
| | | } catch (Exception e) { |
| | | // 未配置时忽略 |
| | | } |
| | | driverInfo.setImgPrefix(imgPrefix); |
| | | driverInfo.setGender(Constants.getGenderByIdCard(driverInfo.getIdcard())); |
| | | // 查询车辆类型名称和是否需要驾驶证 |
| | | if (driverInfo.getCarType() != null) { |
| | | Category category = categoryMapper.selectById(driverInfo.getCarType()); |
| | | if (Objects.nonNull(category)) { |
| | | driverInfo.setCarTypeName(category.getName()); |
| | | driverInfo.setNeedLicense(Constants.equalsInteger(Integer.valueOf(category.getOtherField()), Constants.ONE) ? Constants.ONE : Constants.ZERO); |
| | | } |
| | | } |
| | | // 查询照片列表:objType=6车辆照片、7驾驶证照片、8其他资料照片 |
| | | List<Multifile> multifileList = multifileMapper.selectList(new QueryWrapper<Multifile>().lambda() |
| | | .eq(Multifile::getObjId, driverInfo.getId()) |
| | | .in(Multifile::getObjType, 6, 7, 8) |
| | | .orderByAsc(Multifile::getSortnum)); |
| | | if (!CollectionUtils.isEmpty(multifileList)) { |
| | | for (Multifile mf : multifileList) { |
| | | mf.setFileurlFull(imgPrefix + mf.getFileurl()); |
| | | if (Constants.equalsInteger(mf.getObjType(), 6)) { |
| | | driverInfo.getCarImgList().add(mf); |
| | | } else if (Constants.equalsInteger(mf.getObjType(), 7)) { |
| | | driverInfo.getLicenseImgList().add(mf); |
| | | } else if (Constants.equalsInteger(mf.getObjType(), 8)) { |
| | | driverInfo.getOtherImgList().add(mf); |
| | | } |
| | | } |
| | | } |
| | | return driverInfo; |
| | | } |
| | | |
| | | @Override |
| | | public void changeStatus(ChangeStatusDTO dto) { |
| | | if (dto.getId() == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "主键不能为空"); |
| | | } |
| | | if (dto.getStatus() == null || (dto.getStatus() != 0 && dto.getStatus() != 1)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "状态参数错误,0=启用;1=禁用"); |
| | | } |
| | | DriverInfo driverInfo = driverInfoMapper.selectById(dto.getId()); |
| | | if (Objects.isNull(driverInfo) || Constants.equalsInteger(driverInfo.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | driverInfo.setStatus(dto.getStatus()); |
| | | driverInfo.setUpdateTime(new Date()); |
| | | driverInfoMapper.updateById(driverInfo); |
| | | // 联动修改会员状态(member主键与driver_info主键一致) |
| | | memberMapper.update(new UpdateWrapper<Member>().lambda() |
| | | .set(Member::getStatus, dto.getStatus()) |
| | | .set(Member::getUpdateTime, new Date()) |
| | | .eq(Member::getId, driverInfo.getId())); |
| | | } |
| | | |
| | | /** |
| | | * 批量保存附件记录 |
| | | */ |
| | |
| | | identityInfo.setAuditStatus(Constants.ONE); |
| | | identityInfoMapper.insert(identityInfo); |
| | | |
| | | memberMapper.update(new UpdateWrapper<Member>().lambda() |
| | | .set(Constants.equalsInteger(identityInfo.getType(),Constants.ZERO),Member::getWorkerIdentity,Constants.ONE) |
| | | .set(Constants.equalsInteger(identityInfo.getType(),Constants.ONE),Member::getDriverIdentity,Constants.ONE) |
| | | .set(Constants.equalsInteger(identityInfo.getType(),Constants.TWO),Member::getChefIdentity,Constants.ONE) |
| | | .eq(Member::getId,identityInfo.getMemberId())); |
| | | return identityInfo.getId(); |
| | | } |
| | | |
| | |
| | | identityInfo.setUpdateTime(new Date()); |
| | | identityInfo.setAuditStatus(Constants.ONE); |
| | | identityInfoMapper.updateById(identityInfo); |
| | | memberMapper.update(new UpdateWrapper<Member>().lambda() |
| | | .set(Constants.equalsInteger(identityInfo.getType(),Constants.ZERO),Member::getWorkerIdentity,Constants.ONE) |
| | | .set(Constants.equalsInteger(identityInfo.getType(),Constants.ONE),Member::getDriverIdentity,Constants.ONE) |
| | | .set(Constants.equalsInteger(identityInfo.getType(),Constants.TWO),Member::getChefIdentity,Constants.ONE) |
| | | .eq(Member::getId,identityInfo.getMemberId())); |
| | | } |
| | | |
| | | |
| | |
| | | String path = systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.RESOURCE_PATH).getCode() |
| | | +systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.INENTITY_FILES).getCode(); |
| | | //类型:0=用工身份;1=货运身份;2=供餐身份; |
| | | if(!Constants.equalsInteger(member.getWorkerIdentity(),Constants.ZERO)){//用工身份 |
| | | addMemberModelByType(member.getId(),Constants.ZERO,list,path); |
| | | } |
| | | if(!Constants.equalsInteger(member.getDriverIdentity(),Constants.ZERO)){//货运身份 |
| | | addMemberModelByType(member.getId(),Constants.ONE,list,path); |
| | | } |
| | | if(!Constants.equalsInteger(member.getChefIdentity(),Constants.ZERO)){//供餐很粉 |
| | | addMemberModelByType(member.getId(),Constants.TWO,list,path); |
| | | } |
| | | addMemberModelByType(member.getId(),Constants.ZERO,list,path); |
| | | addMemberModelByType(member.getId(),Constants.ONE,list,path); |
| | | addMemberModelByType(member.getId(),Constants.TWO,list,path); |
| | | |
| | | return list; |
| | | } |
| | |
| | | memberMapper.update(new UpdateWrapper<Member>().lambda() |
| | | .set(Member::getUpdateUser,user.getId()) |
| | | .set(Member::getUpdateTime,date) |
| | | .set(Constants.equalsInteger(auditDTO.getAuditStatus(),Constants.ZERO),Member::getAutoReceiveStatus,Constants.ONE) |
| | | .set(Constants.equalsInteger(identityInfo.getType(),Constants.ZERO),Member::getWorkerIdentity, auditDTO.getAuditStatus() ) |
| | | .set(Constants.equalsInteger(identityInfo.getType(),Constants.ONE),Member::getDriverIdentity , auditDTO.getAuditStatus() ) |
| | | .set(Constants.equalsInteger(identityInfo.getType(),Constants.TWO),Member::getChefIdentity , auditDTO.getAuditStatus() ) |
| | | .eq(Member::getId,identityInfo.getMemberId()) |
| | | ); |
| | | |
| | |
| | | import com.doumee.core.utils.Utils; |
| | | import com.doumee.dao.business.IdentityInfoMapper; |
| | | import com.doumee.dao.business.MemberMapper; |
| | | import com.doumee.dao.business.ShopInfoMapper; |
| | | import com.doumee.dao.business.SmsrecordMapper; |
| | | import com.doumee.dao.business.model.IdentityInfo; |
| | | import com.doumee.dao.business.model.Member; |
| | | import com.doumee.dao.business.model.ShopInfo; |
| | | import com.doumee.dao.business.model.MemberRevenue; |
| | | import com.doumee.dao.business.model.Smsrecord; |
| | | import com.doumee.dao.dto.MemberListQueryDTO; |
| | | import com.doumee.dao.dto.UpdMobileRequest; |
| | | import com.doumee.dao.dto.WxPhoneRequest; |
| | | import com.doumee.dao.vo.AccountResponse; |
| | | import com.doumee.dao.vo.MemberDetailVO; |
| | | import com.doumee.dao.vo.MemberListVO; |
| | | import com.doumee.dao.vo.UserCenterVO; |
| | | import com.doumee.service.business.MemberService; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | |
| | | private IdentityInfoMapper identityInfoMapper; |
| | | |
| | | @Autowired |
| | | private SmsrecordMapper smsrecordMapper; |
| | | |
| | | @Autowired |
| | | private JwtTokenUtil jwtTokenUtil; |
| | | |
| | | @Autowired |
| | |
| | | |
| | | @Autowired |
| | | private RedisTemplate<String,Object> redisTemplate; |
| | | |
| | | @Autowired |
| | | private ShopInfoMapper shopInfoMapper; |
| | | |
| | | |
| | | @Override |
| | |
| | | if (pageWrap.getModel().getName() != null) { |
| | | queryWrapper.lambda().like(Member::getName, pageWrap.getModel().getName()); |
| | | } |
| | | if (pageWrap.getModel().getWorkerIdentity() != null) { |
| | | queryWrapper.lambda().eq(Member::getWorkerIdentity, pageWrap.getModel().getWorkerIdentity()); |
| | | } |
| | | if (pageWrap.getModel().getDriverIdentity() != null) { |
| | | queryWrapper.lambda().eq(Member::getDriverIdentity, pageWrap.getModel().getDriverIdentity()); |
| | | } |
| | | if (pageWrap.getModel().getChefIdentity() != null) { |
| | | queryWrapper.lambda().eq(Member::getChefIdentity, pageWrap.getModel().getChefIdentity()); |
| | | } |
| | | if (pageWrap.getModel().getAmount() != null) { |
| | | queryWrapper.lambda().eq(Member::getAmount, pageWrap.getModel().getAmount()); |
| | | } |
| | |
| | | if (pageWrap.getModel().getArea() != null) { |
| | | queryWrapper.lambda().eq(Member::getArea, pageWrap.getModel().getArea()); |
| | | } |
| | | //如果查询接单方 |
| | | queryWrapper.lambda().and(Constants.equalsInteger(pageWrap.getModel().getType(),Constants.ONE ),w1->{ |
| | | w1.eq(Member::getWorkerIdentity,Constants.TWO ) |
| | | .or().eq(Member::getChefIdentity,Constants.TWO ) |
| | | .or().eq(Member::getDriverIdentity,Constants.TWO ); |
| | | }); |
| | | queryWrapper.lambda().ge(pageWrap.getModel().getStartTime()!=null, Member::getCreateTime,pageWrap.getModel().getStartTime()); |
| | | queryWrapper.lambda().le(pageWrap.getModel().getEndTime()!=null,Member::getCreateTime,pageWrap.getModel().getEndTime()); |
| | | |
| | |
| | | if (StringUtils.isBlank(openId)) { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "获取openid失败!请联系管理员"); |
| | | } |
| | | Member member = memberMapper.selectOne(new QueryWrapper<Member>().lambda().eq(Member::getOpenid, openId).eq(Member::getUserType,Constants.ZERO) |
| | | .eq(Member::getDeleted, Constants.ZERO).ne(Member::getStatus, Constants.TWO).last("limit 1")); |
| | | Member member = memberMapper.selectOne(new QueryWrapper<Member>().lambda().eq(Member::getOpenid, openId) |
| | | .ne(Member::getUserType,Constants.ONE) |
| | | .eq(Member::getDeleted, Constants.ZERO) |
| | | .ne(Member::getStatus, Constants.TWO).last("limit 1")); |
| | | AccountResponse accountResponse = new AccountResponse(); |
| | | accountResponse.setOpenid(openId); |
| | | if(Objects.isNull(member)){ |
| | |
| | | String token = JwtTokenUtil.generateTokenForRedis(member.getId(), Constants.ZERO, JSONObject.toJSONString(member), redisTemplate); |
| | | accountResponse.setToken(token); |
| | | accountResponse.setMember(member); |
| | | // 门店用户身份时,返回申请的门店状态 |
| | | fillShopInfo(accountResponse, member); |
| | | return accountResponse; |
| | | } catch (WxErrorException e) { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "微信登录异常!请联系管理员"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | @Override |
| | |
| | | if(Objects.isNull(mobile)){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"未获取到手机号"); |
| | | } |
| | | Member member = memberMapper.selectOne(new QueryWrapper<Member>().lambda().eq(Member::getTelephone,mobile).eq(Member::getUserType,Constants.ZERO) |
| | | Member member = memberMapper.selectOne(new QueryWrapper<Member>().lambda() |
| | | .eq(Member::getTelephone,mobile) |
| | | .ne(Member::getUserType,Constants.ONE) |
| | | .ne(Member::getStatus, Constants.TWO).last("limit 1")); |
| | | if(Objects.nonNull(member)){ |
| | | if(!Constants.equalsInteger(member.getStatus(),Constants.ZERO)){ |
| | |
| | | member.setTelephone(mobile); |
| | | member.setNickName(mobile); |
| | | // member.setCoverImage("1.png"); |
| | | member.setWorkerIdentity(Constants.ZERO); |
| | | member.setDriverIdentity(Constants.ZERO); |
| | | member.setChefIdentity(Constants.ZERO); |
| | | member.setAmount(Constants.ZERO.longValue()); |
| | | member.setTotalAmount(Constants.ZERO.longValue()); |
| | | member.setStatus(Constants.ZERO); |
| | |
| | | AccountResponse accountResponse = new AccountResponse(); |
| | | accountResponse.setToken(token); |
| | | accountResponse.setMember(member); |
| | | // 门店用户身份时,返回申请的门店状态 |
| | | fillShopInfo(accountResponse, member); |
| | | return accountResponse; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 门店用户身份时,填充门店审核状态 |
| | | */ |
| | | private void fillShopInfo(AccountResponse response, Member member) { |
| | | if (Constants.TWO.equals(member.getUserType())) { |
| | | ShopInfo shopInfo = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda() |
| | | .eq(ShopInfo::getRegionMemberId, member.getId()) |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | if (shopInfo != null) { |
| | | response.setShopId(shopInfo.getId()); |
| | | response.setShopAuditStatus(shopInfo.getAuditStatus()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | @Override |
| | |
| | | userCenterVO.setAboutUs(StringUtils.trimToNull(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.ABOUT_US).getCode())); |
| | | userCenterVO.setUserAgreement(StringUtils.trimToNull(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.USER_AGREEMENT).getCode())); |
| | | userCenterVO.setPrivacyAgreement(StringUtils.trimToNull(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.PRIVACY_AGREEMENT).getCode())); |
| | | |
| | | // userCenterVO.setFeeStandards(StringUtils.trimToNull(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.FEE_STANDARDS).getCode())); |
| | | // userCenterVO.setServerIntroduce(StringUtils.trimToNull(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.SERVER_INTRODUCE).getCode())); |
| | | // userCenterVO.setServerPhone(StringUtils.trimToNull(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.SERVER_PHONE).getCode())); |
| | | userCenterVO.setServerIntroduce(StringUtils.trimToNull(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.SERVER_INTRODUCE).getCode())); |
| | | return userCenterVO; |
| | | } |
| | | |
| | |
| | | redisTemplate.delete(token); |
| | | } |
| | | |
| | | |
| | | /***************管理端会员列表接口*************/ |
| | | |
| | | @Override |
| | | public PageData<MemberListVO> findMemberListPage(PageWrap<MemberListQueryDTO> pageWrap) { |
| | | IPage<Member> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); |
| | | MemberListQueryDTO query = pageWrap.getModel(); |
| | | QueryWrapper<Member> queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.lambda().eq(Member::getDeleted, Constants.ZERO); |
| | | queryWrapper.lambda().eq(Member::getUserType, Constants.ZERO); |
| | | if (query != null) { |
| | | if (StringUtils.isNotBlank(query.getKeyword())) { |
| | | queryWrapper.lambda().and(w -> w |
| | | .like(Member::getName, query.getKeyword()) |
| | | .or().like(Member::getTelephone, query.getKeyword())); |
| | | } |
| | | if (query.getStatus() != null) { |
| | | queryWrapper.lambda().eq(Member::getStatus, query.getStatus()); |
| | | } |
| | | if (query.getStartTime() != null) { |
| | | queryWrapper.lambda().ge(Member::getCreateTime, query.getStartTime()); |
| | | } |
| | | if (query.getEndTime() != null) { |
| | | queryWrapper.lambda().le(Member::getCreateTime, Utils.Date.getEnd(query.getEndTime())); |
| | | } |
| | | } |
| | | for (PageWrap.SortData sortData : pageWrap.getSorts()) { |
| | | if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) { |
| | | queryWrapper.orderByDesc(sortData.getProperty()); |
| | | } else { |
| | | queryWrapper.orderByAsc(sortData.getProperty()); |
| | | } |
| | | } |
| | | IPage<Member> memberPage = memberMapper.selectPage(page, queryWrapper); |
| | | IPage<MemberListVO> voPage = memberPage.convert(this::toListVO); |
| | | return PageData.from(voPage); |
| | | } |
| | | |
| | | @Override |
| | | public MemberDetailVO findMemberDetail(Integer id) { |
| | | Member member = memberMapper.selectById(id); |
| | | if (Objects.isNull(member) || Constants.equalsInteger(member.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | MemberDetailVO detail = new MemberDetailVO(); |
| | | detail.setId(member.getId()); |
| | | detail.setNickName(member.getNickName()); |
| | | detail.setName(member.getName()); |
| | | detail.setTelephone(member.getTelephone()); |
| | | detail.setAmount(member.getAmount()); |
| | | detail.setTotalAmount(member.getTotalAmount()); |
| | | detail.setStatus(member.getStatus()); |
| | | detail.setUseIdentity(member.getUseIdentity()); |
| | | detail.setOpenid(member.getOpenid()); |
| | | detail.setUserType(member.getUserType()); |
| | | detail.setBusinessStatus(member.getBusinessStatus()); |
| | | detail.setScore(member.getScore()); |
| | | detail.setReceiveNum(member.getReceiveNum()); |
| | | detail.setPublishNum(member.getPublishNum()); |
| | | detail.setCreateTime(member.getCreateTime()); |
| | | detail.setLoginTime(member.getLoginTime()); |
| | | detail.setLoginTimes(member.getLoginTimes()); |
| | | detail.setProvince(member.getProvince()); |
| | | detail.setCity(member.getCity()); |
| | | detail.setArea(member.getArea()); |
| | | detail.setAutoReceiveStatus(member.getAutoReceiveStatus()); |
| | | if (StringUtils.isNotBlank(member.getCoverImage())) { |
| | | String path = systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.RESOURCE_PATH).getCode() |
| | | + systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.MEMBER_FILES).getCode(); |
| | | detail.setFullCoverImage(path + member.getCoverImage()); |
| | | } |
| | | return detail; |
| | | } |
| | | |
| | | private MemberListVO toListVO(Member member) { |
| | | MemberListVO vo = new MemberListVO(); |
| | | vo.setId(member.getId()); |
| | | vo.setNickName(member.getNickName()); |
| | | vo.setName(member.getName()); |
| | | vo.setTelephone(member.getTelephone()); |
| | | vo.setCreateTime(member.getCreateTime()); |
| | | vo.setStatus(member.getStatus()); |
| | | return vo; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | @Override |
| | | public void verifyUserPhone(UpdMobileRequest request){ |
| | | if(Objects.isNull(request) |
| | | || Objects.isNull(request.getMemberId()) |
| | | || StringUtils.isBlank(request.getPhone()) |
| | | || StringUtils.isBlank(request.getCode()) |
| | | ){ |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST); |
| | | } |
| | | Member member = memberMapper.selectById(request.getMemberId()); |
| | | if(StringUtils.isNotBlank(member.getTelephone())&&!member.getTelephone().equals(request.getPhone())){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"手机号错误"); |
| | | } |
| | | this.verifyPhoneCode(request.getCode(),request.getPhone()); |
| | | } |
| | | |
| | | public void verifyPhoneCode(String code,String phone){ |
| | | //验证码 |
| | | Smsrecord smsrecord = smsrecordMapper.selectOne(new QueryWrapper<Smsrecord>().lambda() |
| | | .eq(Smsrecord::getDeleted,Constants.ZERO) |
| | | .eq(Smsrecord::getCode,code) |
| | | .eq(Smsrecord::getPhone,phone) |
| | | .last(" limit 1") |
| | | ); |
| | | if(Objects.isNull(smsrecord)){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"验证码错误!"); |
| | | } |
| | | if(!Constants.equalsInteger(smsrecord.getStatus(),Constants.ZERO)){ |
| | | if(Constants.equalsInteger(smsrecord.getStatus(),Constants.ONE)){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"验证码已使用"); |
| | | }else{ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"验证码已过期"); |
| | | } |
| | | } |
| | | smsrecordMapper.update(new UpdateWrapper<Smsrecord>().lambda() |
| | | .set(Smsrecord::getStatus,Constants.ONE) |
| | | .eq(Smsrecord::getId,smsrecord.getId()) |
| | | ); |
| | | } |
| | | |
| | | @Override |
| | | public void updateUserPhone(UpdMobileRequest request){ |
| | | if(Objects.isNull(request) |
| | | || Objects.isNull(request.getMemberId()) |
| | | || StringUtils.isBlank(request.getPhone()) |
| | | || StringUtils.isBlank(request.getCode()) |
| | | ){ |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST); |
| | | } |
| | | //判断新手机号是否已被使用 |
| | | if(memberMapper.selectCount(new QueryWrapper<Member>().lambda().eq(Member::getTelephone,request.getPhone()))>Constants.ZERO){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"对不起,新手机号已被绑定,无法进行换绑!"); |
| | | } |
| | | Member member = memberMapper.selectById(request.getMemberId()); |
| | | if(StringUtils.isNotBlank(member.getTelephone())&&member.getTelephone().equals(request.getPhone())){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"无法更换相同手机号"); |
| | | } |
| | | this.verifyPhoneCode(request.getCode(),request.getPhone()); |
| | | memberMapper.update(new UpdateWrapper<Member>().lambda() |
| | | .set(Member::getTelephone,request.getPhone()) |
| | | .eq(Member::getId,request.getMemberId()) |
| | | ); |
| | | } |
| | | |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.doumee.biz.system.AreasBiz; |
| | | import com.doumee.biz.system.OperationConfigBiz; |
| | | import com.doumee.biz.system.SystemDictDataBiz; |
| | | import com.doumee.config.wx.WxMiniConfig; |
| | | import com.doumee.config.wx.WxMiniUtilService; |
| | | import com.doumee.core.constants.Constants; |
| | | import com.doumee.core.constants.ResponseStatus; |
| | | import com.doumee.core.exception.BusinessException; |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.core.utils.DateUtil; |
| | | import com.doumee.core.utils.Tencent.MapUtil; |
| | | import com.doumee.core.utils.Utils; |
| | | import com.doumee.dao.business.OrdersMapper; |
| | | import com.doumee.dao.business.model.Category; |
| | | import com.doumee.dao.business.model.Orders; |
| | | import com.doumee.dao.business.*; |
| | | import com.doumee.dao.business.model.*; |
| | | import com.doumee.dao.system.SystemUserMapper; |
| | | import com.doumee.dao.system.model.SystemUser; |
| | | import com.doumee.dao.dto.CalculateLocalPriceDTO; |
| | | import com.doumee.dao.dto.CalculateRemotePriceDTO; |
| | | import com.doumee.dao.dto.CreateOrderDTO; |
| | | import com.doumee.dao.dto.DispatchDTO; |
| | | import com.doumee.dao.dto.MyOrderDTO; |
| | | import com.doumee.dao.dto.OrderItemDTO; |
| | | import com.doumee.dao.vo.*; |
| | | import com.doumee.service.business.OrderLogService; |
| | | import com.doumee.service.business.OrdersService; |
| | | import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest; |
| | | import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; |
| | | import com.github.binarywang.wxpay.exception.WxPayException; |
| | | import com.github.xiaoymin.knife4j.core.util.CollectionUtils; |
| | | import com.github.yulichang.wrapper.MPJLambdaWrapper; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.context.request.RequestContextHolder; |
| | | import org.springframework.web.context.request.ServletRequestAttributes; |
| | | |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.net.InetAddress; |
| | | import java.net.UnknownHostException; |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 寄存订单信息Service实现 |
| | |
| | | |
| | | @Autowired |
| | | private OrdersMapper ordersMapper; |
| | | |
| | | @Autowired |
| | | private MemberMapper memberMapper; |
| | | |
| | | @Autowired |
| | | private ShopInfoMapper shopInfoMapper; |
| | | |
| | | @Autowired |
| | | private DriverInfoMapper driverInfoMapper; |
| | | |
| | | @Autowired |
| | | private CategoryMapper categoryMapper; |
| | | |
| | | @Autowired |
| | | private MultifileMapper multifileMapper; |
| | | |
| | | @Autowired |
| | | private OrdersDetailMapper ordersDetailMapper; |
| | | |
| | | @Autowired |
| | | private SystemDictDataBiz systemDictDataBiz; |
| | | |
| | | @Autowired |
| | | private OrderLogService orderLogService; |
| | | |
| | | @Autowired |
| | | private OrdersRefundMapper ordersRefundMapper; |
| | | |
| | | @Autowired |
| | | private WxMiniUtilService wxMiniUtilService; |
| | | |
| | | @Autowired |
| | | private SystemUserMapper systemUserMapper; |
| | | |
| | | @Autowired |
| | | private PricingRuleMapper pricingRuleMapper; |
| | | @Autowired |
| | | private RedisTemplate<String, Object> redisTemplate; |
| | | |
| | | @Autowired |
| | | private AreasBiz areasBiz; |
| | | |
| | | @Autowired |
| | | private OperationConfigBiz operationConfigBiz; |
| | | |
| | | @Override |
| | | public Integer create(Orders orders) { |
| | |
| | | MPJLambdaWrapper<Orders> queryWrapper = new MPJLambdaWrapper<Orders>() |
| | | .selectAll(Orders.class) |
| | | .selectAs(Category::getDetail, Orders::getOrderLevel) |
| | | .leftJoin(Category.class, Category::getId, Orders::getGoodType); |
| | | .select("s1.name", Orders::getDepositShopName) |
| | | .leftJoin(Category.class, Category::getId, Orders::getGoodType) |
| | | .leftJoin(DriverInfo.class, DriverInfo::getId, Orders::getAcceptDriver) |
| | | .leftJoin("shop_info s1 on s1.id = t.DEPOSIT_SHOP_ID") |
| | | .leftJoin("shop_info s2 on s2.id = t.TAKE_SHOP_ID"); |
| | | ; |
| | | Utils.MP.blankToNull(pageWrap.getModel()); |
| | | pageWrap.getModel().setDeleted(Constants.ZERO); |
| | | queryWrapper.eq(pageWrap.getModel().getDeleted() != null, Orders::getDeleted, pageWrap.getModel().getDeleted()); |
| | | queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getCode()), Orders::getCode, pageWrap.getModel().getCode()); |
| | | queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getDepositShopName()), "s1.name", pageWrap.getModel().getDepositShopName()); |
| | | queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getTakeShopName()), "s2.name", pageWrap.getModel().getTakeShopName()); |
| | | queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getGoodsInfo()), Orders::getGoodsInfo, pageWrap.getModel().getGoodsInfo()); |
| | | queryWrapper.ge(pageWrap.getModel().getCreateStartTime() != null, Orders::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateStartTime())); |
| | | queryWrapper.le(pageWrap.getModel().getCreateEndTime() != null, Orders::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateEndTime())); |
| | |
| | | queryWrapper.eq(pageWrap.getModel().getType() != null, Orders::getType, pageWrap.getModel().getType()); |
| | | queryWrapper.eq(pageWrap.getModel().getStatus() != null, Orders::getStatus, pageWrap.getModel().getStatus()); |
| | | queryWrapper.eq(pageWrap.getModel().getTakeShopId() != null, Orders::getTakeShopId, pageWrap.getModel().getTakeShopId()); |
| | | queryWrapper.and(pageWrap.getModel().getDriverKeyword() != null, i->i.like(DriverInfo::getName, pageWrap.getModel().getDriverKeyword()) |
| | | .or().like(DriverInfo::getTelephone, pageWrap.getModel().getDriverKeyword())); |
| | | for (PageWrap.SortData sortData : pageWrap.getSorts()) { |
| | | if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) { |
| | | queryWrapper.orderByDesc(sortData.getProperty()); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public OrderSummaryVO findSummary(PageWrap<Orders> pageWrap) { |
| | | // 构建与findPage相同的查询条件 |
| | | MPJLambdaWrapper<Orders> queryWrapper = new MPJLambdaWrapper<Orders>() |
| | | .leftJoin(Category.class, Category::getId, Orders::getGoodType) |
| | | .leftJoin(DriverInfo.class, DriverInfo::getId, Orders::getAcceptDriver) |
| | | .leftJoin("shop_info s1 on s1.id = t.DEPOSIT_SHOP_ID") |
| | | .leftJoin("shop_info s2 on s2.id = t.TAKE_SHOP_ID"); |
| | | Utils.MP.blankToNull(pageWrap.getModel()); |
| | | pageWrap.getModel().setDeleted(Constants.ZERO); |
| | | queryWrapper.eq(pageWrap.getModel().getDeleted() != null, Orders::getDeleted, pageWrap.getModel().getDeleted()); |
| | | queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getCode()), Orders::getCode, pageWrap.getModel().getCode()); |
| | | queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getDepositShopName()), "s1.name", pageWrap.getModel().getDepositShopName()); |
| | | queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getTakeShopName()), "s2.name", pageWrap.getModel().getTakeShopName()); |
| | | queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getGoodsInfo()), Orders::getGoodsInfo, pageWrap.getModel().getGoodsInfo()); |
| | | queryWrapper.ge(pageWrap.getModel().getCreateStartTime() != null, Orders::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateStartTime())); |
| | | queryWrapper.le(pageWrap.getModel().getCreateEndTime() != null, Orders::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateEndTime())); |
| | | queryWrapper.eq(pageWrap.getModel().getDepositShopId() != null, Orders::getDepositShopId, pageWrap.getModel().getDepositShopId()); |
| | | queryWrapper.eq(pageWrap.getModel().getType() != null, Orders::getType, pageWrap.getModel().getType()); |
| | | queryWrapper.eq(pageWrap.getModel().getStatus() != null, Orders::getStatus, pageWrap.getModel().getStatus()); |
| | | queryWrapper.eq(pageWrap.getModel().getTakeShopId() != null, Orders::getTakeShopId, pageWrap.getModel().getTakeShopId()); |
| | | queryWrapper.and(pageWrap.getModel().getDriverKeyword() != null, i->i.like(DriverInfo::getName, pageWrap.getModel().getDriverKeyword()) |
| | | .or().like(DriverInfo::getTelephone, pageWrap.getModel().getDriverKeyword())); |
| | | |
| | | queryWrapper.select( |
| | | "IFNULL(SUM(t.total_amount), 0) as total_amount_sum", |
| | | "IFNULL(SUM(CASE WHEN t.settlement_status = 1 THEN t.total_amount ELSE 0 END), 0) as settled_total_amount_sum", |
| | | "IFNULL(SUM(t.driver_fee), 0) as driver_fee_sum", |
| | | "IFNULL(SUM(CASE WHEN t.settlement_status = 1 THEN t.driver_fee ELSE 0 END), 0) as settled_driver_fee_sum" |
| | | ); |
| | | queryWrapper.groupBy("1=1"); |
| | | |
| | | List<Map<String, Object>> result = ordersMapper.selectJoinMaps(queryWrapper); |
| | | OrderSummaryVO vo = new OrderSummaryVO(); |
| | | if (result != null && !result.isEmpty()) { |
| | | Map<String, Object> row = result.get(0); |
| | | vo.setTotalAmountSum(toLong(row.get("total_amount_sum"))); |
| | | vo.setSettledTotalAmountSum(toLong(row.get("settled_total_amount_sum"))); |
| | | vo.setDriverFeeSum(toLong(row.get("driver_fee_sum"))); |
| | | vo.setSettledDriverFeeSum(toLong(row.get("settled_driver_fee_sum"))); |
| | | } else { |
| | | vo.setTotalAmountSum(0L); |
| | | vo.setSettledTotalAmountSum(0L); |
| | | vo.setDriverFeeSum(0L); |
| | | vo.setSettledDriverFeeSum(0L); |
| | | } |
| | | return vo; |
| | | } |
| | | |
| | | private Long toLong(Object val) { |
| | | if (val == null) return 0L; |
| | | if (val instanceof Number) return ((Number) val).longValue(); |
| | | return Long.parseLong(val.toString()); |
| | | } |
| | | |
| | | @Override |
| | | public BigDecimal calculateInsuranceFee(BigDecimal declaredValue) { |
| | | if (declaredValue == null || declaredValue.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | String rateStr = systemDictDataBiz.queryByCode(Constants.OPERATION_CONFIG, Constants.OP_INSURANCE_RATE).getCode(); |
| | | BigDecimal rate = new BigDecimal(rateStr); |
| | | return declaredValue.multiply(rate).setScale(2, BigDecimal.ROUND_HALF_UP); |
| | | } |
| | | |
| | | /** |
| | | * 计算就地存取预估费用 |
| | | * |
| | | * 计算规则: |
| | | * 1. 根据城市+物品类型 查询 pricing_rule(type=0),fieldA=categoryId, fieldB=单价(分/天) |
| | | * 2. 每项小计 = 单价 × 数量 × 天数 |
| | | * 3. 物品价格 = 各项小计之和 |
| | | * 4. 保价费用 = 报价金额 × 保价费率(字典 INSURANCE_RATE),元转分 |
| | | * 5. 总价格 = 物品价格 + 保价费用 |
| | | * |
| | | * @param dto 就地存取计价请求参数 |
| | | * @return 价格计算结果 |
| | | */ |
| | | @Override |
| | | public PriceCalculateVO calculateLocalPrice(CalculateLocalPriceDTO dto) { |
| | | // 天数校验,最少1天 |
| | | int days = dto.getEstimatedDepositDays() != null && dto.getEstimatedDepositDays() > 0 |
| | | ? dto.getEstimatedDepositDays() : 1; |
| | | |
| | | // 收集所有物品类型ID |
| | | List<Integer> categoryIds = new ArrayList<>(); |
| | | for (OrderItemDTO item : dto.getItems()) { |
| | | categoryIds.add(item.getCategoryId()); |
| | | } |
| | | |
| | | // 批量查询计价规则 pricing_rule type=0:fieldA=categoryId, fieldB=单价(分/天) |
| | | List<String> fieldAList = new ArrayList<>(); |
| | | for (Integer cid : categoryIds) { |
| | | fieldAList.add(String.valueOf(cid)); |
| | | } |
| | | List<PricingRule> rules = pricingRuleMapper.selectList(new QueryWrapper<PricingRule>().lambda() |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .eq(PricingRule::getType, Constants.ZERO) |
| | | .eq(PricingRule::getCityId, dto.getCityId()) |
| | | .in(PricingRule::getFieldA, fieldAList)); |
| | | Map<String, PricingRule> ruleMap = new HashMap<>(); |
| | | for (PricingRule r : rules) { |
| | | ruleMap.put(r.getFieldA(), r); |
| | | } |
| | | |
| | | // 批量查询物品类型名称 |
| | | List<Category> categories = categoryMapper.selectBatchIds(categoryIds); |
| | | Map<Integer, String> categoryNameMap = new HashMap<>(); |
| | | Map<Integer, String> categoryDetailMap = new HashMap<>(); |
| | | for (Category c : categories) { |
| | | categoryNameMap.put(c.getId(), c.getName()); |
| | | categoryDetailMap.put(c.getId(), c.getDetail()); |
| | | } |
| | | |
| | | // 计算每项物品费用:小计 = 单价 × 数量 × 天数 |
| | | List<ItemPriceVO> itemList = new ArrayList<>(); |
| | | long itemPriceTotal = 0L; |
| | | |
| | | for (OrderItemDTO item : dto.getItems()) { |
| | | PricingRule rule = ruleMap.get(String.valueOf(item.getCategoryId())); |
| | | if (rule == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), |
| | | "未找到该城市物品类型的计价规则"); |
| | | } |
| | | |
| | | long unitPrice = Long.parseLong(rule.getFieldB()); |
| | | long subtotal = unitPrice * item.getQuantity() * days; |
| | | |
| | | ItemPriceVO vo = new ItemPriceVO(); |
| | | vo.setCategoryId(item.getCategoryId()); |
| | | vo.setCategoryName(categoryNameMap.getOrDefault(item.getCategoryId(), "")); |
| | | vo.setDetail(categoryDetailMap.get(item.getCategoryId())); |
| | | vo.setQuantity(item.getQuantity()); |
| | | vo.setUnitPrice(unitPrice); |
| | | vo.setLocallyPrice(unitPrice); |
| | | vo.setSubtotal(subtotal); |
| | | itemList.add(vo); |
| | | |
| | | itemPriceTotal += subtotal; |
| | | } |
| | | |
| | | // 保价费用:报价金额 × 保价费率(字典 INSURANCE_RATE),元→分 |
| | | long insuranceFeeFen = 0L; |
| | | if (Boolean.TRUE.equals(dto.getInsured()) && dto.getDeclaredAmount() != null) { |
| | | BigDecimal insuranceFeeYuan = calculateInsuranceFee(dto.getDeclaredAmount()); |
| | | insuranceFeeFen = insuranceFeeYuan.multiply(new BigDecimal(100)).longValue(); |
| | | } |
| | | |
| | | // 总价格 = 物品价格 + 保价费用 |
| | | long totalPrice = itemPriceTotal + insuranceFeeFen; |
| | | |
| | | PriceCalculateVO result = new PriceCalculateVO(); |
| | | result.setItemList(itemList); |
| | | result.setItemPrice(itemPriceTotal); |
| | | result.setInsuranceFee(insuranceFeeFen); |
| | | result.setTotalPrice(totalPrice); |
| | | result.setDays(days); |
| | | result.setUrgentFee(0L); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 计算异地存取预估费用 |
| | | * |
| | | * 计算规则: |
| | | * 1. 调用腾讯地图API计算寄件点与取件点的驾车距离(米→公里) |
| | | * 2. 根据城市+物品类型 查询 pricing_rule(type=1): |
| | | * fieldB=起步距离(km), fieldC=起步价(分), fieldD=超出距离单位(km), fieldE=超出距离单价(分) |
| | | * 3. 每项运费单价: |
| | | * - 距离 ≤ 起步距离 → 单价 = 起步价 |
| | | * - 距离 > 起步距离 → 单价 = 起步价 + ceil((距离-起步距离)/超出距离单位) × 超出距离单价 |
| | | * 4. 小计 = 运费单价 × 数量 |
| | | * 5. 物品价格 = 各项小计之和 |
| | | * 6. 保价费用 = 报价金额 × 保价费率(字典 INSURANCE_RATE),元转分 |
| | | * 7. 加急费用 = 物品价格 × 加急系数(字典 URGENT_COEFFICIENT) |
| | | * 8. 总价格 = 物品价格 + 保价费用 + 加急费用 |
| | | * |
| | | * @param dto 异地存取计价请求参数 |
| | | * @return 价格计算结果 |
| | | */ |
| | | @Override |
| | | public PriceCalculateVO calculateRemotePrice(CalculateRemotePriceDTO dto) { |
| | | // 1. 调用腾讯地图距离矩阵API计算驾车距离 |
| | | String from = dto.getFromLat() + "," + dto.getFromLgt(); |
| | | String to = dto.getToLat() + "," + dto.getToLgt(); |
| | | JSONObject distanceResult = MapUtil.distanceSingle("driving", from, to); |
| | | BigDecimal distance = distanceResult.getBigDecimal("distance"); |
| | | // distance 单位为米,转为公里 |
| | | BigDecimal distanceKm = distance.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); |
| | | |
| | | // 收集所有物品类型ID |
| | | List<Integer> categoryIds = new ArrayList<>(); |
| | | for (OrderItemDTO item : dto.getItems()) { |
| | | categoryIds.add(item.getCategoryId()); |
| | | } |
| | | |
| | | // 2. 批量查询配送计价规则 pricing_rule type=1 |
| | | List<String> fieldAList = new ArrayList<>(); |
| | | for (Integer cid : categoryIds) { |
| | | fieldAList.add(String.valueOf(cid)); |
| | | } |
| | | List<PricingRule> rules = pricingRuleMapper.selectList(new QueryWrapper<PricingRule>().lambda() |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .eq(PricingRule::getType, Constants.ONE) |
| | | .eq(PricingRule::getCityId, dto.getCityId()) |
| | | .in(PricingRule::getFieldA, fieldAList)); |
| | | Map<String, PricingRule> ruleMap = new HashMap<>(); |
| | | for (PricingRule r : rules) { |
| | | ruleMap.put(r.getFieldA(), r); |
| | | } |
| | | |
| | | // 查询就地存取计价规则 pricing_rule type=0,用于获取 locallyPrice |
| | | List<PricingRule> localRules = pricingRuleMapper.selectList(new QueryWrapper<PricingRule>().lambda() |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .eq(PricingRule::getType, Constants.ZERO) |
| | | .eq(PricingRule::getCityId, dto.getCityId()) |
| | | .in(PricingRule::getFieldA, fieldAList)); |
| | | Map<String, PricingRule> localRuleMap = new HashMap<>(); |
| | | for (PricingRule r : localRules) { |
| | | localRuleMap.put(r.getFieldA(), r); |
| | | } |
| | | |
| | | // 批量查询物品类型名称 |
| | | List<Category> categories = categoryMapper.selectBatchIds(categoryIds); |
| | | Map<Integer, String> categoryNameMap = new HashMap<>(); |
| | | Map<Integer, String> categoryDetailMap = new HashMap<>(); |
| | | for (Category c : categories) { |
| | | categoryNameMap.put(c.getId(), c.getName()); |
| | | categoryDetailMap.put(c.getId(), c.getDetail()); |
| | | } |
| | | |
| | | // 3. 逐项计算运费:起步价 + 超出部分阶梯价 |
| | | List<ItemPriceVO> itemList = new ArrayList<>(); |
| | | long itemPriceTotal = 0L; |
| | | |
| | | for (OrderItemDTO item : dto.getItems()) { |
| | | PricingRule rule = ruleMap.get(String.valueOf(item.getCategoryId())); |
| | | if (rule == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), |
| | | "未找到该城市物品类型的配送计价规则"); |
| | | } |
| | | |
| | | // fieldB=起步距离(km), fieldC=起步价(分), fieldD=超出距离单位(km), fieldE=超出距离单价(分) |
| | | BigDecimal startDistance = new BigDecimal(rule.getFieldB()); |
| | | long startPrice = Long.parseLong(rule.getFieldC()); |
| | | BigDecimal extraDistanceUnit = new BigDecimal(rule.getFieldD()); |
| | | long extraPricePerUnit = Long.parseLong(rule.getFieldE()); |
| | | |
| | | // 阶梯计价:距离 ≤ 起步距离取起步价,超出按 ceil(超出距离/单位) × 单价累加 |
| | | long unitPrice; |
| | | if (distanceKm.compareTo(startDistance) <= 0) { |
| | | unitPrice = startPrice; |
| | | } else { |
| | | BigDecimal extraKm = distanceKm.subtract(startDistance); |
| | | BigDecimal extraCount = extraKm.divide(extraDistanceUnit, 0, RoundingMode.CEILING); |
| | | unitPrice = startPrice + extraCount.longValue() * extraPricePerUnit; |
| | | } |
| | | |
| | | long subtotal = unitPrice * item.getQuantity(); |
| | | |
| | | // 就地存取单价 |
| | | PricingRule localRule = localRuleMap.get(String.valueOf(item.getCategoryId())); |
| | | Long locallyPrice = localRule != null ? Long.parseLong(localRule.getFieldB()) : null; |
| | | |
| | | ItemPriceVO vo = new ItemPriceVO(); |
| | | vo.setCategoryId(item.getCategoryId()); |
| | | vo.setCategoryName(categoryNameMap.getOrDefault(item.getCategoryId(), "")); |
| | | vo.setDetail(categoryDetailMap.get(item.getCategoryId())); |
| | | vo.setQuantity(item.getQuantity()); |
| | | vo.setUnitPrice(unitPrice); |
| | | vo.setLocallyPrice(locallyPrice); |
| | | vo.setSubtotal(subtotal); |
| | | vo.setStartDistance(startDistance); |
| | | vo.setStartPrice(startPrice); |
| | | vo.setExtraDistance(extraDistanceUnit); |
| | | vo.setExtraPrice(extraPricePerUnit); |
| | | itemList.add(vo); |
| | | |
| | | itemPriceTotal += subtotal; |
| | | } |
| | | |
| | | // 4. 保价费用:报价金额 × 保价费率(字典 INSURANCE_RATE),元→分 |
| | | long insuranceFeeFen = 0L; |
| | | if (Boolean.TRUE.equals(dto.getInsured()) && dto.getDeclaredAmount() != null) { |
| | | BigDecimal insuranceFeeYuan = calculateInsuranceFee(dto.getDeclaredAmount()); |
| | | insuranceFeeFen = insuranceFeeYuan.multiply(new BigDecimal(100)).longValue(); |
| | | } |
| | | |
| | | // 5. 加急费用:物品价格 × 加急系数(字典 URGENT_COEFFICIENT) |
| | | long urgentFeeFen = 0L; |
| | | if (Boolean.TRUE.equals(dto.getUrgent())) { |
| | | String urgentRateStr = systemDictDataBiz.queryByCode( |
| | | Constants.OPERATION_CONFIG, Constants.OP_URGENT_COEFFICIENT).getCode(); |
| | | BigDecimal urgentRate = new BigDecimal(urgentRateStr); |
| | | urgentFeeFen = new BigDecimal(itemPriceTotal).multiply(urgentRate) |
| | | .setScale(0, RoundingMode.HALF_UP).longValue(); |
| | | } |
| | | |
| | | // 6. 总价格 = 物品价格 + 保价费用 + 加急费用 |
| | | long totalPrice = itemPriceTotal + insuranceFeeFen + urgentFeeFen; |
| | | |
| | | PriceCalculateVO result = new PriceCalculateVO(); |
| | | result.setItemList(itemList); |
| | | result.setItemPrice(itemPriceTotal); |
| | | result.setInsuranceFee(insuranceFeeFen); |
| | | result.setUrgentFee(urgentFeeFen); |
| | | result.setTotalPrice(totalPrice); |
| | | result.setDistance(distanceKm); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public long count(Orders orders) { |
| | | QueryWrapper<Orders> wrapper = new QueryWrapper<>(orders); |
| | | return ordersMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | /** |
| | | * 创建订单 |
| | | * |
| | | * 业务流程: |
| | | * 1. 参数校验:必填字段、时间顺序、物品不重复、异地必填服务时效 |
| | | * 2. 查询寄件店铺信息(获取经纬度、地址) |
| | | * 3. 调用计价接口计算费用(calculateLocalPrice / calculateRemotePrice) |
| | | * 4. 生成订单编号:JC + yyyyMMddHHmmss + 4位随机数 |
| | | * 5. 创建订单主表 Orders(状态=待支付) |
| | | * 6. 创建订单明细表 OrdersDetail(每项物品尺寸) |
| | | * 7. 创建附件记录 Multifile(物品图片 objType=12) |
| | | * |
| | | * @param dto 创建订单请求参数 |
| | | * @param memberId 当前登录会员ID |
| | | * @return 订单ID |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public PayResponse createOrder(CreateOrderDTO dto, Integer memberId) { |
| | | String lockKey = Constants.GOODS_ORDER_CREATE_LOCK + memberId; |
| | | //判断前端是否在同一页面创建了两次订单 |
| | | if (redisTemplate.hasKey(lockKey)) { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"正在创建订单,请勿重复调用!"); |
| | | } else { |
| | | redisTemplate.opsForValue().set(lockKey, "", 5, TimeUnit.SECONDS); |
| | | } |
| | | Date now = new Date(); |
| | | // ========== 1. 参数校验 ========== |
| | | // 预计到店存件时间必须小于预计到店取件时间 |
| | | java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm"); |
| | | Date depositTime; |
| | | Date takeTime; |
| | | try { |
| | | depositTime = sdf.parse(dto.getExpectedDepositTime()); |
| | | takeTime = sdf.parse(dto.getExpectedTakeTime()); |
| | | } catch (java.text.ParseException e) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "时间格式错误,正确格式:yyyy-MM-dd HH:mm"); |
| | | } |
| | | if (!depositTime.before(takeTime)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "预计到店存件时间必须小于预计到店取件时间"); |
| | | } |
| | | |
| | | // 物品尺寸不能重复 |
| | | List<Integer> categoryIds = new ArrayList<>(); |
| | | for (OrderItemDTO item : dto.getItems()) { |
| | | if (categoryIds.contains(item.getCategoryId())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "物品尺寸不能重复"); |
| | | } |
| | | categoryIds.add(item.getCategoryId()); |
| | | } |
| | | |
| | | // 物品图片最多3张 |
| | | if (dto.getGoodsImages() != null && dto.getGoodsImages().size() > 3) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "物品图片最多3张"); |
| | | } |
| | | |
| | | // ========== 2. 校验物品类型 ========== |
| | | Category goodTypeCategory = categoryMapper.selectById(dto.getGoodType()); |
| | | if (goodTypeCategory == null || Constants.equalsInteger(goodTypeCategory.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "物品类型不存在"); |
| | | } |
| | | if (!Constants.equalsInteger(goodTypeCategory.getType(), Constants.TWO)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "物品类型参数错误"); |
| | | } |
| | | |
| | | // ========== 3. 查询寄件店铺信息 ========== |
| | | ShopInfo depositShop = shopInfoMapper.selectById(dto.getDepositShopId()); |
| | | if (depositShop == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "寄件店铺不存在"); |
| | | } |
| | | |
| | | // ========== 4. 计算费用 ========== |
| | | |
| | | // 异地寄存:校验取件点 |
| | | BigDecimal takeLat = null; |
| | | BigDecimal takeLgt = null; |
| | | String takeLocationValue = null; |
| | | ShopInfo takeShop = null; |
| | | if (Constants.ONE.equals(dto.getType())) { |
| | | // 异地必填服务时效 |
| | | if (dto.getIsUrgent() == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "异地寄存服务时效不能为空"); |
| | | } |
| | | // 取件点:店铺 or 自选点,至少提供一组 |
| | | if (dto.getTakeShopId() != null) { |
| | | takeShop = shopInfoMapper.selectById(dto.getTakeShopId()); |
| | | if (takeShop == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "取件店铺不存在"); |
| | | } |
| | | takeLat = BigDecimal.valueOf(takeShop.getLatitude()); |
| | | takeLgt = BigDecimal.valueOf(takeShop.getLongitude()); |
| | | takeLocationValue = takeShop.getAddress(); |
| | | } else if (dto.getTakeLat() != null && dto.getTakeLgt() != null && StringUtils.isNotBlank(dto.getTakeLocation())) { |
| | | takeLat = dto.getTakeLat(); |
| | | takeLgt = dto.getTakeLgt(); |
| | | takeLocationValue = dto.getTakeLocation(); |
| | | } else { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "请选择取件店铺或输入自选取件地址"); |
| | | } |
| | | } else { |
| | | // 就地存取:取件门店同寄件门店 |
| | | takeShop = depositShop; |
| | | } |
| | | |
| | | // ========== 3. 计算费用 ========== |
| | | PriceCalculateVO priceResult; |
| | | if (Constants.ZERO.equals(dto.getType())) { |
| | | // 就地寄存:计算天数 |
| | | long diffMs = takeTime.getTime() - depositTime.getTime(); |
| | | int days = (int) Math.max(1, (diffMs / (1000 * 60 * 60 * 24)) + 1); |
| | | |
| | | CalculateLocalPriceDTO priceDTO = new CalculateLocalPriceDTO(); |
| | | priceDTO.setCityId(dto.getCityId()); |
| | | priceDTO.setEstimatedDepositDays(days); |
| | | priceDTO.setItems(dto.getItems()); |
| | | priceDTO.setInsured(dto.getDeclaredAmount() != null && dto.getDeclaredAmount().compareTo(BigDecimal.ZERO) > 0); |
| | | priceDTO.setDeclaredAmount(dto.getDeclaredAmount()); |
| | | priceResult = calculateLocalPrice(priceDTO); |
| | | } else { |
| | | // 异地寄存 |
| | | CalculateRemotePriceDTO priceDTO = new CalculateRemotePriceDTO(); |
| | | priceDTO.setCityId(dto.getCityId()); |
| | | priceDTO.setFromLat(BigDecimal.valueOf(depositShop.getLatitude())); |
| | | priceDTO.setFromLgt(BigDecimal.valueOf(depositShop.getLongitude())); |
| | | priceDTO.setToLat(takeLat); |
| | | priceDTO.setToLgt(takeLgt); |
| | | priceDTO.setItems(dto.getItems()); |
| | | priceDTO.setInsured(dto.getDeclaredAmount() != null && dto.getDeclaredAmount().compareTo(BigDecimal.ZERO) > 0); |
| | | priceDTO.setDeclaredAmount(dto.getDeclaredAmount()); |
| | | priceDTO.setUrgent(Constants.ONE.equals(dto.getIsUrgent())); |
| | | priceResult = calculateRemotePrice(priceDTO); |
| | | } |
| | | |
| | | // ========== 5. 生成订单编号 ========== |
| | | String orderCode = "JC" + new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(now) |
| | | + String.format("%04d", new java.util.Random().nextInt(10000)); |
| | | // 生成32位唯一第三方订单编号 |
| | | String orderTradeNo = generateOrderTradeNo(); |
| | | |
| | | // ========== 6. 创建订单主表 ========== |
| | | Orders orders = new Orders(); |
| | | orders.setCode(orderCode); |
| | | orders.setOutTradeNo(orderTradeNo); |
| | | orders.setMemberId(memberId); |
| | | orders.setType(dto.getType()); |
| | | orders.setCityId(String.valueOf(dto.getCityId())); |
| | | orders.setStatus(Constants.ZERO); // 待支付 |
| | | orders.setPayStatus(Constants.ZERO); // 未支付 |
| | | orders.setCommentStatus(Constants.ZERO); // 未评价 |
| | | orders.setSettlementStatus(Constants.ZERO); // 未结算 |
| | | orders.setDeleted(Constants.ZERO); |
| | | orders.setCreateTime(now); |
| | | orders.setUpdateTime(now); |
| | | |
| | | // 寄件信息 |
| | | orders.setDepositShopId(dto.getDepositShopId()); |
| | | // 存件地点:省市区全路径 + 地址描述 |
| | | String depositLocationRemark = depositShop.getAddress(); |
| | | if (depositShop.getAreaId() != null) { |
| | | Areas depositArea = areasBiz.resolveArea(depositShop.getAreaId()); |
| | | if (depositArea != null) { |
| | | depositLocationRemark = depositArea.getProvinceName() + depositArea.getCityName() + depositArea.getName() + depositShop.getAddress(); |
| | | } |
| | | } |
| | | orders.setDepositLocation(depositLocationRemark); |
| | | orders.setDepositLocationRemark(depositShop.getAddress()); |
| | | orders.setDepositLat(BigDecimal.valueOf(depositShop.getLatitude())); |
| | | orders.setDepositLgt(BigDecimal.valueOf(depositShop.getLongitude())); |
| | | |
| | | // 取件信息 |
| | | orders.setTakeUser(dto.getTakeUser()); |
| | | orders.setTakePhone(dto.getTakePhone()); |
| | | orders.setExpectedDepositTime(depositTime); |
| | | orders.setExpectedTakeTime(takeTime); |
| | | // 计算预计存放天数 |
| | | long dayDiff = (takeTime.getTime() - depositTime.getTime()) / (1000 * 60 * 60 * 24); |
| | | orders.setEstimatedDepositDays((int) Math.max(1, dayDiff + 1)); |
| | | |
| | | if (Constants.ONE.equals(dto.getType())) { |
| | | // 异地:取件点信息 |
| | | orders.setTakeShopId(dto.getTakeShopId()); |
| | | orders.setTakeLocation(takeLocationValue); |
| | | orders.setTakeLat(takeLat); |
| | | orders.setTakeLgt(takeLgt); |
| | | orders.setIsUrgent(dto.getIsUrgent()); |
| | | } else { |
| | | // 就地:取件点同寄件店铺 |
| | | orders.setTakeShopId(dto.getDepositShopId()); |
| | | orders.setTakeLocation(depositShop.getAddress()); |
| | | orders.setTakeLat(BigDecimal.valueOf(depositShop.getLatitude())); |
| | | orders.setTakeLgt(BigDecimal.valueOf(depositShop.getLongitude())); |
| | | orders.setIsUrgent(Constants.ZERO); |
| | | } |
| | | |
| | | // 物品信息 |
| | | orders.setGoodType(dto.getGoodType()); |
| | | // 拼接物品信息:物品类型名称、尺寸名称*数量(数组字符串) |
| | | List<String> goodsParts = new ArrayList<>(); |
| | | for (ItemPriceVO itemVO : priceResult.getItemList()) { |
| | | goodsParts.add(itemVO.getCategoryName() + "*" + itemVO.getQuantity()); |
| | | } |
| | | orders.setGoodsInfo(goodTypeCategory.getName() + "、" + String.join(",", goodsParts)); |
| | | orders.setRemark(dto.getRemark()); |
| | | orders.setSelfTake(Constants.ZERO); |
| | | |
| | | // 费用信息(分) |
| | | orders.setBasicAmount(priceResult.getItemPrice()); |
| | | orders.setEstimatedAmount(priceResult.getTotalPrice()); |
| | | orders.setTotalAmount(priceResult.getTotalPrice()); |
| | | orders.setUrgentAmount(priceResult.getUrgentFee()); |
| | | if (dto.getDeclaredAmount() != null && dto.getDeclaredAmount().compareTo(BigDecimal.ZERO) > 0) { |
| | | orders.setDeclaredAmount(dto.getDeclaredAmount().multiply(new BigDecimal(100)).longValue()); |
| | | } else { |
| | | orders.setDeclaredAmount(0L); |
| | | } |
| | | orders.setDeclaredFee(priceResult.getInsuranceFee()); |
| | | orders.setPrice(priceResult.getItemPrice()); |
| | | |
| | | // 薪酬计算与占比存储 |
| | | calculateAndSetFeeAllocation(orders, depositShop, takeShop); |
| | | |
| | | ordersMapper.insert(orders); |
| | | Integer orderId = orders.getId(); |
| | | |
| | | // ========== 7. 创建订单明细 ========== |
| | | for (ItemPriceVO itemVO : priceResult.getItemList()) { |
| | | OrdersDetail detail = new OrdersDetail(); |
| | | detail.setOrderId(orderId); |
| | | detail.setLuggageId(itemVO.getCategoryId()); |
| | | detail.setLuggageName(itemVO.getCategoryName()); |
| | | detail.setLuggageDetail(itemVO.getDetail()); |
| | | detail.setNum(itemVO.getQuantity()); |
| | | detail.setUnitPrice(itemVO.getUnitPrice()); |
| | | detail.setStartDistance(itemVO.getStartDistance()); |
| | | detail.setStartPrice(itemVO.getStartPrice()); |
| | | detail.setExtraDistance(itemVO.getExtraDistance()); |
| | | detail.setExtraPrice(itemVO.getExtraPrice()); |
| | | detail.setLocallyPrice(itemVO.getLocallyPrice()); |
| | | detail.setDeleted(Constants.ZERO); |
| | | detail.setCreateTime(now); |
| | | ordersDetailMapper.insert(detail); |
| | | } |
| | | // ========== 8. 保存物品图片附件 ========== |
| | | if (dto.getGoodsImages() != null && !dto.getGoodsImages().isEmpty()) { |
| | | int sortNum = 1; |
| | | for (String imgUrl : dto.getGoodsImages()) { |
| | | Multifile multifile = new Multifile(); |
| | | multifile.setObjId(orderId); |
| | | multifile.setObjType(Constants.FileType.ORDER_FILE.getKey()); |
| | | multifile.setType(Constants.ZERO); |
| | | multifile.setFileurl(imgUrl); |
| | | multifile.setIsdeleted(Constants.ZERO); |
| | | multifile.setCreateDate(now); |
| | | multifile.setSortnum(sortNum++); |
| | | multifileMapper.insert(multifile); |
| | | } |
| | | } |
| | | // ========== 9. 唤起微信支付 ========== |
| | | Member member = memberMapper.selectById(memberId); |
| | | if (member == null || StringUtils.isBlank(member.getOpenid())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "用户信息异常,无法发起支付"); |
| | | } |
| | | PayResponse payResponse = wxPay(orders, member.getOpenid(), Constants.OrdersAttach.STORAGE_ORDER); |
| | | payResponse.setLockKey(lockKey); |
| | | return payResponse; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public PayResponse continuePay(Integer orderId, Integer memberId) { |
| | | // 1. 查询订单 |
| | | Orders orders = ordersMapper.selectById(orderId); |
| | | if (Objects.isNull(orders) || Constants.equalsInteger(orders.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | // 2. 校验订单归属 |
| | | if (!Constants.equalsInteger(orders.getMemberId(), memberId)) { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "无权操作该订单"); |
| | | } |
| | | // 3. 校验订单状态:仅待支付可继续支付 |
| | | if (!Constants.equalsInteger(orders.getStatus(), Constants.ZERO)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "当前订单状态不支持继续支付"); |
| | | } |
| | | // 4. 校验支付金额 |
| | | if (orders.getTotalAmount() == null || orders.getTotalAmount() <= 0) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "订单金额异常,无法发起支付"); |
| | | } |
| | | // 5. 重新生成第三方订单编号(避免重复) |
| | | String orderTradeNo = generateOrderTradeNo(); |
| | | orders.setOutTradeNo(orderTradeNo); |
| | | orders.setUpdateTime(new Date()); |
| | | ordersMapper.updateById(orders); |
| | | // 6. 唤起微信支付 |
| | | Member member = memberMapper.selectById(memberId); |
| | | if (member == null || StringUtils.isBlank(member.getOpenid())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "用户信息异常,无法发起支付"); |
| | | } |
| | | return wxPay(orders, member.getOpenid(), Constants.OrdersAttach.STORAGE_ORDER); |
| | | } |
| | | |
| | | /** |
| | | * 唤起微信小程序支付 |
| | | * |
| | | * @param orders 订单实体(需要 code、totalAmount) |
| | | * @param openid 用户微信openid |
| | | * @param ordersAttach 订单支付类型 |
| | | * @return PayResponse 包含微信调起参数和订单主键 |
| | | */ |
| | | private PayResponse wxPay(Orders orders, String openid, Constants.OrdersAttach ordersAttach) { |
| | | try { |
| | | WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest(); |
| | | request.setBody(ordersAttach.getName()); |
| | | request.setAttach(ordersAttach.getKey()); |
| | | request.setOutTradeNo(orders.getOutTradeNo()); |
| | | // totalAmount 单位为分,WeChat Pay setTotalFee 也是分,直接转int |
| | | long totalFee = orders.getTotalAmount() != null ? orders.getTotalAmount() : 0L; |
| | | request.setTotalFee((int) totalFee); |
| | | request.setTimeStart(DateUtil.DateToString(new Date(), "yyyyMMddHHmmss")); |
| | | request.setSpbillCreateIp(Constants.getIpAddr()); |
| | | request.setOpenid(openid); |
| | | |
| | | Object response = WxMiniConfig.wxPayService.createOrder(request); |
| | | |
| | | PayResponse payResponse = new PayResponse(); |
| | | payResponse.setResponse(response); |
| | | payResponse.setOrderId(orders.getId()); |
| | | return payResponse; |
| | | } catch (WxPayException e) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "支付调起失败:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | @Override |
| | | public OrderDetailVO findDetail(Integer id) { |
| | | Orders order = ordersMapper.selectById(id); |
| | | if (Objects.isNull(order)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | |
| | | OrderDetailVO vo = new OrderDetailVO(); |
| | | vo.setOrder(order); |
| | | |
| | | // 图片路径前缀 |
| | | String imgPrefix = getOrdersPrefix(); |
| | | |
| | | // 下单图片 (type=12) |
| | | vo.setOrderFiles(getFileUrls(id, Constants.FileType.ORDER_FILE.getKey(), imgPrefix)); |
| | | |
| | | // 会员信息 |
| | | if (order.getMemberId() != null) { |
| | | Member member = memberMapper.selectById(order.getMemberId()); |
| | | if (member != null) { |
| | | vo.setMemberName(member.getName()); |
| | | vo.setMemberPhone(member.getTelephone()); |
| | | } |
| | | } |
| | | |
| | | // 寄存门店信息 |
| | | if (order.getDepositShopId() != null) { |
| | | ShopInfo depositShop = shopInfoMapper.selectById(order.getDepositShopId()); |
| | | if (depositShop != null) { |
| | | vo.setDepositShopName(depositShop.getName()); |
| | | vo.setDepositShopPhone(depositShop.getLinkPhone()); |
| | | } |
| | | } |
| | | |
| | | // 取件门店信息 |
| | | if (order.getTakeShopId() != null) { |
| | | ShopInfo takeShop = shopInfoMapper.selectById(order.getTakeShopId()); |
| | | if (takeShop != null) { |
| | | vo.setTakeShopName(takeShop.getName()); |
| | | vo.setTakeShopAddress(takeShop.getAddress()); |
| | | vo.setTakeShopPhone(takeShop.getLinkPhone()); |
| | | } |
| | | } |
| | | |
| | | // 接单司机信息 |
| | | if (order.getAcceptDriver() != null) { |
| | | DriverInfo driverInfo = driverInfoMapper.selectById(order.getAcceptDriver()); |
| | | if (driverInfo != null) { |
| | | vo.setDriverName(driverInfo.getName()); |
| | | } |
| | | } |
| | | |
| | | // 配送附件图片 |
| | | vo.setDepositImages(getFileUrls(id, Constants.FileType.ORDER_DEPOSIT.getKey(), imgPrefix)); |
| | | vo.setStoreInImages(getFileUrls(id, Constants.FileType.ORDER_TAKE.getKey(), imgPrefix)); |
| | | vo.setDriverTakeImages(getFileUrls(id, Constants.FileType.DRIVER_TAKE.getKey(), imgPrefix)); |
| | | vo.setDriverDoneImages(getFileUrls(id, Constants.FileType.DRIVER_DONE.getKey(), imgPrefix)); |
| | | vo.setStoreOutImages(getFileUrls(id, Constants.FileType.STORE_OUT.getKey(), imgPrefix)); |
| | | // 物品明细 |
| | | vo.setDetailList(buildDetailList(id)); |
| | | Category category = categoryMapper.selectById(order.getGoodType()); |
| | | if(CollectionUtils.isNotEmpty(vo.getDetailList())&&Objects.nonNull(category)){ |
| | | for (OrderItemVO v:vo.getDetailList()) { |
| | | v.setTypeName(category.getName()); |
| | | } |
| | | } |
| | | |
| | | // 取消/退款状态时查询退款记录 |
| | | Integer status = order.getStatus(); |
| | | if (status != null && (status == Constants.OrderStatus.overdue.getStatus() |
| | | || status == Constants.OrderStatus.closed.getStatus() |
| | | || status == Constants.OrderStatus.cancelOverdue.getStatus() |
| | | || status == Constants.OrderStatus.cancelling.getStatus() |
| | | || status == Constants.OrderStatus.cancelled.getStatus())) { |
| | | OrdersRefund ordersRefund = ordersRefundMapper.selectOne( |
| | | new QueryWrapper<OrdersRefund>().lambda() |
| | | .eq(OrdersRefund::getOrderId, id) |
| | | .eq(OrdersRefund::getDeleted, Constants.ZERO) |
| | | .orderByDesc(OrdersRefund::getCreateTime) |
| | | .last("limit 1")); |
| | | if (ordersRefund != null) { |
| | | vo.setOrdersRefund(ordersRefund); |
| | | // 退款方式:1=平台直接取消 → 返回平台操作人名称 |
| | | if (Constants.equalsInteger(ordersRefund.getType(), Constants.ONE) && ordersRefund.getUserId() != null) { |
| | | // userId 关联 system_user 表,查询操作人名称 |
| | | vo.setPlatformUserName(getPlatformUserName(ordersRefund.getUserId())); |
| | | } |
| | | // 退款方式:2=已存件申请取消 → 返回退款取件图片 (multifile objType=14) |
| | | if (Constants.equalsInteger(ordersRefund.getType(), Constants.TWO)) { |
| | | vo.setRefundTakeImages(getFileUrls(id, Constants.FileType.REFUND_TAKE.getKey(), imgPrefix)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | | public OrderDispatchVO findDispatchInfo(Integer id) { |
| | | Orders order = ordersMapper.selectById(id); |
| | | if (Objects.isNull(order)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | |
| | | OrderDispatchVO vo = new OrderDispatchVO(); |
| | | vo.setCode(order.getCode()); |
| | | vo.setPayAmountYuan(order.getPayAmount() != null ? Constants.getFormatMoney(order.getPayAmount()) : 0); |
| | | vo.setType(order.getType()); |
| | | vo.setTypeDesc(order.getType() != null && order.getType() == Constants.ONE ? "异地存取" : "就地存取"); |
| | | vo.setDetailList(buildDetailList(id)); |
| | | |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = {Exception.class, BusinessException.class}) |
| | | public void dispatch(DispatchDTO dto) { |
| | | // 参数校验 |
| | | if (dto == null || dto.getOrderId() == null || dto.getUrgentFee() == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "订单主键和加急费用不能为空"); |
| | | } |
| | | |
| | | Orders order = ordersMapper.selectById(dto.getOrderId()); |
| | | if (Objects.isNull(order)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | |
| | | // 前置条件校验:异地存取 + 已寄存 |
| | | if (!Constants.ONE.equals(order.getType())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅支持异地存取订单派单"); |
| | | } |
| | | if (!Integer.valueOf(Constants.OrderStatus.deposited.getStatus()).equals(order.getStatus())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅已寄存状态订单可派单"); |
| | | } |
| | | |
| | | String optUserName = getCurrentUserName(); |
| | | |
| | | // 加急费日志(每次单独记录本次加急费) |
| | | Constants.OrderLogType urgentLogType = Constants.OrderLogType.urgent; |
| | | OrderLog feeLog = new OrderLog(); |
| | | feeLog.setOrderId(order.getId()); |
| | | feeLog.setTitle(urgentLogType.getTitle()); |
| | | feeLog.setLogInfo(urgentLogType.getStatusInfo().replace("{param}", dto.getUrgentFee().toPlainString())); |
| | | feeLog.setObjType(urgentLogType.getStatus()); |
| | | feeLog.setOrderStatus(order.getStatus()); |
| | | feeLog.setOptUserType(3); |
| | | feeLog.setOptUserName(optUserName); |
| | | feeLog.setCreateTime(new Date()); |
| | | feeLog.setDeleted(Constants.ZERO); |
| | | orderLogService.create(feeLog); |
| | | |
| | | // 加急费用 元→分 |
| | | long urgentFeeFen = dto.getUrgentFee().multiply(new BigDecimal(100)).longValue(); |
| | | |
| | | // 使用 UpdateWrapper 精确更新,不影响其他字段 |
| | | com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper<Orders> updateWrapper = |
| | | new UpdateWrapper<Orders>().lambda() |
| | | .eq(Orders::getId, order.getId()) |
| | | .set(Orders::getIsUrgent, Constants.ONE) |
| | | .set(Orders::getPlatformRewardAmount, urgentFeeFen) |
| | | .set(Orders::getUpdateTime, new Date()); |
| | | |
| | | // 异地寄存且有取件门店时,生成司机核销码 |
| | | if (order.getTakeShopId() != null) { |
| | | String driverVerifyCode = generateVerifyCode(); |
| | | updateWrapper.set(Orders::getDriverVerifyCode, driverVerifyCode); |
| | | } |
| | | |
| | | // 备注 |
| | | if (StringUtils.isNotBlank(dto.getRemark())) { |
| | | updateWrapper.set(Orders::getRemark, dto.getRemark()); |
| | | } |
| | | |
| | | // 指派司机(非必填) |
| | | if (dto.getDriverId() != null) { |
| | | updateWrapper.set(Orders::getAssignDriverId, dto.getDriverId()); |
| | | |
| | | Member driver = memberMapper.selectById(dto.getDriverId()); |
| | | String driverName = driver != null ? driver.getName() : String.valueOf(dto.getDriverId()); |
| | | |
| | | Constants.OrderLogType dispatchLogType = Constants.OrderLogType.dispatch; |
| | | OrderLog driverLog = new OrderLog(); |
| | | driverLog.setOrderId(order.getId()); |
| | | driverLog.setTitle(dispatchLogType.getTitle()); |
| | | driverLog.setLogInfo(dispatchLogType.getStatusInfo().replace("{param}", driverName)); |
| | | driverLog.setObjType(dispatchLogType.getStatus()); |
| | | driverLog.setOrderStatus(order.getStatus()); |
| | | driverLog.setOptUserType(3); |
| | | driverLog.setOptUserName(optUserName); |
| | | driverLog.setCreateTime(new Date()); |
| | | driverLog.setDeleted(Constants.ZERO); |
| | | orderLogService.create(driverLog); |
| | | } |
| | | |
| | | ordersMapper.update(updateWrapper); |
| | | } |
| | | |
| | | private String getCurrentUserName() { |
| | | try { |
| | | com.doumee.core.model.LoginUserInfo user = |
| | | (com.doumee.core.model.LoginUserInfo) org.apache.shiro.SecurityUtils.getSubject().getPrincipal(); |
| | | return user != null ? user.getUsername() : "系统"; |
| | | } catch (Exception e) { |
| | | return "系统"; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 构建订单物品明细列表 |
| | | */ |
| | | private List<OrderItemVO> buildDetailList(Integer orderId) { |
| | | List<OrdersDetail> details = ordersDetailMapper.selectList( |
| | | new QueryWrapper<OrdersDetail>().lambda() |
| | | .eq(OrdersDetail::getOrderId, orderId) |
| | | .eq(OrdersDetail::getDeleted, Constants.ZERO)); |
| | | return buildDetailList(details); |
| | | } |
| | | |
| | | /** |
| | | * 根据已查询的明细构建物品列表(避免重复查询) |
| | | */ |
| | | private List<OrderItemVO> buildDetailList(List<OrdersDetail> details) { |
| | | List<OrderItemVO> items = new ArrayList<>(); |
| | | if (details != null) { |
| | | for (OrdersDetail d : details) { |
| | | OrderItemVO item = new OrderItemVO(); |
| | | item.setLuggageName(d.getLuggageName()); |
| | | item.setLuggageDetail(d.getLuggageDetail()); |
| | | item.setNum(d.getNum()); |
| | | double unitPriceYuan = d.getUnitPrice() != null ? Constants.getFormatMoney(d.getUnitPrice()) : 0; |
| | | item.setUnitPriceYuan(unitPriceYuan); |
| | | item.setSubtotal(unitPriceYuan * (d.getNum() != null ? d.getNum() : 0)); |
| | | items.add(item); |
| | | } |
| | | } |
| | | return items; |
| | | } |
| | | |
| | | /** |
| | | * 生成32位唯一第三方订单编号(时间戳17位 + 随机数15位) |
| | | */ |
| | | private String generateOrderTradeNo() { |
| | | return new java.text.SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) |
| | | + String.format("%015d", Math.abs(new java.util.Random().nextLong() % 1000000000000000L)); |
| | | } |
| | | |
| | | /** |
| | | * 生成6位数字核销码(Redis验重) |
| | | * 使用 SETNX 抢占,保证唯一;使用完毕后调用 releaseVerifyCode 从 Redis 移除 |
| | | */ |
| | | private String generateVerifyCode() { |
| | | Random random = new Random(); |
| | | String redisKey = Constants.REDIS_VERIFY_CODE_KEY; |
| | | for (int i = 0; i < 200; i++) { |
| | | String code = String.format("%06d", random.nextInt(1000000)); |
| | | Boolean success = redisTemplate.opsForValue().setIfAbsent(redisKey + code, "1", 24, TimeUnit.HOURS); |
| | | if (success != null && success) { |
| | | return code; |
| | | } |
| | | } |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "核销码生成失败,请重试"); |
| | | } |
| | | |
| | | /** |
| | | * 释放核销码占位(核销完成后调用,移除 Redis 中的 key) |
| | | */ |
| | | public void releaseVerifyCode(String code) { |
| | | if (StringUtils.isNotBlank(code)) { |
| | | redisTemplate.delete(Constants.REDIS_VERIFY_CODE_KEY + code); |
| | | } |
| | | } |
| | | |
| | | private String getOrdersPrefix() { |
| | | try { |
| | | return systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.RESOURCE_PATH).getCode() |
| | | + systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.ORDERS_FILES).getCode(); |
| | | } catch (Exception e) { |
| | | return ""; |
| | | } |
| | | } |
| | | |
| | | private String getPlatformUserName(Integer userId) { |
| | | SystemUser user = systemUserMapper.selectById(userId); |
| | | return user != null ? user.getRealname() : null; |
| | | } |
| | | |
| | | private List<String> getFileUrls(Integer orderId, int objType, String prefix) { |
| | | List<Multifile> files = multifileMapper.selectList( |
| | | new QueryWrapper<Multifile>().lambda() |
| | | .eq(Multifile::getObjId, orderId) |
| | | .eq(Multifile::getObjType, objType) |
| | | .eq(Multifile::getIsdeleted, Constants.ZERO) |
| | | .orderByAsc(Multifile::getSortnum)); |
| | | List<String> urls = new ArrayList<>(); |
| | | if (files != null) { |
| | | for (Multifile f : files) { |
| | | if (StringUtils.isNotBlank(f.getFileurl())) { |
| | | urls.add(prefix + f.getFileurl()); |
| | | } |
| | | } |
| | | } |
| | | return urls; |
| | | } |
| | | |
| | | /** |
| | | * 计算并设置订单薪酬分配(司机、存件门店、取件门店) |
| | | * 从 pricing_rule (type=4) 读取分成比例,根据门店企业/个人类型区分 |
| | | * |
| | | * @param orders 订单实体(需要 totalAmount、cityId 已设置) |
| | | * @param depositShop 寄件门店(需要 companyType) |
| | | * @param takeShop 取件门店(需要 companyType,就地存取时与 depositShop 相同) |
| | | */ |
| | | private void calculateAndSetFeeAllocation(Orders orders, ShopInfo depositShop, ShopInfo takeShop) { |
| | | Long totalAmount = orders.getTotalAmount() != null ? orders.getTotalAmount() : 0L; |
| | | if (totalAmount <= 0) { |
| | | orders.setDriverFee(0L); |
| | | orders.setDepositShopFee(0L); |
| | | orders.setTakeShopFee(0L); |
| | | orders.setDriverFeeRata(BigDecimal.ZERO); |
| | | orders.setDepositShopFeeRata(BigDecimal.ZERO); |
| | | orders.setTakeShopFeeRata(BigDecimal.ZERO); |
| | | return; |
| | | } |
| | | Integer cityId = Integer.valueOf(orders.getCityId()); |
| | | |
| | | // 司机占比:fieldA=4(配送员) |
| | | BigDecimal driverRata = getRevenueShareRata(cityId, Constants.FOUR); |
| | | // 寄件门店占比:fieldA=0(企业寄)/1(个人寄) |
| | | int depositFieldA = Constants.equalsInteger(depositShop.getCompanyType(), Constants.ONE) ? Constants.ZERO : Constants.ONE; |
| | | BigDecimal depositShopRata = getRevenueShareRata(cityId, depositFieldA); |
| | | // 取件门店占比:fieldA=2(企业取)/3(个人取) |
| | | int takeFieldA = Constants.equalsInteger(takeShop.getCompanyType(), Constants.ONE) ? Constants.TWO : Constants.THREE; |
| | | BigDecimal takeShopRata = getRevenueShareRata(cityId, takeFieldA); |
| | | |
| | | // 计算薪酬(分):totalAmount 为分,rata 为比例值(如 0.15 表示 15%) |
| | | long driverFee = new BigDecimal(totalAmount).multiply(driverRata).longValue(); |
| | | long depositShopFee = new BigDecimal(totalAmount).multiply(depositShopRata).longValue(); |
| | | long takeShopFee = totalAmount - driverFee - depositShopFee; |
| | | |
| | | orders.setDriverFee(driverFee); |
| | | orders.setDepositShopFee(depositShopFee); |
| | | orders.setTakeShopFee(takeShopFee); |
| | | orders.setDriverFeeRata(driverRata); |
| | | orders.setDepositShopFeeRata(depositShopRata); |
| | | orders.setTakeShopFeeRata(takeShopRata); |
| | | } |
| | | |
| | | /** |
| | | * 从 pricing_rule 表获取分成比例(type=4) |
| | | * |
| | | * @param cityId 城市主键 |
| | | * @param fieldA 类型:0=企业寄, 1=个人寄, 2=企业取, 3=个人取, 4=配送员 |
| | | * @return 分成比例(如 0.15 表示 15%) |
| | | */ |
| | | private BigDecimal getRevenueShareRata(Integer cityId, int fieldA) { |
| | | PricingRule rule = pricingRuleMapper.selectOne(new QueryWrapper<PricingRule>().lambda() |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .eq(PricingRule::getType, Constants.FOUR) |
| | | .eq(PricingRule::getCityId, cityId) |
| | | .eq(PricingRule::getFieldA, String.valueOf(fieldA)) |
| | | .last("limit 1")); |
| | | if (rule != null && StringUtils.isNotBlank(rule.getFieldC())) { |
| | | return new BigDecimal(rule.getFieldC()); |
| | | } |
| | | return BigDecimal.ZERO; |
| | | } |
| | | |
| | | @Override |
| | | public PageData<MyOrderVO> findMyOrderPage(PageWrap<MyOrderDTO> pageWrap, Integer memberId) { |
| | | MyOrderDTO model = pageWrap.getModel(); |
| | | Integer status = model != null ? model.getStatus() : null; |
| | | Integer combinedStatus = model != null ? model.getCombinedStatus() : null; |
| | | |
| | | // 解析合并状态为具体状态列表 |
| | | List<Integer> statusList = null; |
| | | if (combinedStatus != null) { |
| | | Constants.OrderCombinedStatus combined = Constants.OrderCombinedStatus.getByKey(combinedStatus); |
| | | if (combined != null) { |
| | | statusList = new ArrayList<>(); |
| | | for (int s : combined.getStatuses()) { |
| | | statusList.add(s); |
| | | } |
| | | } |
| | | } |
| | | |
| | | IPage<Orders> p = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); |
| | | MPJLambdaWrapper<Orders> wrapper = new MPJLambdaWrapper<Orders>() |
| | | .selectAll(Orders.class) |
| | | .select("s1.name", Orders::getDepositShopName) |
| | | .select("s1.link_name", Orders::getDepositShopLinkName) |
| | | .select("s1.link_phone", Orders::getDepositShopLinkPhone) |
| | | .select("s2.name", Orders::getTakeShopName) |
| | | .select("s2.address", Orders::getTakeShopAddress) |
| | | .leftJoin("shop_info s1 on s1.id = t.DEPOSIT_SHOP_ID") |
| | | .leftJoin("shop_info s2 on s2.id = t.TAKE_SHOP_ID") |
| | | .eq(Orders::getDeleted, Constants.ZERO) |
| | | .eq(Orders::getMemberId, memberId) |
| | | .eq(status != null, Orders::getStatus, status) |
| | | .in(statusList != null, Orders::getStatus, statusList) |
| | | .orderByDesc(Orders::getCreateTime); |
| | | |
| | | IPage<Orders> orderPage = ordersMapper.selectJoinPage(p, Orders.class, wrapper); |
| | | List<MyOrderVO> voList = new ArrayList<>(); |
| | | if (orderPage != null && orderPage.getRecords() != null) { |
| | | |
| | | for (Orders o : orderPage.getRecords()) { |
| | | MyOrderVO vo = new MyOrderVO(); |
| | | vo.setId(o.getId()); |
| | | vo.setCode(o.getCode()); |
| | | vo.setType(o.getType()); |
| | | vo.setStatus(o.getStatus()); |
| | | vo.setCreateTime(o.getCreateTime()); |
| | | vo.setExpectedTakeTime(o.getExpectedTakeTime()); |
| | | |
| | | // 存件门店(关联查询直接取值) |
| | | vo.setDepositShopName(o.getDepositShopName()); |
| | | vo.setDepositShopLinkName(o.getDepositShopLinkName()); |
| | | vo.setDepositShopPhone(o.getDepositShopLinkPhone()); |
| | | |
| | | // 取件信息:有取件门店取门店,无则取用户自选取件点 |
| | | if (o.getTakeShopId() != null) { |
| | | vo.setTakeShopName(o.getTakeShopName()); |
| | | vo.setTakeShopAddress(o.getTakeShopAddress()); |
| | | } else { |
| | | vo.setTakeLocation(o.getTakeLocation()); |
| | | vo.setTakeLocationRemark(o.getTakeLocationRemark()); |
| | | } |
| | | |
| | | // 取件联系人 |
| | | vo.setTakeUser(o.getTakeUser()); |
| | | vo.setTakePhone(o.getTakePhone()); |
| | | |
| | | // 费用(分) |
| | | vo.setDeclaredFee(o.getDeclaredFee()); |
| | | vo.setEstimatedAmount(o.getEstimatedAmount()); |
| | | |
| | | // 查询物品明细(一次查询,同时用于物品列表和逾期计算) |
| | | List<OrdersDetail> details = ordersDetailMapper.selectList( |
| | | new QueryWrapper<OrdersDetail>().lambda() |
| | | .eq(OrdersDetail::getOrderId, o.getId()) |
| | | .eq(OrdersDetail::getDeleted, Constants.ZERO)); |
| | | |
| | | // 物品明细 |
| | | vo.setDetailList(buildDetailList(details)); |
| | | |
| | | // 逾期信息(仅待取件状态计算) |
| | | if (Integer.valueOf(Constants.OrderStatus.arrived.getStatus()).equals(o.getStatus())) { |
| | | OverdueFeeVO overdueInfo = calculateOverdueFeeInternal(o, details); |
| | | vo.setOverdue(overdueInfo.getOverdue()); |
| | | vo.setOverdueDays(overdueInfo.getOverdueDays()); |
| | | vo.setOverdueFee(overdueInfo.getOverdueFee()); |
| | | } |
| | | voList.add(vo); |
| | | } |
| | | } |
| | | |
| | | IPage<MyOrderVO> vPage = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); |
| | | PageData<MyOrderVO> pageData = PageData.from(vPage); |
| | | pageData.setRecords(voList); |
| | | pageData.setTotal(orderPage.getTotal()); |
| | | pageData.setPage(orderPage.getCurrent()); |
| | | pageData.setCapacity(orderPage.getSize()); |
| | | return pageData; |
| | | } |
| | | |
| | | @Override |
| | | public MyOrderDetailVO findMyOrderDetail(Integer id, Integer memberId) { |
| | | Orders order = ordersMapper.selectOne(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getId, id) |
| | | .eq(Orders::getMemberId, memberId) |
| | | .eq(Orders::getDeleted, Constants.ZERO)); |
| | | if (order == null) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | return buildOrderDetailVO(order, true); |
| | | } |
| | | |
| | | @Override |
| | | public MyOrderDetailVO findShopOrderDetail(Integer orderId, String verifyCode) { |
| | | Orders order = null; |
| | | if (orderId != null) { |
| | | order = ordersMapper.selectOne(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getId, orderId) |
| | | .eq(Orders::getDeleted, Constants.ZERO)); |
| | | } else if (StringUtils.isNotBlank(verifyCode)) { |
| | | order = ordersMapper.selectOne(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getMemberVerifyCode, verifyCode) |
| | | .eq(Orders::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | if (order == null) { |
| | | order = ordersMapper.selectOne(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getDriverVerifyCode, verifyCode) |
| | | .eq(Orders::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | } |
| | | } |
| | | if (order == null) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "订单不存在"); |
| | | } |
| | | return buildOrderDetailVO(order, false); |
| | | } |
| | | |
| | | /** |
| | | * 构建订单详情VO(会员端/门店端复用) |
| | | * |
| | | * @param order 订单实体 |
| | | * @param memberViewMode true=会员端(按条件返回核销码),false=门店端(始终返回核销码) |
| | | */ |
| | | private MyOrderDetailVO buildOrderDetailVO(Orders order, boolean memberViewMode) { |
| | | MyOrderDetailVO vo = new MyOrderDetailVO(); |
| | | vo.setId(order.getId()); |
| | | vo.setStatus(order.getStatus()); |
| | | vo.setType(order.getType()); |
| | | vo.setCode(order.getCode()); |
| | | vo.setOutTradeNo(order.getOutTradeNo()); |
| | | vo.setRemark(order.getRemark()); |
| | | vo.setCreateTime(order.getCreateTime()); |
| | | vo.setPayTime(order.getPayTime()); |
| | | vo.setExpectedDepositTime(order.getExpectedDepositTime()); |
| | | vo.setExpectedTakeTime(order.getExpectedTakeTime()); |
| | | vo.setArriveTime(order.getArriveTime()); |
| | | |
| | | // 费用(分) |
| | | vo.setBasicAmount(order.getBasicAmount()); |
| | | vo.setDeclaredAmount(order.getDeclaredAmount()); |
| | | vo.setDeclaredFee(order.getDeclaredFee()); |
| | | vo.setUrgentAmount(order.getUrgentAmount()); |
| | | vo.setActualPayAmount(order.getPayAmount()); |
| | | |
| | | // 标记 |
| | | vo.setExceptionStatus(order.getExceptionStatus()); |
| | | |
| | | // 是否超出取件时间 |
| | | vo.setPastTakeTime(order.getExpectedTakeTime() != null && new Date().after(order.getExpectedTakeTime())); |
| | | |
| | | // 订单状态描述 + 倒计时 |
| | | vo.setStatusDesc(buildStatusDesc(order)); |
| | | if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.waitPay.getStatus())) { |
| | | vo.setPayCountdownMs(calcPayCountdownMs(order)); |
| | | } |
| | | |
| | | // 存件门店 |
| | | if (order.getDepositShopId() != null) { |
| | | ShopInfo depositShop = shopInfoMapper.selectById(order.getDepositShopId()); |
| | | if (depositShop != null) { |
| | | vo.setDepositShopName(depositShop.getName()); |
| | | vo.setDepositShopLinkName(depositShop.getLinkName()); |
| | | vo.setDepositShopPhone(depositShop.getLinkPhone()); |
| | | vo.setDepositShopAddress(depositShop.getAddress()); |
| | | } |
| | | } |
| | | |
| | | // 取件信息 |
| | | if (order.getTakeShopId() != null) { |
| | | ShopInfo takeShop = shopInfoMapper.selectById(order.getTakeShopId()); |
| | | if (takeShop != null) { |
| | | vo.setTakeShopName(takeShop.getName()); |
| | | vo.setTakeShopAddress(takeShop.getAddress()); |
| | | } |
| | | } else { |
| | | vo.setTakeLocation(order.getTakeLocation()); |
| | | vo.setTakeLocationRemark(order.getTakeLocationRemark()); |
| | | } |
| | | |
| | | // 取件联系人 |
| | | vo.setTakeUser(order.getTakeUser()); |
| | | vo.setTakePhone(order.getTakePhone()); |
| | | |
| | | // 物品类型名称 |
| | | if (order.getGoodType() != null) { |
| | | Category category = categoryMapper.selectById(order.getGoodType()); |
| | | if (category != null) { |
| | | vo.setGoodTypeName(category.getName()); |
| | | } |
| | | } |
| | | |
| | | // 下单照片 |
| | | String imgPrefix = getOrdersPrefix(); |
| | | vo.setOrderImages(getFileUrls(order.getId(), Constants.FileType.ORDER_FILE.getKey(), imgPrefix)); |
| | | |
| | | // 物品明细 |
| | | List<OrdersDetail> details = ordersDetailMapper.selectList( |
| | | new QueryWrapper<OrdersDetail>().lambda() |
| | | .eq(OrdersDetail::getOrderId, order.getId()) |
| | | .eq(OrdersDetail::getDeleted, Constants.ZERO)); |
| | | vo.setDetailList(buildDetailList(details)); |
| | | |
| | | // 逾期信息 |
| | | OverdueFeeVO overdueInfo = calculateOverdueFeeInternal(order, details); |
| | | vo.setOverdue(overdueInfo.getOverdue()); |
| | | vo.setOverdueDays(overdueInfo.getOverdueDays()); |
| | | vo.setOverdueFee(overdueInfo.getOverdueFee()); |
| | | |
| | | // 核销码 |
| | | Integer status = order.getStatus(); |
| | | if (memberViewMode) { |
| | | // 会员端:待寄存(1)返回;待取件(5)时,就地寄存无取件门店不返回 |
| | | boolean returnCode = false; |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.waitDeposit.getStatus())) { |
| | | returnCode = true; |
| | | } else if (Constants.equalsInteger(status, Constants.OrderStatus.arrived.getStatus())) { |
| | | if (!(Constants.equalsInteger(order.getType(), Constants.ZERO) && order.getTakeShopId() == null)) { |
| | | returnCode = true; |
| | | } |
| | | } |
| | | if (returnCode) { |
| | | vo.setMemberVerifyCode(order.getMemberVerifyCode()); |
| | | } |
| | | } else { |
| | | // 门店端:始终返回会员核销码 |
| | | vo.setMemberVerifyCode(order.getMemberVerifyCode()); |
| | | } |
| | | |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = {Exception.class, BusinessException.class}) |
| | | public void cancelOrder(Integer orderId, Integer memberId, String reason) { |
| | | Orders order = ordersMapper.selectOne(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getId, orderId) |
| | | .eq(Orders::getMemberId, memberId) |
| | | .eq(Orders::getDeleted, Constants.ZERO)); |
| | | if (order == null) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | |
| | | // 仅异地寄存可取消 |
| | | if (!Constants.equalsInteger(order.getType(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅异地寄存订单可取消"); |
| | | } |
| | | |
| | | Integer status = order.getStatus(); |
| | | if (status == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "订单状态异常"); |
| | | } |
| | | |
| | | Date now = new Date(); |
| | | |
| | | // 待支付:直接取消 |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.waitPay.getStatus())) { |
| | | order.setStatus(Constants.OrderStatus.cancelled.getStatus()); |
| | | order.setCancelTime(now); |
| | | ordersMapper.updateById(order); |
| | | saveCancelLog(order, "会员取消订单(待支付)", reason, memberId); |
| | | return; |
| | | } |
| | | |
| | | // 待寄存:直接取消,全额退款 |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.waitDeposit.getStatus())) { |
| | | // 记录退款信息 |
| | | OrdersRefund refund = new OrdersRefund(); |
| | | refund.setOrderId(orderId); |
| | | refund.setType(0); // 未寄存直接取消 |
| | | refund.setCancelInfo(reason); |
| | | refund.setCreateTime(now); |
| | | refund.setDeleted(Constants.ZERO); |
| | | |
| | | // 调用微信退款,全额退款 |
| | | String refundCode = wxMiniUtilService.wxRefund(order.getOutTradeNo(), order.getPayAmount(), order.getPayAmount()); |
| | | refund.setRefundCode(refundCode); |
| | | refund.setRefundTime(new Date()); |
| | | ordersRefundMapper.insert(refund); |
| | | |
| | | order.setStatus(Constants.OrderStatus.cancelled.getStatus()); |
| | | order.setCancelTime(now); |
| | | order.setRefundAmount(order.getPayAmount()); |
| | | ordersMapper.updateById(order); |
| | | |
| | | saveCancelLog(order, "会员取消订单(待寄存,全额退款)", reason, memberId); |
| | | return; |
| | | } |
| | | |
| | | // 已寄存/已接单:进入取消中状态 |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.deposited.getStatus()) |
| | | || Constants.equalsInteger(status, Constants.OrderStatus.accepted.getStatus())) { |
| | | order.setStatus(Constants.OrderStatus.cancelling.getStatus()); |
| | | order.setCancelTime(now); |
| | | ordersMapper.updateById(order); |
| | | saveCancelLog(order, "会员申请取消订单(已寄存/已接单)", reason, memberId); |
| | | return; |
| | | } |
| | | |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "当前订单状态不允许取消"); |
| | | } |
| | | |
| | | /** |
| | | * 保存取消订单操作日志 |
| | | */ |
| | | private void saveCancelLog(Orders order, String title, String reason, Integer memberId) { |
| | | OrderLog log = new OrderLog(); |
| | | log.setOrderId(order.getId()); |
| | | log.setTitle(title); |
| | | log.setLogInfo(reason); |
| | | log.setObjType(Constants.ORDER_LOG_CANCEL); |
| | | log.setOrderStatus(order.getStatus()); |
| | | log.setOptUserId(memberId); |
| | | log.setOptUserType(0); // 0=用户 |
| | | log.setCreateTime(new Date()); |
| | | log.setDeleted(Constants.ZERO); |
| | | orderLogService.create(log); |
| | | } |
| | | |
| | | /** |
| | | * 保存门店核销日志 |
| | | */ |
| | | private void saveShopVerifyLog(Orders order, String title, String logInfo, String remark, Integer shopId) { |
| | | OrderLog log = new OrderLog(); |
| | | log.setOrderId(order.getId()); |
| | | log.setTitle(title); |
| | | log.setLogInfo(logInfo); |
| | | log.setRemark(remark); |
| | | log.setOrderStatus(order.getStatus()); |
| | | log.setOptUserId(shopId); |
| | | log.setOptUserType(2); // 2=门店 |
| | | log.setCreateTime(new Date()); |
| | | log.setDeleted(Constants.ZERO); |
| | | orderLogService.create(log); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = {Exception.class, BusinessException.class}) |
| | | public void handleStorageOrderPayNotify(String outTradeNo, String wxTradeNo) { |
| | | Orders order = ordersMapper.selectOne(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getOutTradeNo, outTradeNo) |
| | | .eq(Orders::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | if (order == null) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "订单不存在: " + outTradeNo); |
| | | } |
| | | // 幂等:已支付则跳过 |
| | | if (Constants.equalsInteger(order.getPayStatus(), Constants.ONE)) { |
| | | return; |
| | | } |
| | | Date now = new Date(); |
| | | order.setStatus(Constants.OrderStatus.waitDeposit.getStatus()); // 待寄存 |
| | | order.setPayStatus(Constants.ONE); // 已支付 |
| | | order.setPayTime(now); |
| | | order.setWxExternalNo(wxTradeNo); |
| | | order.setUpdateTime(now); |
| | | // 生成会员核销码 |
| | | order.setMemberVerifyCode(generateVerifyCode()); |
| | | ordersMapper.updateById(order); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = {Exception.class, BusinessException.class}) |
| | | public void shopVerifyOrder(String verifyCode, Integer shopId, List<String> images, String remark) { |
| | | if (StringUtils.isBlank(verifyCode)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "核销码不能为空"); |
| | | } |
| | | // 根据核销码查找订单(会员核销码) |
| | | Orders order = ordersMapper.selectOne(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getMemberVerifyCode, verifyCode) |
| | | .eq(Orders::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | if (order == null) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "核销码无效"); |
| | | } |
| | | |
| | | // 查询门店名称用于日志 |
| | | String shopName = ""; |
| | | ShopInfo shopInfo = shopInfoMapper.selectById(shopId); |
| | | if (shopInfo != null) { |
| | | shopName = shopInfo.getName() != null ? shopInfo.getName() : ""; |
| | | } |
| | | |
| | | Integer status = order.getStatus(); |
| | | Date now = new Date(); |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.waitDeposit.getStatus())) { |
| | | // 待寄存(1) → 已寄存(2),两种类型通用 |
| | | // 校验当前门店是否为订单的存件门店 |
| | | if (!shopId.equals(order.getDepositShopId())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单不属于当前门店,无法核销"); |
| | | } |
| | | order.setStatus(Constants.OrderStatus.deposited.getStatus()); |
| | | order.setDepositTime(now); |
| | | // 释放当前核销码,生成新的核销码供取件时使用 |
| | | releaseVerifyCode(verifyCode); |
| | | order.setMemberVerifyCode(generateVerifyCode()); |
| | | ordersMapper.updateById(order); |
| | | // 保存寄存图片(obj_type=2 订单寄存图片,最多3张) |
| | | saveVerifyImages(order.getId(), images, Constants.FileType.ORDER_DEPOSIT.getKey(), shopId); |
| | | // 记录订单日志 |
| | | saveShopVerifyLog(order, "门店确认寄存", "门店【" + shopName + "】确认寄存", remark, shopId); |
| | | } else if (Constants.equalsInteger(status, Constants.OrderStatus.arrived.getStatus())) { |
| | | // 异地寄存 + 无取件门店 → 无法核销(客户自取,无门店操作) |
| | | if (Constants.equalsInteger(order.getType(), Constants.ONE) && order.getTakeShopId() == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单无取件门店,无法核销"); |
| | | } |
| | | // 校验取件门店与当前登录门店一致 |
| | | if (!shopId.equals(order.getTakeShopId())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单不属于当前门店,无法核销"); |
| | | } |
| | | // 待取件(5) → 已完成(7) |
| | | order.setStatus(Constants.OrderStatus.finished.getStatus()); |
| | | order.setConfirmArriveTime(now); |
| | | ordersMapper.updateById(order); |
| | | // 订单完成,释放核销码 |
| | | releaseVerifyCode(verifyCode); |
| | | // 保存出库图片(obj_type=13 门店出库图片,最多3张) |
| | | saveVerifyImages(order.getId(), images, Constants.FileType.STORE_OUT.getKey(), shopId); |
| | | // 记录订单日志 |
| | | saveShopVerifyLog(order, "门店确认取件", "门店【" + shopName + "】确认取件,订单完成", remark, shopId); |
| | | } else { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "当前订单状态不允许核销"); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = {Exception.class, BusinessException.class}) |
| | | public void driverVerifyOrder(String verifyCode, List<String> images, String remark, Integer driverId) { |
| | | if (StringUtils.isBlank(verifyCode)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "核销码不能为空"); |
| | | } |
| | | // 根据司机核销码查找订单 |
| | | Orders order = ordersMapper.selectOne(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getDriverVerifyCode, verifyCode) |
| | | .eq(Orders::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | if (order == null) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "核销码无效"); |
| | | } |
| | | |
| | | // 仅异地寄存 + 有取件门店 + 派送中(4) 可核销 |
| | | if (!Constants.equalsInteger(order.getType(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅异地寄存订单支持司机核销"); |
| | | } |
| | | if (order.getTakeShopId() == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单无取件门店,无需司机核销"); |
| | | } |
| | | if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.delivering.getStatus())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "当前订单状态不允许核销"); |
| | | } |
| | | |
| | | // 派送中(4) → 已到店(5) |
| | | order.setStatus(Constants.OrderStatus.arrived.getStatus()); |
| | | order.setArriveTime(new Date()); |
| | | if (StringUtils.isNotBlank(remark)) { |
| | | order.setRemark(remark); |
| | | } |
| | | ordersMapper.updateById(order); |
| | | |
| | | // 释放司机核销码 |
| | | releaseVerifyCode(verifyCode); |
| | | |
| | | // 保存附件(obj_type=3 门店入库图片,最多3张) |
| | | saveVerifyImages(order.getId(), images, Constants.FileType.ORDER_TAKE.getKey(), driverId); |
| | | } |
| | | |
| | | /** |
| | | * 保存核销附件到 multifile 表 |
| | | * |
| | | * @param orderId 订单主键 |
| | | * @param images 图片地址列表(最多3张) |
| | | * @param objType 附件类型 |
| | | * @param creator 创建人编码 |
| | | */ |
| | | private void saveVerifyImages(Integer orderId, List<String> images, int objType, Integer creator) { |
| | | if (images == null || images.isEmpty()) return; |
| | | List<String> saveImages = images.size() > 3 ? images.subList(0, 3) : images; |
| | | Date now = new Date(); |
| | | int sortNum = 1; |
| | | for (String imgUrl : saveImages) { |
| | | if (StringUtils.isBlank(imgUrl)) continue; |
| | | Multifile multifile = new Multifile(); |
| | | multifile.setObjId(orderId); |
| | | multifile.setObjType(objType); |
| | | multifile.setFileurl(imgUrl); |
| | | multifile.setType(Constants.ZERO); |
| | | multifile.setCreator(creator); |
| | | multifile.setCreateDate(now); |
| | | multifile.setIsdeleted(Constants.ZERO); |
| | | multifile.setSortnum(sortNum++); |
| | | multifileMapper.insert(multifile); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = {Exception.class, BusinessException.class}) |
| | | public void confirmCustomerArrived(Integer orderId, Integer shopId) { |
| | | // 1. 查询订单 |
| | | Orders order = ordersMapper.selectById(orderId); |
| | | if (order == null || Constants.equalsInteger(order.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "订单不存在"); |
| | | } |
| | | |
| | | // 2. 校验订单状态:待取件(5) |
| | | if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.arrived.getStatus())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "当前订单状态不允许该操作"); |
| | | } |
| | | |
| | | // 3. 校验门店与订单关系 |
| | | if (Constants.equalsInteger(order.getType(), Constants.ONE) && order.getTakeShopId() != null) { |
| | | // 异地寄存有取件门店:校验取件门店 |
| | | if (!shopId.equals(order.getTakeShopId())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单不属于当前门店"); |
| | | } |
| | | } else if (Constants.equalsInteger(order.getType(), Constants.ZERO)) { |
| | | // 就地寄存:校验存件门店(取件门店同存件门店) |
| | | if (!shopId.equals(order.getDepositShopId())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单不属于当前门店"); |
| | | } |
| | | } else { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单无取件门店,无法确认到店"); |
| | | } |
| | | |
| | | // 4. 查询门店名称(用于日志) |
| | | String shopName = ""; |
| | | ShopInfo shopInfo = shopInfoMapper.selectById(shopId); |
| | | if (shopInfo != null) { |
| | | shopName = shopInfo.getName() != null ? shopInfo.getName() : ""; |
| | | } |
| | | |
| | | // 5. 计算逾期费用 |
| | | List<OrdersDetail> details = ordersDetailMapper.selectList( |
| | | new QueryWrapper<OrdersDetail>().lambda() |
| | | .eq(OrdersDetail::getOrderId, orderId) |
| | | .eq(OrdersDetail::getDeleted, Constants.ZERO)); |
| | | OverdueFeeVO overdueInfo = calculateOverdueFeeInternal(order, details); |
| | | |
| | | Date now = new Date(); |
| | | |
| | | if (overdueInfo.getOverdue() && overdueInfo.getOverdueDays() > 0) { |
| | | // 存在逾期:标记逾期状态,订单保持当前状态 |
| | | order.setConfirmArriveTime(now); |
| | | order.setOverdueStatus(Constants.ONE); |
| | | order.setOverdueDays(overdueInfo.getOverdueDays()); |
| | | order.setOverdueAmount(overdueInfo.getOverdueFee()); |
| | | order.setUpdateTime(now); |
| | | ordersMapper.updateById(order); |
| | | |
| | | // 记录订单日志 |
| | | saveShopVerifyLog(order, "确认顾客到店(逾期)", |
| | | "门店【" + shopName + "】确认顾客到店,逾期" + overdueInfo.getOverdueDays() |
| | | + "天,逾期费用" + Constants.getFormatMoney(overdueInfo.getOverdueFee()) + "元", |
| | | null, shopId); |
| | | } else { |
| | | // 未逾期:完成订单 |
| | | order.setStatus(Constants.OrderStatus.finished.getStatus()); |
| | | order.setConfirmArriveTime(now); |
| | | order.setFinishTime(now); |
| | | order.setOverdueStatus(Constants.ZERO); |
| | | order.setUpdateTime(now); |
| | | ordersMapper.updateById(order); |
| | | |
| | | // 释放核销码 |
| | | if (StringUtils.isNotBlank(order.getMemberVerifyCode())) { |
| | | releaseVerifyCode(order.getMemberVerifyCode()); |
| | | } |
| | | |
| | | // 记录订单日志 |
| | | saveShopVerifyLog(order, "确认顾客到店", |
| | | "门店【" + shopName + "】确认顾客到店,订单完成", |
| | | null, shopId); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 构建订单状态描述 |
| | | */ |
| | | private String buildStatusDesc(Orders order) { |
| | | boolean isLocal = Constants.equalsInteger(order.getType(), Constants.ZERO); |
| | | Integer status = order.getStatus(); |
| | | if (status == null) return ""; |
| | | |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.waitPay.getStatus())) { |
| | | String minutes = ""; |
| | | try { |
| | | minutes = operationConfigBiz.getConfig().getAutoCancelTime(); |
| | | } catch (Exception ignored) {} |
| | | return "请在" + (StringUtils.isNotBlank(minutes) ? minutes : "") + "分钟内完成支付,超时订单将自动取消"; |
| | | } |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.waitDeposit.getStatus())) { |
| | | return isLocal ? "订单已支付,请等待门店确认接单" : "订单已支付,请等待门店确认接单"; |
| | | } |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.deposited.getStatus())) { |
| | | return isLocal ? "行李已寄存,请凭取件码前往指定门店取件" : "门店已接单,正在为您安排取件司机"; |
| | | } |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.accepted.getStatus())) { |
| | | return isLocal ? "行李已寄存,请凭取件码前往指定门店取件" : "已有司机抢单,正前往取件地点"; |
| | | } |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.delivering.getStatus())) { |
| | | return "司机已取件,正运往目的地"; |
| | | } |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.arrived.getStatus())) { |
| | | return "行李已送达服务点,请及时前往取件"; |
| | | } |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.finished.getStatus())) { |
| | | if (Constants.equalsInteger(order.getCommentStatus(), Constants.ONE)) { |
| | | return "感谢您的用心评价,祝您出行顺利,旅途愉快!"; |
| | | } |
| | | return "订单已完成,感谢您的支持,请对本次服务做出评价"; |
| | | } |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.cancelled.getStatus())) { |
| | | return "订单已取消,感谢您的支持,欢迎下次再会!"; |
| | | } |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.cancelling.getStatus())) { |
| | | return "退款申请已提交,平台会尽快为您处理退款"; |
| | | } |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.closed.getStatus())) { |
| | | return "退款已成功原路返回,请注意查收"; |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | /** |
| | | * 计算支付倒计时毫秒 |
| | | */ |
| | | private Long calcPayCountdownMs(Orders order) { |
| | | try { |
| | | String minutesStr = operationConfigBiz.getConfig().getAutoCancelTime(); |
| | | if (StringUtils.isBlank(minutesStr)) return -1L; |
| | | int minutes = Integer.parseInt(minutesStr); |
| | | long deadline = order.getCreateTime().getTime() + minutes * 60 * 1000L; |
| | | long remaining = deadline - System.currentTimeMillis(); |
| | | return remaining > 0 ? remaining : -1L; |
| | | } catch (Exception e) { |
| | | return -1L; |
| | | } |
| | | } |
| | | public OverdueFeeVO calculateOverdueFee(Integer orderId) { |
| | | Orders order = ordersMapper.selectById(orderId); |
| | | if (order == null || Constants.equalsInteger(order.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | |
| | | // 查询订单明细 |
| | | List<OrdersDetail> details = ordersDetailMapper.selectList( |
| | | new QueryWrapper<OrdersDetail>().lambda() |
| | | .eq(OrdersDetail::getOrderId, orderId) |
| | | .eq(OrdersDetail::getDeleted, Constants.ZERO)); |
| | | |
| | | return calculateOverdueFeeInternal(order, details); |
| | | } |
| | | |
| | | /** |
| | | * 逾期费用内部计算(不查库,接受预查询的数据) |
| | | * 供分页等已查询明细的业务场景复用,避免重复查询 |
| | | */ |
| | | private OverdueFeeVO calculateOverdueFeeInternal(Orders order, List<OrdersDetail> details) { |
| | | if (CollectionUtils.isEmpty(details)) { |
| | | OverdueFeeVO vo = new OverdueFeeVO(); |
| | | vo.setOverdue(false); |
| | | vo.setOverdueDays(0); |
| | | vo.setOverdueFee(0L); |
| | | vo.setDailyBaseFee(0L); |
| | | return vo; |
| | | } |
| | | |
| | | // 物品基础日费用 = Σ(单价 × 数量) |
| | | long dailyBaseFee = 0L; |
| | | for (OrdersDetail d : details) { |
| | | dailyBaseFee += (d.getUnitPrice() != null ? d.getUnitPrice() : 0L) |
| | | * (d.getNum() != null ? d.getNum() : 0); |
| | | } |
| | | |
| | | Date now = new Date(); |
| | | int overdueDays; |
| | | long overdueFee; |
| | | |
| | | if (Constants.equalsInteger(order.getType(), Constants.ZERO)) { |
| | | // ========== 就地寄存 ========== |
| | | overdueDays = calcLocalOverdueDays(now, order.getExpectedTakeTime()); |
| | | overdueFee = (long) overdueDays * dailyBaseFee; |
| | | |
| | | OverdueFeeVO vo = new OverdueFeeVO(); |
| | | vo.setOverdue(overdueDays > 0); |
| | | vo.setOverdueDays(overdueDays); |
| | | vo.setOverdueFee(overdueFee); |
| | | vo.setDailyBaseFee(dailyBaseFee); |
| | | return vo; |
| | | |
| | | } else { |
| | | // ========== 异地寄存 ========== |
| | | // 条件:存在取件门店 且 订单处于已到店状态(5) |
| | | if (order.getTakeShopId() == null |
| | | || !Constants.equalsInteger(order.getStatus(), Constants.FIVE)) { |
| | | OverdueFeeVO vo = new OverdueFeeVO(); |
| | | vo.setOverdue(false); |
| | | vo.setOverdueDays(0); |
| | | vo.setOverdueFee(0L); |
| | | vo.setDailyBaseFee(dailyBaseFee); |
| | | vo.setDiscountRate(null); |
| | | return vo; |
| | | } |
| | | |
| | | overdueDays = calcRemoteOverdueDays(now, order.getArriveTime()); |
| | | |
| | | // 折扣比率 |
| | | String discountStr = operationConfigBiz.getConfig().getUnpickedDiscount(); |
| | | BigDecimal discountRate = StringUtils.isNotBlank(discountStr) |
| | | ? new BigDecimal(discountStr) : BigDecimal.ONE; |
| | | |
| | | overdueFee = new BigDecimal(overdueDays) |
| | | .multiply(new BigDecimal(dailyBaseFee)) |
| | | .multiply(discountRate) |
| | | .setScale(0, RoundingMode.HALF_UP) |
| | | .longValue(); |
| | | |
| | | OverdueFeeVO vo = new OverdueFeeVO(); |
| | | vo.setOverdue(overdueDays > 0); |
| | | vo.setOverdueDays(overdueDays); |
| | | vo.setOverdueFee(overdueFee); |
| | | vo.setDailyBaseFee(dailyBaseFee); |
| | | vo.setDiscountRate(discountStr); |
| | | return vo; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 就地寄存逾期天数计算 |
| | | * 过了预计取件时间当天的12点后才算一天 |
| | | */ |
| | | private int calcLocalOverdueDays(Date now, Date expectedTakeTime) { |
| | | if (expectedTakeTime == null || !now.after(expectedTakeTime)) { |
| | | return 0; |
| | | } |
| | | // 基准时间 = 预计取件日期的12:00 |
| | | Calendar baseCal = Calendar.getInstance(); |
| | | baseCal.setTime(expectedTakeTime); |
| | | baseCal.set(Calendar.HOUR_OF_DAY, 12); |
| | | baseCal.set(Calendar.MINUTE, 0); |
| | | baseCal.set(Calendar.SECOND, 0); |
| | | baseCal.set(Calendar.MILLISECOND, 0); |
| | | Date baseTime = baseCal.getTime(); |
| | | |
| | | if (!now.after(baseTime)) { |
| | | return 0; |
| | | } |
| | | // 逾期天数 = 当前日期 - 基准日期(按天取差) |
| | | Calendar nowCal = Calendar.getInstance(); |
| | | nowCal.setTime(now); |
| | | nowCal.set(Calendar.HOUR_OF_DAY, 0); |
| | | nowCal.set(Calendar.MINUTE, 0); |
| | | nowCal.set(Calendar.SECOND, 0); |
| | | nowCal.set(Calendar.MILLISECOND, 0); |
| | | |
| | | Calendar baseDateCal = Calendar.getInstance(); |
| | | baseDateCal.setTime(baseTime); |
| | | baseDateCal.set(Calendar.HOUR_OF_DAY, 0); |
| | | baseDateCal.set(Calendar.MINUTE, 0); |
| | | baseDateCal.set(Calendar.SECOND, 0); |
| | | baseDateCal.set(Calendar.MILLISECOND, 0); |
| | | |
| | | long diffMs = nowCal.getTimeInMillis() - baseDateCal.getTimeInMillis(); |
| | | int days = (int) (diffMs / (1000 * 60 * 60 * 24)); |
| | | return Math.max(days, 0); |
| | | } |
| | | |
| | | /** |
| | | * 异地寄存逾期天数计算 |
| | | * 过了转移到店时间当天的晚上12点(24:00)后才算第一天 |
| | | */ |
| | | private int calcRemoteOverdueDays(Date now, Date arriveTime) { |
| | | if (arriveTime == null || !now.after(arriveTime)) { |
| | | return 0; |
| | | } |
| | | // 基准时间 = 转移到店日期的次日 00:00(即当天24:00) |
| | | Calendar baseCal = Calendar.getInstance(); |
| | | baseCal.setTime(arriveTime); |
| | | baseCal.set(Calendar.HOUR_OF_DAY, 0); |
| | | baseCal.set(Calendar.MINUTE, 0); |
| | | baseCal.set(Calendar.SECOND, 0); |
| | | baseCal.set(Calendar.MILLISECOND, 0); |
| | | baseCal.add(Calendar.DAY_OF_MONTH, 1); // 次日00:00 = 当天24:00 |
| | | Date baseTime = baseCal.getTime(); |
| | | |
| | | if (!now.after(baseTime)) { |
| | | return 0; |
| | | } |
| | | // 逾期天数 = 当前日期 - 基准日期 |
| | | Calendar nowCal = Calendar.getInstance(); |
| | | nowCal.setTime(now); |
| | | nowCal.set(Calendar.HOUR_OF_DAY, 0); |
| | | nowCal.set(Calendar.MINUTE, 0); |
| | | nowCal.set(Calendar.SECOND, 0); |
| | | nowCal.set(Calendar.MILLISECOND, 0); |
| | | |
| | | Calendar baseDateCal = Calendar.getInstance(); |
| | | baseDateCal.setTime(baseTime); |
| | | baseDateCal.set(Calendar.HOUR_OF_DAY, 0); |
| | | baseDateCal.set(Calendar.MINUTE, 0); |
| | | baseDateCal.set(Calendar.SECOND, 0); |
| | | baseDateCal.set(Calendar.MILLISECOND, 0); |
| | | |
| | | long diffMs = nowCal.getTimeInMillis() - baseDateCal.getTimeInMillis(); |
| | | int days = (int) (diffMs / (1000 * 60 * 60 * 24)); |
| | | return Math.max(days, 0); |
| | | } |
| | | |
| | | } |
| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void saveEstimatedDelivery(EstimatedDeliverySaveDTO request) { |
| | | // 查询已有规则 type=2, fieldA=1, cityId, deleted=0 |
| | | QueryWrapper<PricingRule> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(PricingRule::getType, Constants.TWO) |
| | | .eq(PricingRule::getFieldA, "1") |
| | | .eq(PricingRule::getCityId, request.getCityId()) |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .last("limit 1"); |
| | | PricingRule existing = pricingRuleMapper.selectOne(qw); |
| | | |
| | | if (request.getItems() == null || request.getItems().isEmpty()) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "时效配置列表不能为空"); |
| | | } |
| | | Date now = new Date(); |
| | | if (existing != null) { |
| | | // 更新 |
| | | existing.setFieldB(request.getStartDistance()); |
| | | existing.setFieldC(request.getStartTime()); |
| | | existing.setFieldD(request.getContinueDistance()); |
| | | existing.setFieldE(request.getContinueTime()); |
| | | existing.setUpdateTime(now); |
| | | pricingRuleMapper.updateById(existing); |
| | | } else { |
| | | // 新增 |
| | | PricingRule rule = new PricingRule(); |
| | | rule.setType(Constants.TWO); |
| | | rule.setFieldA("1"); |
| | | rule.setFieldB(request.getStartDistance()); |
| | | rule.setFieldC(request.getStartTime()); |
| | | rule.setFieldD(request.getContinueDistance()); |
| | | rule.setFieldE(request.getContinueTime()); |
| | | rule.setCityId(request.getCityId()); |
| | | rule.setDeleted(Constants.ZERO); |
| | | rule.setCreateTime(now); |
| | | rule.setUpdateTime(now); |
| | | pricingRuleMapper.insert(rule); |
| | | for (EstimatedDeliverySaveDTO.EstimatedDeliveryItem item : request.getItems()) { |
| | | // 查询已有规则 type=2, fieldA, cityId, deleted=0 |
| | | QueryWrapper<PricingRule> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(PricingRule::getType, Constants.TWO) |
| | | .eq(PricingRule::getFieldA, String.valueOf(item.getFieldA())) |
| | | .eq(PricingRule::getCityId, request.getCityId()) |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .last("limit 1"); |
| | | PricingRule existing = pricingRuleMapper.selectOne(qw); |
| | | |
| | | if (existing != null) { |
| | | existing.setFieldB(item.getStartDistance()); |
| | | existing.setFieldC(item.getStartTime()); |
| | | existing.setFieldD(item.getContinueDistance()); |
| | | existing.setFieldE(item.getContinueTime()); |
| | | existing.setUpdateTime(now); |
| | | pricingRuleMapper.updateById(existing); |
| | | } else { |
| | | PricingRule rule = new PricingRule(); |
| | | rule.setType(Constants.TWO); |
| | | rule.setFieldA(String.valueOf(item.getFieldA())); |
| | | rule.setFieldB(item.getStartDistance()); |
| | | rule.setFieldC(item.getStartTime()); |
| | | rule.setFieldD(item.getContinueDistance()); |
| | | rule.setFieldE(item.getContinueTime()); |
| | | rule.setCityId(request.getCityId()); |
| | | rule.setDeleted(Constants.ZERO); |
| | | rule.setCreateTime(now); |
| | | rule.setUpdateTime(now); |
| | | pricingRuleMapper.insert(rule); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public EstimatedDeliveryVO getEstimatedDelivery(Integer cityId) { |
| | | public List<EstimatedDeliveryVO> getEstimatedDelivery(Integer cityId) { |
| | | QueryWrapper<PricingRule> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(PricingRule::getType, Constants.TWO) |
| | | .eq(PricingRule::getFieldA, "1") |
| | | .in(PricingRule::getFieldA, "1", "2") |
| | | .eq(PricingRule::getCityId, cityId) |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .orderByAsc(PricingRule::getFieldA); |
| | | List<PricingRule> rules = pricingRuleMapper.selectList(qw); |
| | | |
| | | // 将已有规则按fieldA分组 |
| | | Map<String, PricingRule> ruleMap = new HashMap<>(); |
| | | for (PricingRule rule : rules) { |
| | | ruleMap.put(rule.getFieldA(), rule); |
| | | } |
| | | |
| | | // 固定返回2条:fieldA=1(标速达), fieldA=2(极速达),无数据时返回空对象 |
| | | List<EstimatedDeliveryVO> voList = new ArrayList<>(); |
| | | for (int fieldA = 1; fieldA <= 2; fieldA++) { |
| | | EstimatedDeliveryVO vo = new EstimatedDeliveryVO(); |
| | | vo.setCityId(cityId); |
| | | vo.setFieldA(fieldA); |
| | | PricingRule rule = ruleMap.get(String.valueOf(fieldA)); |
| | | if (rule != null) { |
| | | vo.setPricingRuleId(rule.getId()); |
| | | vo.setStartDistance(rule.getFieldB()); |
| | | vo.setStartTime(rule.getFieldC()); |
| | | vo.setContinueDistance(rule.getFieldD()); |
| | | vo.setContinueTime(rule.getFieldE()); |
| | | } |
| | | voList.add(vo); |
| | | } |
| | | return voList; |
| | | } |
| | | |
| | | @Override |
| | | public BigDecimal calculateEstimatedTime(Integer cityId, Integer fieldA, BigDecimal distance) { |
| | | if (cityId == null || fieldA == null || distance == null) { |
| | | return null; |
| | | } |
| | | QueryWrapper<PricingRule> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(PricingRule::getType, Constants.TWO) |
| | | .eq(PricingRule::getFieldA, String.valueOf(fieldA)) |
| | | .eq(PricingRule::getCityId, cityId) |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .last("limit 1"); |
| | | PricingRule rule = pricingRuleMapper.selectOne(qw); |
| | | |
| | | EstimatedDeliveryVO vo = new EstimatedDeliveryVO(); |
| | | vo.setCityId(cityId); |
| | | if (rule != null) { |
| | | vo.setPricingRuleId(rule.getId()); |
| | | vo.setStartDistance(rule.getFieldB()); |
| | | vo.setStartTime(rule.getFieldC()); |
| | | vo.setContinueDistance(rule.getFieldD()); |
| | | vo.setContinueTime(rule.getFieldE()); |
| | | if (rule == null) { |
| | | return null; |
| | | } |
| | | return vo; |
| | | // fieldB=起送里程, fieldC=起送时长, fieldD=续送里程, fieldE=续送时长 |
| | | BigDecimal startDistance = new BigDecimal(rule.getFieldB()); |
| | | BigDecimal startTime = new BigDecimal(rule.getFieldC()); |
| | | BigDecimal continueDistance = new BigDecimal(rule.getFieldD()); |
| | | BigDecimal continueTime = new BigDecimal(rule.getFieldE()); |
| | | |
| | | // 距离 <= 起送里程 → 直接返回起送时长 |
| | | if (distance.compareTo(startDistance) <= 0) { |
| | | return startTime; |
| | | } |
| | | // 超出部分:向上取整 * 续送时长 + 起送时长 |
| | | BigDecimal extraDistance = distance.subtract(startDistance); |
| | | BigDecimal extraCount = extraDistance.divide(continueDistance, 0, RoundingMode.CEILING); |
| | | return startTime.add(extraCount.multiply(continueTime)); |
| | | } |
| | | |
| | | @Override |
| | |
| | | package com.doumee.service.business.impl; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.doumee.config.jwt.JwtTokenUtil; |
| | | import com.doumee.core.constants.Constants; |
| | | import com.doumee.core.constants.ResponseStatus; |
| | | import com.doumee.core.exception.BusinessException; |
| | |
| | | import com.doumee.dao.business.model.Member; |
| | | import com.doumee.dao.business.model.Multifile; |
| | | import com.doumee.dao.business.model.ShopInfo; |
| | | import com.doumee.dao.dto.AuditDTO; |
| | | import com.doumee.dao.dto.ChangeStatusDTO; |
| | | import com.doumee.dao.dto.ResetPasswordDTO; |
| | | import com.doumee.dao.dto.ShopApplyDTO; |
| | | import com.doumee.dao.dto.ShopUpdateDTO; |
| | | import com.doumee.dao.dto.*; |
| | | import com.doumee.dao.system.SystemUserMapper; |
| | | import com.doumee.dao.system.model.SystemUser; |
| | | import com.doumee.dao.vo.ShopDetailVO; |
| | | import com.doumee.dao.vo.ShopLoginVO; |
| | | import com.doumee.dao.vo.ShopNearbyVO; |
| | | import com.doumee.dao.vo.ShopWebDetailVO; |
| | | import com.doumee.service.business.ShopInfoService; |
| | | import org.apache.commons.collections.CollectionUtils; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.apache.commons.lang3.RandomStringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | |
| | | private SystemDictDataBiz systemDictDataBiz; |
| | | |
| | | @Autowired |
| | | private SystemUserMapper systemUserMapper; |
| | | |
| | | @Autowired |
| | | private AreasBiz areasBiz; |
| | | |
| | | @Autowired |
| | | private RedisTemplate<String,Object> redisTemplate; |
| | | @Override |
| | | public Integer create(ShopInfo shopInfo) { |
| | | shopInfoMapper.insert(shopInfo); |
| | |
| | | } |
| | | if (pageWrap.getModel().getAuditStatus() != null) { |
| | | queryWrapper.lambda().eq(ShopInfo::getAuditStatus, pageWrap.getModel().getAuditStatus()); |
| | | } |
| | | if (pageWrap.getModel().getAuditStatusList() != null && !pageWrap.getModel().getAuditStatusList().isEmpty()) { |
| | | queryWrapper.lambda().in(ShopInfo::getAuditStatus, pageWrap.getModel().getAuditStatusList()); |
| | | } |
| | | if (pageWrap.getModel().getStatus() != null) { |
| | | queryWrapper.lambda().eq(ShopInfo::getStatus, pageWrap.getModel().getStatus()); |
| | |
| | | vo.setAuditStatus(shopInfo.getAuditStatus()); |
| | | vo.setStatus(shopInfo.getStatus()); |
| | | vo.setAuditTime(shopInfo.getAuditTime()); |
| | | if(Objects.nonNull(shopInfo.getAuditUserId())){ |
| | | SystemUser systemUser = systemUserMapper.selectById(shopInfo.getAuditUserId()); |
| | | if (systemUser != null) vo.setAuditName(systemUser.getRealname()); |
| | | |
| | | } |
| | | vo.setAuditRemark(shopInfo.getAuditRemark()); |
| | | vo.setOpenid(shopInfo.getOpenid()); |
| | | vo.setPayStatus(shopInfo.getPayStatus()); |
| | |
| | | } |
| | | vo.setImgPrefix(imgPrefix); |
| | | |
| | | // 单图字段返回半路径 |
| | | // 单图字段:半路径 + 全路径 |
| | | vo.setIdcardImg(shopInfo.getIdcardImg()); |
| | | vo.setIdcardImgUrl(StringUtils.isNotBlank(shopInfo.getIdcardImg()) ? imgPrefix + shopInfo.getIdcardImg() : null); |
| | | vo.setIdcardImgBack(shopInfo.getIdcardImgBack()); |
| | | vo.setIdcardImgBackUrl(StringUtils.isNotBlank(shopInfo.getIdcardImgBack()) ? imgPrefix + shopInfo.getIdcardImgBack() : null); |
| | | vo.setBusinessImg(shopInfo.getBusinessImg()); |
| | | vo.setBusinessImgUrl(StringUtils.isNotBlank(shopInfo.getBusinessImg()) ? imgPrefix + shopInfo.getBusinessImg() : null); |
| | | |
| | | // 查询附件 |
| | | QueryWrapper<Multifile> fileQw = new QueryWrapper<>(); |
| | |
| | | .orderByAsc(Multifile::getObjType, Multifile::getSortnum); |
| | | List<Multifile> files = multifileMapper.selectList(fileQw); |
| | | |
| | | // 按 objType 分组,返回半路径 |
| | | // 按 objType 分组,半路径 + 全路径 |
| | | Map<Integer, List<String>> fileMap = new HashMap<>(); |
| | | Map<Integer, List<String>> fileUrlMap = new HashMap<>(); |
| | | for (Multifile f : files) { |
| | | fileMap.computeIfAbsent(f.getObjType(), k -> new ArrayList<>()).add(f.getFileurl()); |
| | | String fullUrl = StringUtils.isNotBlank(f.getFileurl()) ? imgPrefix + f.getFileurl() : f.getFileurl(); |
| | | fileUrlMap.computeIfAbsent(f.getObjType(), k -> new ArrayList<>()).add(fullUrl); |
| | | } |
| | | |
| | | vo.setStoreFrontImgs(fileMap.getOrDefault(Constants.FileType.STORE_FRONT.getKey(), new ArrayList<>())); |
| | |
| | | vo.setLaborContractImgs(fileMap.getOrDefault(Constants.FileType.LABOR_CONTRACT.getKey(), new ArrayList<>())); |
| | | vo.setSocialSecurityImgs(fileMap.getOrDefault(Constants.FileType.SOCIAL_SECURITY.getKey(), new ArrayList<>())); |
| | | |
| | | vo.setStoreFrontImgUrls(fileUrlMap.getOrDefault(Constants.FileType.STORE_FRONT.getKey(), new ArrayList<>())); |
| | | vo.setStoreInteriorImgUrls(fileUrlMap.getOrDefault(Constants.FileType.STORE_INTERIOR.getKey(), new ArrayList<>())); |
| | | vo.setOtherMaterialImgUrls(fileUrlMap.getOrDefault(Constants.FileType.OTHER_MATERIAL.getKey(), new ArrayList<>())); |
| | | vo.setLaborContractImgUrls(fileUrlMap.getOrDefault(Constants.FileType.LABOR_CONTRACT.getKey(), new ArrayList<>())); |
| | | vo.setSocialSecurityImgUrls(fileUrlMap.getOrDefault(Constants.FileType.SOCIAL_SECURITY.getKey(), new ArrayList<>())); |
| | | |
| | | // 查询绑定开户会员头像(payMemberOpenId 关联 member.openid) |
| | | if (StringUtils.isNotBlank(shopInfo.getPayMemberOpenId())) { |
| | | QueryWrapper<Member> memberQw = new QueryWrapper<>(); |
| | | memberQw.lambda().eq(Member::getOpenid, shopInfo.getPayMemberOpenId()).last("limit 1"); |
| | | Member payMember = memberMapper.selectOne(memberQw); |
| | | if (payMember != null) { |
| | | vo.setPayMemberCoverImage(payMember.getCoverImage()); |
| | | if (payMember != null && StringUtils.isNotBlank(payMember.getCoverImage())) { |
| | | String memberPrefix = ""; |
| | | try { |
| | | memberPrefix = systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.RESOURCE_PATH).getCode() |
| | | + systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.MEMBER_FILES).getCode(); |
| | | } catch (Exception e) { |
| | | // 未配置时忽略 |
| | | } |
| | | vo.setPayMemberCoverImage(memberPrefix + payMember.getCoverImage()); |
| | | } |
| | | } |
| | | |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | | public PageData<ShopNearbyVO> findNearbyShops(PageWrap<ShopNearbyDTO> pageWrap) { |
| | | IPage<ShopInfo> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); |
| | | ShopNearbyDTO dto = pageWrap.getModel(); |
| | | Double longitude = dto.getLongitude(); |
| | | Double latitude = dto.getLatitude(); |
| | | Integer sortType = dto.getSortType(); |
| | | Integer distanceMeter = dto.getDistance(); |
| | | |
| | | // Haversine距离公式(单位km) |
| | | String distanceFormula = "(6371 * acos(cos(radians(" + latitude + ")) * cos(radians(latitude)) " + |
| | | "* cos(radians(longitude) - radians(" + longitude + ")) " + |
| | | "+ sin(radians(" + latitude + ")) * sin(radians(latitude))))"; |
| | | |
| | | QueryWrapper<ShopInfo> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .eq(ShopInfo::getStatus, Constants.ZERO) |
| | | .eq(ShopInfo::getAuditStatus, Constants.THREE); |
| | | |
| | | // 门店营业类型筛选 |
| | | if (dto.getBusinessType() != null) { |
| | | qw.lambda().eq(ShopInfo::getBusinessType, dto.getBusinessType()); |
| | | } |
| | | |
| | | // 门店名称模糊查询 |
| | | if (StringUtils.isNotBlank(dto.getName())) { |
| | | qw.lambda().like(ShopInfo::getName, dto.getName()); |
| | | } |
| | | |
| | | // 距离筛选(单位:米 → 转换为km比较) |
| | | if (distanceMeter != null && distanceMeter > 0) { |
| | | double maxKm = distanceMeter / 1000.0; |
| | | qw.apply(distanceFormula + " <= {0}", maxKm); |
| | | } |
| | | |
| | | // 排序 |
| | | if (longitude != null && latitude != null) { |
| | | if (sortType != null && sortType == 2) { |
| | | // 按评分降序 |
| | | qw.last("ORDER BY score DESC"); |
| | | } else { |
| | | // 默认:按距离升序 |
| | | qw.last("ORDER BY " + distanceFormula + " ASC"); |
| | | } |
| | | } else { |
| | | qw.lambda().orderByDesc(ShopInfo::getCreateTime); |
| | | } |
| | | |
| | | IPage<ShopInfo> result = shopInfoMapper.selectPage(page, qw); |
| | | |
| | | // 图片前缀 |
| | | String imgPrefix = getShopPrefix(); |
| | | |
| | | List<ShopNearbyVO> voList = new ArrayList<>(); |
| | | for (ShopInfo shop : result.getRecords()) { |
| | | ShopNearbyVO vo = new ShopNearbyVO(); |
| | | vo.setId(shop.getId()); |
| | | vo.setName(shop.getName()); |
| | | vo.setShopHours(shop.getShopHours()); |
| | | vo.setAddress(shop.getAddress()); |
| | | vo.setScore(shop.getScore()); |
| | | // 门头照第一张 |
| | | vo.setCoverImg(getFirstImage(shop.getId(), Constants.FileType.STORE_FRONT.getKey(), imgPrefix)); |
| | | // 距离 |
| | | if (longitude != null && latitude != null && shop.getLongitude() != null && shop.getLatitude() != null) { |
| | | double distKm = haversine(latitude, longitude, shop.getLatitude(), shop.getLongitude()); |
| | | vo.setDistanceText(formatDistance(distKm)); |
| | | } |
| | | voList.add(vo); |
| | | } |
| | | IPage<ShopNearbyVO> vPage = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); |
| | | PageData<ShopNearbyVO> pageData = PageData.from(vPage); |
| | | pageData.setRecords(voList); |
| | | pageData.setTotal(result.getTotal()); |
| | | pageData.setPage(result.getCurrent()); |
| | | pageData.setCapacity(result.getSize()); |
| | | return pageData; |
| | | } |
| | | |
| | | @Override |
| | | public ShopWebDetailVO getShopWebDetail(ShopDetailQueryDTO dto) { |
| | | ShopInfo shop = shopInfoMapper.selectById(dto.getId()); |
| | | if (Objects.isNull(shop) || Constants.equalsInteger(shop.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | |
| | | ShopWebDetailVO vo = new ShopWebDetailVO(); |
| | | vo.setId(shop.getId()); |
| | | vo.setName(shop.getName()); |
| | | vo.setAddress(shop.getAddress()); |
| | | vo.setContent(shop.getContent()); |
| | | |
| | | // 门头照 + 内部照 全路径集合 |
| | | String imgPrefix = getShopPrefix(); |
| | | List<String> images = new ArrayList<>(); |
| | | images.addAll(getImageList(dto.getId(), Constants.FileType.STORE_FRONT.getKey(), imgPrefix)); |
| | | images.addAll(getImageList(dto.getId(), Constants.FileType.STORE_INTERIOR.getKey(), imgPrefix)); |
| | | vo.setImages(images); |
| | | |
| | | // 距离 |
| | | if (dto.getLongitude() != null && dto.getLatitude() != null && shop.getLongitude() != null && shop.getLatitude() != null) { |
| | | double distKm = haversine(dto.getLatitude(), dto.getLongitude(), shop.getLatitude(), shop.getLongitude()); |
| | | vo.setDistanceText(formatDistance(distKm)); |
| | | } |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | | public void maintainShopInfo(Integer memberId, ShopInfoMaintainDTO dto) { |
| | | // 门店主键与会员主键一致 |
| | | ShopInfo shop = shopInfoMapper.selectById(memberId); |
| | | if (Objects.isNull(shop) || Constants.equalsInteger(shop.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | // 需要支付完押金后才可维护(auditStatus >= 2) |
| | | if (shop.getAuditStatus() == null || shop.getAuditStatus() < Constants.TWO) { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "请先完成押金支付后再维护门店信息"); |
| | | } |
| | | UpdateWrapper<ShopInfo> updateWrapper = new UpdateWrapper<>(); |
| | | updateWrapper.lambda() |
| | | .eq(ShopInfo::getId, shop.getId()) |
| | | .set(ShopInfo::getUpdateTime, new Date()) |
| | | .set(dto.getCoverImg() != null, ShopInfo::getCoverImg, dto.getCoverImg()) |
| | | .set(dto.getContent() != null, ShopInfo::getContent, dto.getContent()) |
| | | .set(dto.getDepositTypes() != null, ShopInfo::getDepositTypes, dto.getDepositTypes()) |
| | | .set(dto.getFeeStandard() != null, ShopInfo::getFeeStandard, dto.getFeeStandard()) |
| | | .set(dto.getDeliveryArea() != null, ShopInfo::getDeliveryArea, dto.getDeliveryArea()) |
| | | .set(dto.getShopHours() != null, ShopInfo::getShopHours, dto.getShopHours()) |
| | | .set(dto.getBusinessType() != null, ShopInfo::getBusinessType, dto.getBusinessType()); |
| | | shopInfoMapper.update(updateWrapper); |
| | | } |
| | | |
| | | @Override |
| | | public ShopInfoMaintainDTO getShopMaintainInfo(Integer memberId) { |
| | | ShopInfo shop = shopInfoMapper.selectById(memberId); |
| | | if (Objects.isNull(shop) || Constants.equalsInteger(shop.getDeleted(), Constants.ONE)) { |
| | | return null; |
| | | } |
| | | ShopInfoMaintainDTO dto = new ShopInfoMaintainDTO(); |
| | | dto.setCoverImg(shop.getCoverImg()); |
| | | dto.setContent(shop.getContent()); |
| | | dto.setDepositTypes(shop.getDepositTypes()); |
| | | dto.setFeeStandard(shop.getFeeStandard()); |
| | | dto.setDeliveryArea(shop.getDeliveryArea()); |
| | | dto.setShopHours(shop.getShopHours()); |
| | | dto.setBusinessType(shop.getBusinessType()); |
| | | return dto; |
| | | } |
| | | |
| | | /** |
| | | * Haversine公式计算两点间距离(km) |
| | | */ |
| | | private double haversine(double lat1, double lng1, double lat2, double lng2) { |
| | | double R = 6371; |
| | | double dLat = Math.toRadians(lat2 - lat1); |
| | | double dLng = Math.toRadians(lng2 - lng1); |
| | | double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) |
| | | + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) |
| | | * Math.sin(dLng / 2) * Math.sin(dLng / 2); |
| | | double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); |
| | | return R * c; |
| | | } |
| | | |
| | | /** |
| | | * 格式化距离:小于1km显示米,大于等于1km显示千米(保留1位小数) |
| | | */ |
| | | private String formatDistance(double km) { |
| | | if (km < 1) { |
| | | return Math.round(km * 1000) + "m"; |
| | | } |
| | | return String.format("%.1fkm", km); |
| | | } |
| | | |
| | | /** |
| | | * 获取门店图片前缀 |
| | | */ |
| | | private String getShopPrefix() { |
| | | try { |
| | | return systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.RESOURCE_PATH).getCode() |
| | | + systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.SHOP_FILES).getCode(); |
| | | } catch (Exception e) { |
| | | return ""; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取门店指定类型的第一张图片全路径 |
| | | */ |
| | | private String getFirstImage(Integer shopId, int objType, String imgPrefix) { |
| | | QueryWrapper<Multifile> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(Multifile::getObjId, shopId) |
| | | .eq(Multifile::getObjType, objType) |
| | | .eq(Multifile::getIsdeleted, Constants.ZERO) |
| | | .orderByAsc(Multifile::getSortnum) |
| | | .last("limit 1"); |
| | | Multifile f = multifileMapper.selectOne(qw); |
| | | return f != null && StringUtils.isNotBlank(f.getFileurl()) ? imgPrefix + f.getFileurl() : null; |
| | | } |
| | | |
| | | /** |
| | | * 获取门店指定类型的所有图片全路径 |
| | | */ |
| | | private List<String> getImageList(Integer shopId, int objType, String imgPrefix) { |
| | | QueryWrapper<Multifile> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(Multifile::getObjId, shopId) |
| | | .eq(Multifile::getObjType, objType) |
| | | .eq(Multifile::getIsdeleted, Constants.ZERO) |
| | | .orderByAsc(Multifile::getSortnum); |
| | | List<Multifile> files = multifileMapper.selectList(qw); |
| | | List<String> urls = new ArrayList<>(); |
| | | for (Multifile f : files) { |
| | | if (StringUtils.isNotBlank(f.getFileurl())) { |
| | | urls.add(imgPrefix + f.getFileurl()); |
| | | } |
| | | } |
| | | return urls; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 商户账号密码登录 |
| | | * @param dto |
| | | * @return |
| | | */ |
| | | @Override |
| | | public ShopLoginVO shopPasswordLogin(ShopLoginDTO dto){ |
| | | if(StringUtils.isBlank(dto.getTelephone()) |
| | | || StringUtils.isBlank(dto.getPassword()) |
| | | || StringUtils.isBlank(dto.getOpenid()) |
| | | ){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"用户名或密码不能为空"); |
| | | } |
| | | ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda().eq(ShopInfo::getTelephone, dto.getTelephone()) |
| | | .eq(ShopInfo::getDeleted,Constants.ZERO) |
| | | .last("limit 1") |
| | | ); |
| | | if(shop==null){ |
| | | throw new BusinessException(ResponseStatus.ACCOUNT_INCORRECT); |
| | | } |
| | | //加密密码 |
| | | String pwd = Utils.Secure.encryptPassword( dto.getPassword(), shop.getSalt()); |
| | | if(!pwd.equals(shop.getPassword())){ |
| | | throw new BusinessException(ResponseStatus.ACCOUNT_INCORRECT); |
| | | } |
| | | |
| | | // 更新当前登录会员的openid到门店 |
| | | if(StringUtils.isNotBlank(dto.getOpenid())){ |
| | | shopInfoMapper.update(null,new UpdateWrapper<ShopInfo>().lambda() |
| | | .set(ShopInfo::getOpenid,dto.getOpenid()) |
| | | .eq(ShopInfo::getId,shop.getId()) |
| | | ); |
| | | // 清空其他门店的同一openid,保证唯一 |
| | | shopInfoMapper.update(null,new UpdateWrapper<ShopInfo>().lambda() |
| | | .set(ShopInfo::getOpenid,null) |
| | | .eq(ShopInfo::getOpenid,dto.getOpenid()) |
| | | .ne(ShopInfo::getId,shop.getId()) |
| | | ); |
| | | shop.setOpenid(dto.getOpenid()); |
| | | } |
| | | |
| | | // 创建token(generateTokenForRedis 已自动清除该用户旧token,保证唯一有效) |
| | | String token = JwtTokenUtil.generateTokenForRedis(shop.getId(), Constants.TWO, JSONObject.toJSONString(shop), redisTemplate); |
| | | |
| | | // 构建响应 |
| | | ShopLoginVO vo = new ShopLoginVO(); |
| | | vo.setToken(token); |
| | | vo.setShopId(shop.getId()); |
| | | vo.setShopName(shop.getName()); |
| | | vo.setCompanyType(shop.getCompanyType()); |
| | | |
| | | // 所属城市名称 |
| | | Areas area = areasBiz.resolveArea(shop.getAreaId()); |
| | | if (area != null) { |
| | | vo.setCityName(area.getCityName()); |
| | | } |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | | public ShopLoginVO shopSilentLogin(String openid) { |
| | | if (StringUtils.isBlank(openid)) { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "openid不能为空"); |
| | | } |
| | | ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda() |
| | | .eq(ShopInfo::getOpenid, openid) |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | if (shop == null) { |
| | | return null; |
| | | } |
| | | |
| | | // 创建token(generateTokenForRedis 已自动清除该用户旧token,保证唯一有效) |
| | | String token = JwtTokenUtil.generateTokenForRedis(shop.getId(), Constants.TWO, JSONObject.toJSONString(shop), redisTemplate); |
| | | |
| | | ShopLoginVO vo = new ShopLoginVO(); |
| | | vo.setToken(token); |
| | | vo.setShopId(shop.getId()); |
| | | vo.setShopName(shop.getName()); |
| | | vo.setCompanyType(shop.getCompanyType()); |
| | | |
| | | Areas area = areasBiz.resolveArea(shop.getAreaId()); |
| | | if (area != null) { |
| | | vo.setCityName(area.getCityName()); |
| | | } |
| | | return vo; |
| | | } |
| | | |
| | | } |
| | |
| | | package com.doumee.service.business.impl; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.aliyuncs.CommonResponse; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | |
| | | import com.doumee.core.exception.BusinessException; |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.core.utils.DateUtil; |
| | | import com.doumee.core.utils.Strings; |
| | | import com.doumee.core.utils.Utils; |
| | | import com.doumee.core.utils.aliyun.ALiYunSmSUtil; |
| | | import com.doumee.dao.business.SmsrecordMapper; |
| | | import com.doumee.dao.business.model.Smsrecord; |
| | | import com.doumee.service.business.SmsrecordService; |
| | |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * 短信验证码Service实现 |
| | |
| | | return smsrecordMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | |
| | | /****************************************移动端接口开始********************************************************************/ |
| | | |
| | | |
| | | /** |
| | | * 发送短信 目前只有短信验证码 |
| | | * @param memberId |
| | | * @param phone |
| | | */ |
| | | @Override |
| | | public void sendSms(Integer memberId,String phone){ |
| | | smsrecordMapper.update(null, |
| | | new UpdateWrapper<Smsrecord>() |
| | | .set("STATUS",2) |
| | | .eq("PHONE",phone) |
| | | .eq("STATUS",0) |
| | | ); |
| | | String digits = Strings.randomNumeric(4); |
| | | //发送验证码 |
| | | Map<String,Object> map = new HashMap<String,Object>(); |
| | | map.put("code",digits); |
| | | CommonResponse response = ALiYunSmSUtil.sendMessage(phone,map); |
| | | if(response.getHttpResponse().isSuccess()){ |
| | | JSONObject data = JSONObject.parseObject(response.getData()); |
| | | String returnCode = data.getString("Code"); |
| | | if(!returnCode.equals("OK")){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"短信发送失败:" + data.getString("Message")); |
| | | } |
| | | } |
| | | //存储短信验证码 |
| | | Smsrecord smsrecord = new Smsrecord(); |
| | | smsrecord.setCreateTime(new Date()); |
| | | smsrecord.setMemberId(memberId); |
| | | smsrecord.setPhone(phone); |
| | | smsrecord.setContent("验证码短信"); |
| | | smsrecord.setType(Constants.ZERO); |
| | | smsrecord.setValidDate(DateUtil.afterMinutesDate(3)); |
| | | smsrecord.setCode(digits); |
| | | smsrecord.setStatus(Constants.ZERO); |
| | | smsrecord.setDeleted(Constants.ZERO); |
| | | smsrecordMapper.insert(smsrecord); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 验证码验证 |
| | | * @param memberId |
| | | * @param phone |
| | | * @param code |
| | | */ |
| | | @Override |
| | | public void verifyCode(Integer memberId,String phone,String code){ |
| | | Smsrecord smsrecord = smsrecordMapper.selectOne(new QueryWrapper<Smsrecord>() |
| | | .eq("MEMBER_ID",memberId) |
| | | .eq("PHONE",phone) |
| | | .eq("CODE",code) |
| | | .eq("TYPE",Constants.ZERO) |
| | | .eq("STATUS",Constants.ZERO) |
| | | .last(" limit 1 ") |
| | | ); |
| | | if(Objects.isNull(smsrecord)){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"验证码输入错误或已过期!"); |
| | | } |
| | | if(smsrecord.getValidDate().getTime()<System.currentTimeMillis()){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"验证码已过期请重新获取!"); |
| | | } |
| | | smsrecord.setStatus(Constants.ONE); |
| | | smsrecord.setUpdateTime(new Date()); |
| | | smsrecordMapper.updateById(smsrecord); |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.core.utils.Utils; |
| | | import com.doumee.dao.business.DriverInfoMapper; |
| | | import com.doumee.dao.business.ShopInfoMapper; |
| | | import com.doumee.dao.business.WithdrawalOrdersMapper; |
| | | import com.doumee.dao.business.model.DriverInfo; |
| | | import com.doumee.dao.business.model.ShopInfo; |
| | | import com.doumee.dao.business.model.WithdrawalOrders; |
| | | import com.doumee.dao.dto.WithdrawalApproveDTO; |
| | | import com.doumee.dao.system.SystemUserMapper; |
| | | import com.doumee.dao.system.model.SystemUser; |
| | | import com.doumee.service.business.WithdrawalOrdersService; |
| | | import com.github.yulichang.wrapper.MPJLambdaWrapper; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | |
| | | |
| | | @Autowired |
| | | private WithdrawalOrdersMapper withdrawalOrdersMapper; |
| | | |
| | | @Autowired |
| | | private SystemUserMapper systemUserMapper; |
| | | |
| | | @Autowired |
| | | private ShopInfoMapper shopInfoMapper; |
| | | |
| | | @Autowired |
| | | private DriverInfoMapper driverInfoMapper; |
| | | |
| | | @Override |
| | | public Integer create(WithdrawalOrders withdrawalOrders) { |
| | |
| | | |
| | | @Override |
| | | public WithdrawalOrders findById(Integer id) { |
| | | WithdrawalOrders withdrawalOrders = withdrawalOrdersMapper.selectById(id); |
| | | if (Objects.isNull(withdrawalOrders)) { |
| | | WithdrawalOrders order = withdrawalOrdersMapper.selectById(id); |
| | | if (Objects.isNull(order)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | return withdrawalOrders; |
| | | // 查询审批人名称 |
| | | fillUpdateUserName(order); |
| | | // 根据用户类型查询关联信息 |
| | | if (Constants.ONE.equals(order.getMemberType())) { |
| | | fillMemberInfo(order); |
| | | } else { |
| | | fillShopInfo(order); |
| | | } |
| | | return order; |
| | | } |
| | | |
| | | @Override |
| | |
| | | @Override |
| | | public PageData<WithdrawalOrders> findPage(PageWrap<WithdrawalOrders> pageWrap) { |
| | | IPage<WithdrawalOrders> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); |
| | | QueryWrapper<WithdrawalOrders> queryWrapper = new QueryWrapper<>(); |
| | | MPJLambdaWrapper<WithdrawalOrders> queryWrapper = new MPJLambdaWrapper<>(); |
| | | Utils.MP.blankToNull(pageWrap.getModel()); |
| | | pageWrap.getModel().setDeleted(Constants.ZERO); |
| | | queryWrapper.lambda().eq(WithdrawalOrders::getDeleted, pageWrap.getModel().getDeleted()); |
| | | queryWrapper.lambda().like(StringUtils.isNotBlank(pageWrap.getModel().getOutBillNo()), WithdrawalOrders::getOutBillNo, pageWrap.getModel().getOutBillNo()); |
| | | queryWrapper.lambda().eq(pageWrap.getModel().getMemberId() != null, WithdrawalOrders::getMemberId, pageWrap.getModel().getMemberId()); |
| | | queryWrapper.lambda().eq(pageWrap.getModel().getStatus() != null, WithdrawalOrders::getStatus, pageWrap.getModel().getStatus()); |
| | | queryWrapper.lambda().eq(pageWrap.getModel().getType() != null, WithdrawalOrders::getType, pageWrap.getModel().getType()); |
| | | queryWrapper.lambda().ge(pageWrap.getModel().getCreateStartTime() != null, WithdrawalOrders::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateStartTime())); |
| | | queryWrapper.lambda().le(pageWrap.getModel().getCreateEndTime() != null, WithdrawalOrders::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateEndTime())); |
| | | |
| | | // 公共:审批人名称 |
| | | queryWrapper.selectAll(WithdrawalOrders.class) |
| | | .selectAs(SystemUser::getUsername, WithdrawalOrders::getUpdateUserName) |
| | | .leftJoin(SystemUser.class, SystemUser::getId, WithdrawalOrders::getUserId); |
| | | |
| | | // 根据用户类型关联不同表 |
| | | Integer memberType = pageWrap.getModel().getMemberType(); |
| | | if (Constants.ONE.equals(memberType)) { |
| | | // 司机端:关联 DriverInfo 表 |
| | | queryWrapper.selectAs(DriverInfo::getName, WithdrawalOrders::getMemberName) |
| | | .selectAs(DriverInfo::getTelephone, WithdrawalOrders::getMemberTelephone) |
| | | .leftJoin(DriverInfo.class, DriverInfo::getMemberId, WithdrawalOrders::getMemberId); |
| | | } else { |
| | | // 店铺端 / 不筛选:关联 ShopInfo 表 |
| | | queryWrapper.selectAs(ShopInfo::getName, WithdrawalOrders::getShopName) |
| | | .selectAs(ShopInfo::getLinkName, WithdrawalOrders::getLinkName) |
| | | .leftJoin(ShopInfo.class, ShopInfo::getId, WithdrawalOrders::getMemberId, |
| | | ext -> ext.eq(ShopInfo::getDeleted, Constants.ZERO)); |
| | | } |
| | | |
| | | queryWrapper.eq(WithdrawalOrders::getDeleted, pageWrap.getModel().getDeleted()); |
| | | if (memberType != null) { |
| | | queryWrapper.eq(WithdrawalOrders::getMemberType, memberType); |
| | | } |
| | | if (StringUtils.isNotBlank(pageWrap.getModel().getOutBillNo())) { |
| | | queryWrapper.like(WithdrawalOrders::getOutBillNo, pageWrap.getModel().getOutBillNo()); |
| | | } |
| | | if (pageWrap.getModel().getMemberId() != null) { |
| | | queryWrapper.eq(WithdrawalOrders::getMemberId, pageWrap.getModel().getMemberId()); |
| | | } |
| | | if (pageWrap.getModel().getStatus() != null) { |
| | | queryWrapper.eq(WithdrawalOrders::getStatus, pageWrap.getModel().getStatus()); |
| | | } |
| | | if (pageWrap.getModel().getType() != null) { |
| | | queryWrapper.eq(WithdrawalOrders::getType, pageWrap.getModel().getType()); |
| | | } |
| | | if (pageWrap.getModel().getCreateStartTime() != null) { |
| | | queryWrapper.ge(WithdrawalOrders::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateStartTime())); |
| | | } |
| | | if (pageWrap.getModel().getCreateEndTime() != null) { |
| | | queryWrapper.le(WithdrawalOrders::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateEndTime())); |
| | | } |
| | | for (PageWrap.SortData sortData : pageWrap.getSorts()) { |
| | | if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) { |
| | | queryWrapper.orderByDesc(sortData.getProperty()); |
| | |
| | | queryWrapper.orderByAsc(sortData.getProperty()); |
| | | } |
| | | } |
| | | return PageData.from(withdrawalOrdersMapper.selectPage(page, queryWrapper)); |
| | | return PageData.from(withdrawalOrdersMapper.selectJoinPage(page, WithdrawalOrders.class, queryWrapper)); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | @Override |
| | | public long count(WithdrawalOrders withdrawalOrders) { |
| | |
| | | return withdrawalOrdersMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | @Override |
| | | public Long totalAmount(PageWrap<WithdrawalOrders> pageWrap) { |
| | | QueryWrapper<WithdrawalOrders> queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.select("IFNULL(SUM(amount), 0) as amount"); |
| | | Utils.MP.blankToNull(pageWrap.getModel()); |
| | | queryWrapper.lambda().eq(WithdrawalOrders::getDeleted, Constants.ZERO); |
| | | queryWrapper.lambda().in(WithdrawalOrders::getStatus, Arrays.asList(Constants.ZERO, Constants.ONE)); |
| | | if (pageWrap.getModel().getOutBillNo() != null) { |
| | | queryWrapper.lambda().like(WithdrawalOrders::getOutBillNo, pageWrap.getModel().getOutBillNo()); |
| | | } |
| | | if (pageWrap.getModel().getMemberId() != null) { |
| | | queryWrapper.lambda().eq(WithdrawalOrders::getMemberId, pageWrap.getModel().getMemberId()); |
| | | } |
| | | if (pageWrap.getModel().getStatus() != null) { |
| | | queryWrapper.lambda().eq(WithdrawalOrders::getStatus, pageWrap.getModel().getStatus()); |
| | | } |
| | | if (pageWrap.getModel().getType() != null) { |
| | | queryWrapper.lambda().eq(WithdrawalOrders::getType, pageWrap.getModel().getType()); |
| | | } |
| | | if (pageWrap.getModel().getCreateStartTime() != null) { |
| | | queryWrapper.lambda().ge(WithdrawalOrders::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateStartTime())); |
| | | } |
| | | if (pageWrap.getModel().getCreateEndTime() != null) { |
| | | queryWrapper.lambda().le(WithdrawalOrders::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateEndTime())); |
| | | } |
| | | WithdrawalOrders result = withdrawalOrdersMapper.selectOne(queryWrapper); |
| | | return result != null && result.getAmount() != null ? result.getAmount() : 0L; |
| | | } |
| | | |
| | | @Override |
| | | public void approve(WithdrawalApproveDTO dto) { |
| | | if (dto == null || dto.getId() == null || dto.getStatus() == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "审批参数不完整"); |
| | | } |
| | | if (!Constants.ONE.equals(dto.getStatus()) && !Constants.TWO.equals(dto.getStatus())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "审批结果仅支持通过或拒绝"); |
| | | } |
| | | |
| | | WithdrawalOrders order = withdrawalOrdersMapper.selectById(dto.getId()); |
| | | if (Objects.isNull(order)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | if (!Constants.ZERO.equals(order.getStatus())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅申请中的提现订单可审批"); |
| | | } |
| | | |
| | | // 获取当前登录用户 |
| | | Integer currentUserId = getCurrentUserId(); |
| | | |
| | | WithdrawalOrders update = new WithdrawalOrders(); |
| | | update.setId(dto.getId()); |
| | | update.setStatus(dto.getStatus()); |
| | | update.setUserId(currentUserId); |
| | | update.setApproveTime(new Date()); |
| | | update.setApproveRemark(dto.getApproveRemark()); |
| | | update.setUpdateTime(new Date()); |
| | | withdrawalOrdersMapper.updateById(update); |
| | | } |
| | | |
| | | private Integer getCurrentUserId() { |
| | | com.doumee.core.model.LoginUserInfo user = |
| | | (com.doumee.core.model.LoginUserInfo) org.apache.shiro.SecurityUtils.getSubject().getPrincipal(); |
| | | return user != null ? user.getId() : null; |
| | | } |
| | | |
| | | private void fillUpdateUserName(WithdrawalOrders order) { |
| | | if (order.getUserId() != null) { |
| | | SystemUser user = systemUserMapper.selectById(order.getUserId()); |
| | | if (user != null) { |
| | | order.setUpdateUserName(user.getUsername()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void fillShopInfo(WithdrawalOrders order) { |
| | | if (order.getMemberId() != null) { |
| | | ShopInfo shop = shopInfoMapper.selectById(order.getMemberId()); |
| | | if (shop != null && !Constants.ONE.equals(shop.getDeleted())) { |
| | | order.setShopInfo(shop); |
| | | order.setShopName(shop.getName()); |
| | | order.setLinkName(shop.getLinkName()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void fillMemberInfo(WithdrawalOrders order) { |
| | | if (order.getMemberId() != null) { |
| | | DriverInfo driver = driverInfoMapper.selectOne( |
| | | new QueryWrapper<DriverInfo>().lambda() |
| | | .eq(DriverInfo::getMemberId, order.getMemberId()) |
| | | .eq(DriverInfo::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | if (driver != null) { |
| | | order.setMemberName(driver.getName()); |
| | | order.setMemberTelephone(driver.getTelephone()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | upload: |
| | | type: ftp |
| | | |
| | | # 腾讯地图apikey |
| | | tencent_key: WE3BZ-HN6WS-ONDOH-62QCV-MNL6F-5NFNE |
| | | |
| | | |
| | | |
| | |
| | | type: blob |
| | | |
| | | qiwei: |
| | | serviceurl: https://wecom-qyapi.unilever-china.com/ |
| | | serviceurl: https://wecom-qyapi.unilever-china.com/ |
| | | |
| | | |
| | | |
| | | # 腾讯地图apikey |
| | | tencent_key: WE3BZ-HN6WS-ONDOH-62QCV-MNL6F-5NFNE |
| | |
| | | type: blob |
| | | |
| | | qiwei: |
| | | serviceurl: https://qyapi.weixin.qq.com |
| | | serviceurl: https://qyapi.weixin.qq.com |
| | | |
| | | |
| | | # 腾讯地图apikey |
| | | tencent_key: WE3BZ-HN6WS-ONDOH-62QCV-MNL6F-5NFNE |
| | |
| | | import com.doumee.core.annotation.trace.Trace; |
| | | import com.doumee.core.model.ApiResponse; |
| | | import com.doumee.dao.business.model.Member; |
| | | import com.doumee.dao.dto.ShopLoginDTO; |
| | | import com.doumee.dao.dto.WxPhoneRequest; |
| | | import com.doumee.dao.vo.AccountResponse; |
| | | import com.doumee.dao.vo.ShopLoginVO; |
| | | import com.doumee.service.business.MemberService; |
| | | import com.doumee.service.business.ShopInfoService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | /** |
| | |
| | | @Autowired |
| | | private MemberService memberService; |
| | | |
| | | @Autowired |
| | | private ShopInfoService shopInfoService; |
| | | |
| | | |
| | | @Trace |
| | | @ApiOperation(value = "微信授权", notes = "小程序端") |
| | | @ApiOperation(value = "会员微信授权", notes = "小程序端") |
| | | @GetMapping("/wxLogin") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "query", dataType = "String", name = "code", value = "微信code", required = true) |
| | |
| | | } |
| | | |
| | | |
| | | @ApiOperation(value = "授权手机号", notes = "小程序端") |
| | | @ApiOperation(value = "会员授权手机号", notes = "小程序端") |
| | | @PostMapping("/wxAuthPhone") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "query", dataType = "String", name = "code", value = "微信code", required = true) |
| | |
| | | return ApiResponse.success("操作成功",memberService.wxAuthPhone(wxPhoneRequest)); |
| | | } |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "退出登录", notes = "小程序端") |
| | | @GetMapping("/logOff") |
| | | @ApiOperation(value = "门店账号密码登录", notes = "小程序端,门店用户通过手机号+密码登录") |
| | | @PostMapping("/shopLogin") |
| | | public ApiResponse<ShopLoginVO> shopLogin(@RequestBody @Validated ShopLoginDTO dto) { |
| | | return ApiResponse.success("操作成功", shopInfoService.shopPasswordLogin(dto)); |
| | | } |
| | | |
| | | @ApiOperation(value = "门店静默登录", notes = "根据openid自动登录门店,未绑定则返回空") |
| | | @GetMapping("/shopSilentLogin") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true), |
| | | @ApiImplicitParam(paramType = "query", dataType = "String", name = "openid", value = "微信openid", required = true) |
| | | }) |
| | | public ApiResponse logOff() { |
| | | String token = this.getRequest().getHeader(JwtTokenUtil.HEADER_KEY); |
| | | memberService.logOut(token,getMemberId()); |
| | | return ApiResponse.success("操作成功"); |
| | | public ApiResponse<ShopLoginVO> shopSilentLogin(@RequestParam String openid) { |
| | | return ApiResponse.success("操作成功", shopInfoService.shopSilentLogin(openid)); |
| | | } |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "用户注销", notes = "小程序端") |
| | | @ApiOperation(value = "退出登录", notes = "小程序端") |
| | | @GetMapping("/logOut") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true), |
| | |
| | | return ApiResponse.success("操作成功"); |
| | | } |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "用户注销", notes = "小程序端") |
| | | @GetMapping("/logOff") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true), |
| | | }) |
| | | public ApiResponse logOff() { |
| | | String token = this.getRequest().getHeader(JwtTokenUtil.HEADER_KEY); |
| | | memberService.logOff(token,getMemberId()); |
| | | return ApiResponse.success("操作成功"); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true), |
| | | }) |
| | | public ApiResponse<List<Addr>> list() { |
| | | Addr query = new Addr(); |
| | | query.setMemberId(getMemberId()); |
| | | query.setDeleted(0); |
| | | return ApiResponse.success("查询成功", addrService.findList(query)); |
| | | return ApiResponse.success("查询成功", addrService.findListWithArea(getMemberId())); |
| | | } |
| | | |
| | | @LoginRequired |
| | |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true), |
| | | }) |
| | | public ApiResponse<Addr> findById(@PathVariable Integer id) { |
| | | return ApiResponse.success("查询成功", addrService.findById(id)); |
| | | return ApiResponse.success("查询成功", addrService.findByIdWithArea(id)); |
| | | } |
| | | |
| | | @LoginRequired |
| | |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true), |
| | | }) |
| | | public ApiResponse create(@RequestBody Addr addr) { |
| | | addr.setMemberId(getMemberId()); |
| | | addrService.create(addr); |
| | | return ApiResponse.success("操作成功"); |
| | | addrService.createByMember(addr, getMemberId()); |
| | | return ApiResponse.success("操作成功", addrService.findByIdWithArea(addr.getId())); |
| | | } |
| | | |
| | | @LoginRequired |
| | |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true), |
| | | }) |
| | | public ApiResponse updateById(@RequestBody Addr addr) { |
| | | addr.setMemberId(getMemberId()); |
| | | addrService.updateById(addr); |
| | | return ApiResponse.success("操作成功"); |
| | | addrService.updateByMember(addr, getMemberId()); |
| | | return ApiResponse.success("操作成功", addrService.findByIdWithArea(addr.getId())); |
| | | } |
| | | |
| | | @LoginRequired |
| | |
| | | Addr addr = new Addr(); |
| | | addr.setId(id); |
| | | addr.setIsDefault(1); |
| | | addrService.updateById(addr); |
| | | addrService.updateByMember(addr, getMemberId()); |
| | | return ApiResponse.success("操作成功"); |
| | | } |
| | | } |
| | |
| | | return obj != null ? (Integer) obj : null; |
| | | } |
| | | |
| | | protected Integer getShopId() { |
| | | Object obj = this.getRequest().getAttribute(JwtTokenUtil.SHOP_ID); |
| | | return obj != null ? (Integer) obj : null; |
| | | } |
| | | |
| | | /** |
| | | * 获取登录用户对象信息 |
| | | * @return |
| | |
| | | import com.doumee.core.annotation.LoginRequired; |
| | | import com.doumee.core.annotation.trace.Trace; |
| | | import com.doumee.core.model.ApiResponse; |
| | | import com.doumee.dao.business.model.Areas; |
| | | import com.doumee.dao.business.model.Banner; |
| | | import com.doumee.dao.business.model.Category; |
| | | import com.doumee.dao.dto.CalculateLocalPriceDTO; |
| | | import com.doumee.dao.dto.CalculateRemotePriceDTO; |
| | | import com.doumee.dao.vo.AccountResponse; |
| | | import com.doumee.service.business.CategoryService; |
| | | import com.doumee.dao.vo.PriceCalculateVO; |
| | | import com.doumee.dao.vo.UserCenterVO; |
| | | import com.doumee.service.business.*; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.checkerframework.checker.units.qual.A; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.validation.Valid; |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @Api(tags = "配置类接口") |
| | | @Trace(exclude = true) |
| | | @RestController |
| | | @RequestMapping("/web/orders") |
| | | @RequestMapping("/web/config") |
| | | @Slf4j |
| | | public class ConfigApi extends ApiController{ |
| | | |
| | | @Autowired |
| | | private CategoryService categoryService; |
| | | |
| | | @Autowired |
| | | private AreasService areasService; |
| | | |
| | | @Autowired |
| | | private BannerService bannerService; |
| | | |
| | | @Autowired |
| | | private OrdersService ordersService; |
| | | |
| | | @Autowired |
| | | private MemberService memberService; |
| | | |
| | | @ApiOperation(value = "获取分类列表", notes = "小程序端") |
| | | @GetMapping("/getCategoryList") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "type", value = "类型:0=品种配置;1=车辆类型配置;2=餐标配置;3=手续费配置;", required = true) |
| | | @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "type", value = "类型:1=车辆类型;2=物品分类;3=物品等级;4=物品尺寸;", required = true) |
| | | }) |
| | | public ApiResponse<List<Category>> getCategoryList(@RequestParam Integer type) { |
| | | return ApiResponse.success("操作成功",categoryService.getCategoryList(type)); |
| | | } |
| | | |
| | | @ApiOperation(value = "获取开放城市列表", notes = "返回已开放城市,含首字母,按首字母排序") |
| | | @GetMapping("/getOpenCityList") |
| | | public ApiResponse<List<Areas>> getOpenCityList() { |
| | | return ApiResponse.success("操作成功", areasService.getOpenCityList()); |
| | | } |
| | | |
| | | @ApiOperation(value = "获取轮播图列表", notes = "根据位置返回轮播图,含图片全路径") |
| | | @GetMapping("/getBannerList") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "position", value = "位置:0=会员端首页轮播;1=司机APP引导页;", required = true) |
| | | }) |
| | | public ApiResponse<List<Banner>> getBannerList(@RequestParam Integer position) { |
| | | return ApiResponse.success("操作成功", bannerService.findListByPosition(position)); |
| | | } |
| | | |
| | | @ApiOperation(value = "获取城市已开通物品尺寸", notes = "根据城市主键查询已开通的物品尺寸(category type=4)") |
| | | @GetMapping("/getCitySizeList") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "cityId", value = "城市主键", required = true) |
| | | }) |
| | | public ApiResponse<List<Category>> getCitySizeList(@RequestParam Integer cityId) { |
| | | return ApiResponse.success("操作成功", categoryService.getCitySizeList(cityId)); |
| | | } |
| | | |
| | | |
| | | @ApiOperation(value = "获取系统配置", notes = "小程序端") |
| | | @GetMapping("/getPlatformAboutUs") |
| | | public ApiResponse<UserCenterVO> getPlatformAboutUs() { |
| | | return ApiResponse.success("查询成功",memberService.getPlatformAboutUs()); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "计算保价费用", notes = "根据报价金额计算保价费用") |
| | | @GetMapping("/calculateInsuranceFee") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "query", dataType = "BigDecimal", name = "declaredValue", value = "报价金额", required = true), |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true) |
| | | }) |
| | | public ApiResponse<BigDecimal> calculateInsuranceFee(@RequestParam BigDecimal declaredValue) { |
| | | return ApiResponse.success("操作成功", ordersService.calculateInsuranceFee(declaredValue)); |
| | | } |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "计算就地存取预估费用", notes = "根据城市、天数、物品类型和数量计算就地存取预估费用") |
| | | @PostMapping("/calculateLocalPrice") |
| | | public ApiResponse<PriceCalculateVO> calculateLocalPrice(@RequestBody @Valid CalculateLocalPriceDTO dto) { |
| | | return ApiResponse.success("操作成功", ordersService.calculateLocalPrice(dto)); |
| | | } |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "计算异地存取预估费用", notes = "根据距离、物品类型和数量计算异地存取预估费用") |
| | | @PostMapping("/calculateRemotePrice") |
| | | public ApiResponse<PriceCalculateVO> calculateRemotePrice(@RequestBody @Valid CalculateRemotePriceDTO dto) { |
| | | return ApiResponse.success("操作成功", ordersService.calculateRemotePrice(dto)); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | import com.doumee.core.annotation.LoginRequired; |
| | | import com.doumee.core.annotation.trace.Trace; |
| | | import com.doumee.core.model.ApiResponse; |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.dao.business.model.IdentityInfo; |
| | | import com.doumee.dao.business.model.Member; |
| | | import com.doumee.dao.business.model.MemberRevenue; |
| | | import com.doumee.dao.dto.UpdMobileRequest; |
| | | import com.doumee.dao.dto.WithdrawalDTO; |
| | | import com.doumee.dao.dto.WxPhoneRequest; |
| | | import com.doumee.dao.vo.AccountResponse; |
| | | import com.doumee.dao.vo.UserCenterVO; |
| | | import com.doumee.service.business.IdentityInfoService; |
| | | import com.doumee.service.business.MemberService; |
| | | import com.doumee.service.business.SmsrecordService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.shiro.authz.annotation.RequiresPermissions; |
| | | import org.checkerframework.checker.units.qual.A; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | |
| | | @Api(tags = "2、用户信息") |
| | | @Trace(exclude = true) |
| | | @RestController |
| | | @RequestMapping("/web/user") |
| | | @RequestMapping("/web/member") |
| | | @Slf4j |
| | | public class UserApi extends ApiController{ |
| | | public class MemberApi extends ApiController{ |
| | | |
| | | |
| | | @Autowired |
| | | private MemberService memberService; |
| | | |
| | | // @Autowired |
| | | // private IdentityInfoService identityInfoService; |
| | | |
| | | // @Autowired |
| | | // private MemberRevenueService memberRevenueService; |
| | | // |
| | | // @Autowired |
| | | // private WithdrawalOrdersService withdrawalOrdersService; |
| | | |
| | | |
| | | @ApiOperation(value = "获取系统配置", notes = "小程序端") |
| | | @GetMapping("/getPlatformAboutUs") |
| | | public ApiResponse<UserCenterVO> getPlatformAboutUs() { |
| | | return ApiResponse.success("查询成功",memberService.getPlatformAboutUs()); |
| | | } |
| | | |
| | | @Autowired |
| | | private SmsrecordService smsrecordService; |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "获取个人信息", notes = "小程序端") |
| | |
| | | return ApiResponse.success("操作成功"); |
| | | } |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "发送短信验证码", notes = "小程序端") |
| | | @GetMapping("/sendSmsCode") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true), |
| | | @ApiImplicitParam(paramType = "query", dataType = "String", name = "phone", value = "手机号码", required = true) |
| | | }) |
| | | public ApiResponse sendSmsCode(@RequestParam String phone) { |
| | | smsrecordService.sendSms(getMemberId(),phone); |
| | | return ApiResponse.success("操作成功"); |
| | | } |
| | | |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "验证短信验证码", notes = "小程序端") |
| | | @GetMapping("/verifyCode") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true), |
| | | @ApiImplicitParam(paramType = "query", dataType = "String", name = "phone", value = "手机号码", required = true), |
| | | @ApiImplicitParam(paramType = "query", dataType = "String", name = "code", value = "验证码", required = true) |
| | | }) |
| | | public ApiResponse verifyCode(@RequestParam String phone,@RequestParam String code) { |
| | | smsrecordService.verifyCode(getMemberId(),phone,code); |
| | | return ApiResponse.success("操作成功"); |
| | | } |
| | | |
| | | |
| | | @LoginRequired |
| | | @ApiOperation("验证手机号") |
| | |
| | | package com.doumee.api.web; |
| | | |
| | | import com.doumee.core.annotation.LoginRequired; |
| | | import com.doumee.core.annotation.LoginShopRequired; |
| | | import com.doumee.core.annotation.trace.Trace; |
| | | import com.doumee.core.model.ApiResponse; |
| | | import com.doumee.dao.business.model.Areas; |
| | | import com.doumee.dao.business.model.Banner; |
| | | import com.doumee.dao.business.model.Category; |
| | | import com.doumee.dao.dto.CalculateLocalPriceDTO; |
| | | import com.doumee.dao.dto.CalculateRemotePriceDTO; |
| | | import com.doumee.dao.vo.AccountResponse; |
| | | import com.doumee.dao.vo.PriceCalculateVO; |
| | | import com.doumee.service.business.AreasService; |
| | | import com.doumee.service.business.BannerService; |
| | | import com.doumee.service.business.CategoryService; |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.dao.dto.CancelOrderDTO; |
| | | import com.doumee.dao.dto.CreateOrderDTO; |
| | | import com.doumee.dao.dto.DriverVerifyDTO; |
| | | import com.doumee.dao.dto.ShopVerifyDTO; |
| | | import com.doumee.dao.dto.MyOrderDTO; |
| | | import com.doumee.dao.vo.MyOrderDetailVO; |
| | | import com.doumee.dao.vo.MyOrderVO; |
| | | import com.doumee.dao.vo.OverdueFeeVO; |
| | | import com.doumee.dao.vo.PayResponse; |
| | | import com.doumee.service.business.OrdersService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.validation.Valid; |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * Created by IntelliJ IDEA. |
| | | * 订单接口 |
| | | * |
| | | * @Author : Rk |
| | | * @create 2025/7/15 15:49 |
| | | */ |
| | | @Api(tags = "配置类接口") |
| | | @Api(tags = "订单接口") |
| | | @Trace(exclude = true) |
| | | @RestController |
| | | @RequestMapping("/web/config") |
| | | @RequestMapping("/web/order") |
| | | @Slf4j |
| | | public class ConfigApi extends ApiController{ |
| | | |
| | | @Autowired |
| | | private CategoryService categoryService; |
| | | |
| | | @Autowired |
| | | private AreasService areasService; |
| | | |
| | | @Autowired |
| | | private BannerService bannerService; |
| | | public class OrdersApi extends ApiController { |
| | | |
| | | @Autowired |
| | | private OrdersService ordersService; |
| | | |
| | | @ApiOperation(value = "获取分类列表", notes = "小程序端") |
| | | @GetMapping("/getCategoryList") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "type", value = "类型:1=车辆类型;2=物品分类;3=物品等级;4=物品尺寸;", required = true) |
| | | }) |
| | | public ApiResponse<List<Category>> getCategoryList(@RequestParam Integer type) { |
| | | return ApiResponse.success("操作成功",categoryService.getCategoryList(type)); |
| | | } |
| | | @Autowired |
| | | private RedisTemplate<String, Object> redisTemplate; |
| | | |
| | | @ApiOperation(value = "获取开放城市列表", notes = "返回已开放城市,含首字母,按首字母排序") |
| | | @GetMapping("/getOpenCityList") |
| | | public ApiResponse<List<Areas>> getOpenCityList() { |
| | | return ApiResponse.success("操作成功", areasService.getOpenCityList()); |
| | | } |
| | | |
| | | @ApiOperation(value = "获取轮播图列表", notes = "根据位置返回轮播图,含图片全路径") |
| | | @GetMapping("/getBannerList") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "position", value = "位置:0=会员端首页轮播;1=司机APP引导页;", required = true) |
| | | }) |
| | | public ApiResponse<List<Banner>> getBannerList(@RequestParam Integer position) { |
| | | return ApiResponse.success("操作成功", bannerService.findListByPosition(position)); |
| | | } |
| | | |
| | | @ApiOperation(value = "获取城市已开通物品尺寸", notes = "根据城市主键查询已开通的物品尺寸(category type=4)") |
| | | @GetMapping("/getCitySizeList") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "cityId", value = "城市主键", required = true) |
| | | }) |
| | | public ApiResponse<List<Category>> getCitySizeList(@RequestParam Integer cityId) { |
| | | return ApiResponse.success("操作成功", categoryService.getCitySizeList(cityId)); |
| | | @LoginRequired |
| | | @ApiOperation(value = "创建订单", notes = "创建就地/异地寄存订单,返回微信支付参数") |
| | | @PostMapping("/create") |
| | | public ApiResponse<PayResponse> createOrder(@RequestBody @Valid CreateOrderDTO dto) { |
| | | PayResponse payResponse = ordersService.createOrder(dto, getMemberId()); |
| | | if (Objects.nonNull(payResponse) && StringUtils.isNotBlank(payResponse.getLockKey())) { |
| | | redisTemplate.delete(payResponse.getLockKey()); |
| | | } |
| | | return ApiResponse.success("操作成功", payResponse); |
| | | } |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "计算保价费用", notes = "根据报价金额计算保价费用") |
| | | @GetMapping("/calculateInsuranceFee") |
| | | @ApiOperation(value = "继续支付", notes = "待支付订单重新唤起微信支付") |
| | | @PostMapping("/continuePay/{orderId}") |
| | | public ApiResponse<PayResponse> continuePay(@PathVariable Integer orderId) { |
| | | return ApiResponse.success("操作成功", ordersService.continuePay(orderId, getMemberId())); |
| | | } |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "会员订单分页", notes = "小程序端,按状态筛选") |
| | | @PostMapping("/myPage") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "query", dataType = "BigDecimal", name = "declaredValue", value = "报价金额", required = true), |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true), |
| | | }) |
| | | public ApiResponse<PageData<MyOrderVO>> myPage(@RequestBody @Validated PageWrap<MyOrderDTO> pageWrap) { |
| | | return ApiResponse.success("查询成功", ordersService.findMyOrderPage(pageWrap, getMemberId())); |
| | | } |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "会员订单详情", notes = "小程序端,查询当前会员的订单详情") |
| | | @GetMapping("/detail/{orderId}") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "path", dataType = "Integer", name = "orderId", value = "订单主键", required = true), |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true) |
| | | }) |
| | | public ApiResponse<BigDecimal> calculateInsuranceFee(@RequestParam BigDecimal declaredValue) { |
| | | return ApiResponse.success("操作成功", ordersService.calculateInsuranceFee(declaredValue)); |
| | | public ApiResponse<MyOrderDetailVO> detail(@PathVariable Integer orderId) { |
| | | return ApiResponse.success("查询成功", ordersService.findMyOrderDetail(orderId, getMemberId())); |
| | | } |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "计算就地存取预估费用", notes = "根据城市、天数、物品类型和数量计算就地存取预估费用") |
| | | @PostMapping("/calculateLocalPrice") |
| | | public ApiResponse<PriceCalculateVO> calculateLocalPrice(@RequestBody @Valid CalculateLocalPriceDTO dto) { |
| | | return ApiResponse.success("操作成功", ordersService.calculateLocalPrice(dto)); |
| | | @ApiOperation(value = "会员取消订单", notes = "仅异地寄存订单可取消") |
| | | @PostMapping("/cancel") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true) |
| | | }) |
| | | public ApiResponse cancel(@RequestBody @Validated CancelOrderDTO dto) { |
| | | ordersService.cancelOrder(dto.getOrderId(), getMemberId(), dto.getCancelReason()); |
| | | return ApiResponse.success("操作成功"); |
| | | } |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "计算异地存取预估费用", notes = "根据距离、物品类型和数量计算异地存取预估费用") |
| | | @PostMapping("/calculateRemotePrice") |
| | | public ApiResponse<PriceCalculateVO> calculateRemotePrice(@RequestBody @Valid CalculateRemotePriceDTO dto) { |
| | | return ApiResponse.success("操作成功", ordersService.calculateRemotePrice(dto)); |
| | | @ApiOperation(value = "查询超时费用", notes = "查询订单逾期天数和逾期费用") |
| | | @GetMapping("/overdueFee/{orderId}") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "path", dataType = "Integer", name = "orderId", value = "订单主键", required = true), |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true) |
| | | }) |
| | | public ApiResponse<OverdueFeeVO> overdueFee(@PathVariable Integer orderId) { |
| | | return ApiResponse.success("查询成功", ordersService.calculateOverdueFee(orderId)); |
| | | } |
| | | |
| | | @LoginShopRequired |
| | | @ApiOperation(value = "门店核销收件", notes = "门店通过核销码确认收件/取件") |
| | | @PostMapping("/shopVerify") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "门店token值", required = true) |
| | | }) |
| | | public ApiResponse shopVerify(@RequestBody @Validated ShopVerifyDTO dto) { |
| | | ordersService.shopVerifyOrder(dto.getVerifyCode(), getShopId(), dto.getImages(), dto.getRemark()); |
| | | return ApiResponse.success("核销成功"); |
| | | } |
| | | |
| | | @LoginShopRequired |
| | | @ApiOperation(value = "核销司机码", notes = "异地寄存且有取件门店的订单,通过司机核销码确认到店") |
| | | @PostMapping("/driverVerify") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true) |
| | | }) |
| | | public ApiResponse driverVerify(@RequestBody @Validated DriverVerifyDTO dto) { |
| | | ordersService.driverVerifyOrder(dto.getVerifyCode(), dto.getImages(), dto.getRemark(), getShopId()); |
| | | return ApiResponse.success("核销成功"); |
| | | } |
| | | |
| | | @LoginShopRequired |
| | | @ApiOperation(value = "门店订单详情", notes = "门店端查询订单详情,支持订单主键或核销码查询") |
| | | @GetMapping("/shopDetail") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "门店token值", required = true), |
| | | @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "orderId", value = "订单主键"), |
| | | @ApiImplicitParam(paramType = "query", dataType = "String", name = "verifyCode", value = "核销码") |
| | | }) |
| | | public ApiResponse<MyOrderDetailVO> shopDetail(@RequestParam(required = false) Integer orderId, |
| | | @RequestParam(required = false) String verifyCode) { |
| | | return ApiResponse.success("查询成功", ordersService.findShopOrderDetail(orderId, verifyCode)); |
| | | } |
| | | |
| | | |
| | |
| | | package com.doumee.api.web.mall; |
| | | package com.doumee.api.web; |
| | | |
| | | import com.doumee.api.web.ApiController; |
| | | import com.doumee.core.utils.Constants; |
| | | import com.doumee.config.wx.WxMiniConfig; |
| | | import com.doumee.core.constants.Constants; |
| | | import com.doumee.core.utils.ID; |
| | | import com.doumee.core.wx.WxMiniConfig; |
| | | import com.doumee.dao.business.model.ActivitySign; |
| | | import com.doumee.dao.business.model.Fund; |
| | | import com.doumee.dao.business.model.Goodsorder; |
| | | import com.doumee.service.business.OrdersService; |
| | | import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse; |
| | | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.CrossOrigin; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | |
| | | @CrossOrigin |
| | | public class PaymentCallback extends ApiController { |
| | | |
| | | @Autowired |
| | | private OrdersService ordersService; |
| | | |
| | | |
| | | @PostMapping("/web/api/wxPayNotify") |
| | | public String wxPay_notify(@RequestBody String xmlResult) { |
| | |
| | | //微信订单号 |
| | | String paymentNo = result.getTransactionId(); |
| | | |
| | | if (Constants.SUCCESS_STR.equals(result.getReturnCode())) { |
| | | |
| | | |
| | | if (Constants.SUCCESS.equals(result.getReturnCode())) { |
| | | // 支付成功 |
| | | switch (result.getAttach()) { |
| | | //活动参与支付 |
| | | case "ActivitySign": { |
| | | ActivitySign activitySign = activitySignService.findById(Integer.valueOf(outTradeNo)); |
| | | if(Objects.isNull(activitySign)){ |
| | | return WxPayNotifyResponse.fail( "支付回调信息("+ wxId + ") = > 未查询到支付对象信息!"); |
| | | } |
| | | if(activitySign.getStatus().equals(Constants.ONE)){ |
| | | return WxPayNotifyResponse.success("处理成功!"); |
| | | } |
| | | activitySign.setPayStatus(Constants.ONE); |
| | | activitySign.setPayDate(new Date()); |
| | | activitySign.setPayOrderId(paymentNo); |
| | | activitySign.setStatus(Constants.ONE); |
| | | activitySignService.updateById(activitySign); |
| | | //寄存订单 |
| | | case "storageOrder": { |
| | | ordersService.handleStorageOrderPayNotify(outTradeNo, paymentNo); |
| | | break; |
| | | } |
| | | case "terraceMall": { |
| | | Goodsorder DBGoodsOrder = new Goodsorder(); |
| | | DBGoodsOrder.setCode(Long.valueOf(outTradeNo)); |
| | | Goodsorder goodsOrder = goodsorderService.findOne(DBGoodsOrder); |
| | | if(Objects.isNull(goodsOrder)){ |
| | | return WxPayNotifyResponse.fail( "支付回调信息("+ wxId + ") = > 未查询到支付对象信息!"); |
| | | } |
| | | if(goodsOrder.getStatus().equals(Constants.ONE)){ |
| | | return WxPayNotifyResponse.success("处理成功!"); |
| | | } |
| | | goodsOrder.setPayStatus(Constants.ONE); |
| | | goodsOrder.setPayDate(new Date()); |
| | | goodsOrder.setPayOrderId(paymentNo); |
| | | goodsOrder.setStatus(Constants.OrderStatus.PAY_DONE.getKey()); |
| | | goodsOrder.setPayMethod(Constants.ZERO); |
| | | goodsorderService.updateById(goodsOrder); |
| | | //生成 咖啡计划订单明细表 |
| | | if(goodsOrder.getType().equals(Constants.TWO)){ |
| | | planorderDetailService.createPlanOrderDetail(goodsOrder); |
| | | } |
| | | Fund fund = new Fund(); |
| | | fund.setOrderCode(goodsOrder.getPayOrderId()); |
| | | fund.setCreator(goodsOrder.getMemberId()); |
| | | fund.setCreateDate(new Date()); |
| | | fund.setIsdeleted(Constants.ZERO); |
| | | fund.setRemark(goodsOrder.getCode().toString()); |
| | | fund.setMemberId(goodsOrder.getMemberId()); |
| | | fund.setTitle("订单支付"); |
| | | fund.setContent("订单支付"); |
| | | fund.setObjId(goodsOrder.getId()); |
| | | fund.setObjType(Constants.ONE); |
| | | fund.setType(Constants.ZERO); |
| | | fund.setNum(goodsOrder.getPrice()); |
| | | fundService.create(fund); |
| | | break; |
| | | } |
| | | case "shopGoods": { |
| | | Goodsorder DBGoodsOrder = new Goodsorder(); |
| | | DBGoodsOrder.setCode(Long.valueOf(outTradeNo)); |
| | | Goodsorder goodsOrder = goodsorderService.findOne(DBGoodsOrder); |
| | | if(Objects.isNull(goodsOrder)){ |
| | | return WxPayNotifyResponse.fail( "支付回调信息("+ wxId + ") = > 未查询到支付对象信息!"); |
| | | } |
| | | if(goodsOrder.getStatus().equals(Constants.ONE)){ |
| | | return WxPayNotifyResponse.success("处理成功!"); |
| | | } |
| | | goodsOrder.setPayStatus(Constants.ONE); |
| | | goodsOrder.setPayDate(new Date()); |
| | | goodsOrder.setPayOrderId(paymentNo); |
| | | goodsOrder.setStatus(Constants.OrderStatus.PAY_DONE.getKey()); |
| | | //生成核销码 |
| | | if(Constants.equalsInteger(goodsOrder.getReceiveType(),Constants.ONE)){ |
| | | goodsOrder.setExchangeCode(goodsorderService.createExchangeCode()); |
| | | } |
| | | goodsOrder.setPayMethod(Constants.ZERO); |
| | | goodsorderService.updateById(goodsOrder); |
| | | if(Objects.nonNull(goodsOrder.getPickUpShopId())){ |
| | | //发送站内信 - 经销商 |
| | | noticeService.orderPayNotice(goodsOrder.getPickUpShopId(),goodsOrder.getId(),goodsOrder.getReceiveType()); |
| | | } |
| | | Fund fund = new Fund(); |
| | | fund.setOrderCode(goodsOrder.getPayOrderId()); |
| | | fund.setCreator(goodsOrder.getMemberId()); |
| | | fund.setCreateDate(new Date()); |
| | | fund.setIsdeleted(Constants.ZERO); |
| | | fund.setRemark(goodsOrder.getCode().toString()); |
| | | fund.setMemberId(goodsOrder.getMemberId()); |
| | | fund.setTitle("订单支付"); |
| | | fund.setContent("订单支付"); |
| | | fund.setObjId(goodsOrder.getId()); |
| | | fund.setObjType(Constants.ONE); |
| | | fund.setType(Constants.ZERO); |
| | | fund.setNum(goodsOrder.getPrice()); |
| | | fundService.create(fund); |
| | | break; |
| | | } |
| | | //店铺押金订单 |
| | | case "shopDeposit": { |
| | | |
| | | break; |
| | | } |
| | | //逾期费用订单 |
| | | case "overdueFee": { |
| | | |
| | | break; |
| | | } |
| | | } |
| | | return WxPayNotifyResponse.success("处理成功!"); |
| | | } |
| | |
| | | package com.doumee.api.web; |
| | | |
| | | import com.doumee.core.annotation.LoginRequired; |
| | | import com.doumee.core.annotation.LoginShopRequired; |
| | | import com.doumee.core.model.ApiResponse; |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.dao.business.model.Member; |
| | | import com.doumee.dao.dto.ShopApplyDTO; |
| | | import com.doumee.dao.dto.ShopDetailQueryDTO; |
| | | import com.doumee.dao.dto.ShopInfoMaintainDTO; |
| | | import com.doumee.dao.dto.ShopNearbyDTO; |
| | | import com.doumee.dao.vo.ShopDetailVO; |
| | | import com.doumee.dao.vo.ShopNearbyVO; |
| | | import com.doumee.dao.vo.ShopWebDetailVO; |
| | | import com.doumee.service.business.ShopInfoService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | |
| | | return ApiResponse.success(shopInfoService.getMyShop(this.getMemberId())); |
| | | } |
| | | |
| | | @ApiOperation("附近门店分页列表") |
| | | @PostMapping("/nearby") |
| | | public ApiResponse<PageData<ShopNearbyVO>> nearby(@RequestBody @Validated PageWrap<ShopNearbyDTO> pageWrap) { |
| | | return ApiResponse.success(shopInfoService.findNearbyShops(pageWrap)); |
| | | } |
| | | |
| | | @ApiOperation("门店详情") |
| | | @PostMapping("/detail") |
| | | public ApiResponse<ShopWebDetailVO> detail(@RequestBody @Validated ShopDetailQueryDTO dto) { |
| | | return ApiResponse.success(shopInfoService.getShopWebDetail(dto)); |
| | | } |
| | | |
| | | @LoginShopRequired |
| | | @ApiOperation("维护门店信息(支付押金后)") |
| | | @PostMapping("/maintain") |
| | | public ApiResponse maintain(@RequestBody ShopInfoMaintainDTO dto) { |
| | | shopInfoService.maintainShopInfo(this.getMemberId(), dto); |
| | | return ApiResponse.success("操作成功"); |
| | | } |
| | | |
| | | @LoginShopRequired |
| | | @ApiOperation("查询门店维护信息") |
| | | @PostMapping("/maintainInfo") |
| | | public ApiResponse<ShopInfoMaintainDTO> maintainInfo() { |
| | | return ApiResponse.success(shopInfoService.getShopMaintainInfo(this.getMemberId())); |
| | | } |
| | | |
| | | } |