| | |
| | | @Autowired |
| | | private PricingRuleService pricingRuleService; |
| | | |
| | | /*@PreventRepeat |
| | | @ApiOperation("新建") |
| | | @PostMapping("/create") |
| | | @RequiresPermissions("business:pricingRule:create") |
| | | public ApiResponse create(@RequestBody PricingRule pricingRule) { |
| | | return ApiResponse.success(pricingRuleService.create(pricingRule)); |
| | | } |
| | | |
| | | @ApiOperation("根据ID删除") |
| | | @GetMapping("/delete/{id}") |
| | | @RequiresPermissions("business:pricingRule:delete") |
| | | public ApiResponse deleteById(@PathVariable Integer id) { |
| | | pricingRuleService.deleteById(id); |
| | | return ApiResponse.success(null); |
| | | } |
| | | |
| | | @ApiOperation("批量删除") |
| | | @GetMapping("/delete/batch") |
| | | @RequiresPermissions("business:pricingRule:delete") |
| | | public ApiResponse deleteByIdInBatch(@RequestParam String ids) { |
| | | String[] idArray = ids.split(","); |
| | | List<Integer> idList = new ArrayList<>(); |
| | | for (String id : idArray) { |
| | | idList.add(Integer.valueOf(id)); |
| | | } |
| | | pricingRuleService.deleteByIdInBatch(idList); |
| | | return ApiResponse.success(null); |
| | | } |
| | | |
| | | @ApiOperation("根据ID修改") |
| | | @PostMapping("/updateById") |
| | | @RequiresPermissions("business:pricingRule:update") |
| | | public ApiResponse updateById(@RequestBody PricingRule pricingRule) { |
| | | pricingRuleService.updateById(pricingRule); |
| | | return ApiResponse.success(null); |
| | | } |
| | | |
| | | @ApiOperation("分页查询") |
| | | @PostMapping("/page") |
| | | @RequiresPermissions("business:pricingRule:query") |
| | | public ApiResponse<PageData<PricingRule>> findPage(@RequestBody PageWrap<PricingRule> pageWrap) { |
| | | return ApiResponse.success(pricingRuleService.findPage(pageWrap)); |
| | | } |
| | | |
| | | @ApiOperation("导出Excel") |
| | | @PostMapping("/exportExcel") |
| | | @RequiresPermissions("business:pricingRule:exportExcel") |
| | | public void exportExcel(@RequestBody PageWrap<PricingRule> pageWrap, HttpServletResponse response) { |
| | | List<PricingRule> pricingRuleList = pricingRuleService.findPage(pageWrap).getRecords(); |
| | | ExcelExporter.build(PricingRule.class).export(pricingRuleList, "计价规则配置", response); |
| | | } |
| | | |
| | | @ApiOperation("根据ID查询") |
| | | @GetMapping("/{id}") |
| | | @RequiresPermissions("business:pricingRule:query") |
| | | public ApiResponse findById(@PathVariable Integer id) { |
| | | return ApiResponse.success(pricingRuleService.findById(id)); |
| | | }*/ |
| | | |
| | | @PreventRepeat |
| | | @ApiOperation("批量保存就地存取规则") |
| | |
| | | |
| | | spring: |
| | | profiles: |
| | | active: pro |
| | | active: dev |
| | | # JSON返回配置 |
| | | jackson: |
| | | # 默认时区 |
| | |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/05/11 司机版本类型字段 |
| | | -- ============================================================ |
| | | ALTER TABLE `driver_info` ADD COLUMN `VERSION_TYPE` INT DEFAULT 0 COMMENT '司机版本类型:0=正式版本;1=变更版本'; |
| | | ALTER TABLE `driver_info` ADD COLUMN `RELATION_DRIVER_ID` INT DEFAULT NULL COMMENT '关联正式版本司机主键(变更版本使用)'; |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/05/09 门店收益比例配置字段 |
| | | -- ============================================================ |
| | | ALTER TABLE `shop_info` ADD COLUMN `REVENUE_SHARE_CONFIG` TEXT COMMENT '收益比例配置(JSON): remoteCompanyDeposit/remotePersonalDeposit/remoteCompanyTake/remotePersonalTake/localCompanyDeposit/localPersonalDeposit'; |
| | | |
| | | ALTER TABLE `member` ADD COLUMN `LOGIN_SHOP_ID` INT COMMENT '已登录的门店主键'; |
| | | |
| | | ALTER TABLE `shop_info` ADD COLUMN `VERSION_TYPE` INT DEFAULT 0 COMMENT '门店版本类型:0=正式版本;1=变更版本'; |
| | | ALTER TABLE `shop_info` ADD COLUMN `RELATION_SHOP_ID` INT COMMENT '关联正式版本门店主键(变更版本使用)'; |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/05/07 操作半径校验配置 |
| | | -- ============================================================ |
| | | INSERT INTO `system_dict_data` (`DICT_ID`, `CODE`, `LABEL`, `REMARK`, `SORT`, `DISABLED`, `CREATE_USER`, `CREATE_TIME`, `DELETED`) VALUES ((SELECT `id` FROM `system_dict` WHERE `code` = 'OPERATION_CONFIG'), '500', 'OPERATION_RADIUS', '允许操作半径(m)', 0, 0, 1, NOW(), 0); |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/05/07 即将到达取件时间通知相关变更 |
| | | -- ============================================================ |
| | | -- 订单表增加取件通知状态字段 |
| | | ALTER TABLE `orders` ADD COLUMN `PICK_UP_NOTIFY_STATUS` INT DEFAULT 0 COMMENT '取件时间即将到达通知状态:0=未通知;1=已通知'; |
| | | |
| | | -- 运营配置:即将到达取件时间提前通知(分钟) |
| | | INSERT INTO `system_dict_data` (`DICT_ID`, `CODE`, `LABEL`, `REMARK`, `SORT`, `DISABLED`, `CREATE_USER`, `CREATE_TIME`, `DELETED`) VALUES ((SELECT `id` FROM `system_dict` WHERE `code` = 'OPERATION_CONFIG'), '30', 'ARRIVAL_PICK_UP_TIME', '即将到达取件时间提前通知(分钟)', 0, 0, 1, NOW(), 0); |
| | | |
| | | -- 定时任务:即将到达取件时间通知(每5分钟执行一次) |
| | | INSERT INTO `system_job` (`JOB_NAME`, `HANDLER`, `CRON`, `WITH_LOG`, `WITH_ASYNC`, `STATUS`, `REMARK`, `CREATE_USER`, `CREATE_TIME`, `UPDATE_USER`, `UPDATE_TIME`, `DELETED`) VALUES ('即将到达取件时间通知', 'arrivalPickUpNotifyJob', '0 */5 * * * ?', 1, 0, 1, '查询即将到达取件时间的订单,发送短信通知会员', 1, NOW(), 1, NOW(), 0); |
| | | |
| | | |
| | | -- ============================================================ |
| | | -- 2026/04/30 APP版本文件上传字典配置 |
| | | -- ============================================================ |
| | | INSERT INTO `system_dict_data` (`DICT_ID`, `CODE`, `LABEL`, `REMARK`, `SORT`, `DISABLED`, `CREATE_USER`, `CREATE_TIME`, `DELETED`) VALUES ((SELECT `id` FROM `system_dict` WHERE `code` = 'OSS'), '', 'APP_FILES', 'APP版本文件存储路径', 0, 0, 1, NOW(), 0); |
| | |
| | | dto.setNoGrabNotifyTime(getValue(Constants.OP_NO_GRAB_NOTIFY_TIME)); |
| | | dto.setNoGrabNotifyUsers(getValue(Constants.OP_NO_GRAB_NOTIFY_USERS)); |
| | | dto.setDefaultDeliveryRange(getValue(Constants.OP_DEFAULT_DELIVERY_RANGE)); |
| | | dto.setArrivalPickUpTime(getValue(Constants.OP_ARRIVAL_PICK_UP_TIME)); |
| | | dto.setOperationRadius(getValue(Constants.OP_OPERATION_RADIUS)); |
| | | return dto; |
| | | } |
| | | |
| | |
| | | saveOrUpdate(Constants.OP_NO_GRAB_NOTIFY_TIME, "无人抢单通知时间", dto.getNoGrabNotifyTime()); |
| | | saveOrUpdate(Constants.OP_NO_GRAB_NOTIFY_USERS, "无人抢单短信通知人员", dto.getNoGrabNotifyUsers()); |
| | | saveOrUpdate(Constants.OP_DEFAULT_DELIVERY_RANGE, "默认配送范围", dto.getDefaultDeliveryRange()); |
| | | saveOrUpdate(Constants.OP_ARRIVAL_PICK_UP_TIME, "即将到达取件时间通知", dto.getArrivalPickUpTime()); |
| | | // saveOrUpdate(Constants.OP_OPERATION_RADIUS, "允许操作半径", dto.getOperationRadius()); |
| | | } |
| | | |
| | | private String getValue(String label) { |
| | |
| | | public static String generateTokenForRedis(Integer userId, Integer userType, String userInfo, RedisTemplate<String,Object> redisTemplate) { |
| | | // 删除该用户之前登录的token |
| | | String userTokenMappingKey = Constants.REDIS_TOKEN_KEY + "user_" + userType + "_" + userId; |
| | | |
| | | String oldToken = (String) redisTemplate.opsForValue().get(userTokenMappingKey); |
| | | if (StringUtils.isNotBlank(oldToken)) { |
| | | redisTemplate.delete(Constants.REDIS_TOKEN_KEY + oldToken); |
| | |
| | | } |
| | | |
| | | |
| | | public static String generateShopTokenForRedis(Integer userId, String userInfo, RedisTemplate<String,Object> redisTemplate) { |
| | | // 删除该用户之前登录的token |
| | | String userTokenMappingKey = Constants.REDIS_TOKEN_KEY + "user_" + Constants.TWO + "_" + userId; |
| | | String oldToken = (String) redisTemplate.opsForValue().get(userTokenMappingKey); |
| | | if (StringUtils.isNotBlank(oldToken)) { |
| | | redisTemplate.delete(Constants.REDIS_TOKEN_KEY + oldToken); |
| | | } |
| | | // 生成新token |
| | | String tokenKey = Constants.TWO +""+ UUID.randomUUID() + "_" + userId; |
| | | redisTemplate.opsForValue().set(Constants.REDIS_TOKEN_KEY + tokenKey, userInfo, redisExpire, TimeUnit.DAYS); |
| | | // 记录用户与token的映射关系 |
| | | redisTemplate.opsForValue().set(userTokenMappingKey, tokenKey, redisExpire, TimeUnit.DAYS); |
| | | return tokenKey; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 刷新令牌 |
| | | * |
| | |
| | | throw new BusinessException(ResponseStatus.SHOP_BE_OVERDUE); |
| | | } |
| | | String openid = shop.getOpenid(); |
| | | Integer shopId = getTokenId(token); |
| | | Integer isDeleted = dao.queryForObject(" select COALESCE(DELETED,0) from shop_info where id = ?", Integer.class, shopId); |
| | | Integer shopId = shop.getId();//getTokenId(token); |
| | | Integer isDeleted = dao.queryForObject(" select COALESCE(DELETED,0) from shop_info where VERSION_TYPE = 0 and 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); |
| | | Integer isForbidden = dao.queryForObject(" select COALESCE(STATUS,0) from shop_info where VERSION_TYPE = 0 and id = ?", Integer.class, shopId); |
| | | if(isForbidden == Constants.ONE){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"商户已禁用,请联系管理员"); |
| | | } |
| | | Integer count = dao.queryForObject("select count(1) from shop_info where id = ?", Integer.class, shopId); |
| | | Integer count = dao.queryForObject("select count(1) from shop_info where VERSION_TYPE = 0 and id = ?", Integer.class, shopId); |
| | | if (count != null && count > 0) { |
| | | request.setAttribute(JwtTokenUtil.SHOP_ID, shop.getId()); |
| | | return true; |
| | |
| | | public static final String FEE_STANDARDS ="FEE_STANDARDS" ; |
| | | public static final String ABOUT_US ="ABOUT_US" ; |
| | | public static final String SERVER_PHONE ="SERVER_PHONE" ; |
| | | public static final String ARRIVAL_PICK_UP_TIME ="ARRIVAL_PICK_UP_TIME" ;//即将到达取件时间配置(分钟) |
| | | |
| | | public static final String USER_AGREEMENT ="USER_AGREEMENT" ; |
| | | public static final String PRIVACY_AGREEMENT ="PRIVACY_AGREEMENT" ; |
| | | |
| | |
| | | public static final String OP_NO_GRAB_NOTIFY_TIME = "NO_GRAB_NOTIFY_TIME"; |
| | | public static final String OP_NO_GRAB_NOTIFY_USERS = "NO_GRAB_NOTIFY_USERS"; |
| | | public static final String OP_DEFAULT_DELIVERY_RANGE = "DEFAULT_DELIVERY_RANGE"; |
| | | public static final String OP_ARRIVAL_PICK_UP_TIME = "ARRIVAL_PICK_UP_TIME"; |
| | | public static final String OP_OPERATION_RADIUS = "OPERATION_RADIUS"; |
| | | |
| | | // 芯烨云打印机配置 |
| | | public static final String XPYUN_CONFIG = "XPYUN_CONFIG"; |
| | |
| | | deposited(2, "已寄存"), |
| | | accepted(3, "已接单"), |
| | | delivering(4, "派送中"), |
| | | arrived(5, "已到店/已送达/待取件"), |
| | | arrived(5, "已到店/已送达"), |
| | | overdue(6, "存在逾期"), //弃用 |
| | | finished(7, "已完成"), |
| | | cancelled(99, "已取消") |
| | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum SmsNotify { |
| | | PLATFORM_WAIT_GRAB("SMS_505865290", "平台端-待抢单", "您好,订单:{orderNo}已超过{time}分钟无司机抢单,请尽快加急派单,避免客户过久等待。"), |
| | | SHOP_REFUNDING("SMS_505905263", "门店端-退款中", "行李订单:{orderNo}客户已提交退款申请,请尽快处理。"), |
| | | SHOP_WAIT_VERIFY("SMS_505915292", "门店端-待核验", "新行李订单:{orderNo}客户已支付,请尽快核验用户物品信息。"), |
| | | DRIVER_REFUNDING("SMS_505905264", "司机端-退款中", "行李订单:{orderNo}用户已提交退款申请,该订单任务已取消,请勿前往。"), |
| | | DRIVER_WAIT_PICKUP("SMS_505960277", "司机端-待取件", "您已抢单成功,订单{orderNo},请按时到{address}取件。"), |
| | | MEMBER_CANCELLED("SMS_505615328", "会员端-已取消", "您的行李订单:{orderNo}已取消,感谢您的支持,欢迎下次再会。"), |
| | | MEMBER_REFUNDED("SMS_505850299", "会员端-已退款", "您的行李订单:{orderNo}退款已完成,金额{money}元将原路退回,请注意查收。"), |
| | | MEMBER_ARRIVED("SMS_505645328", "会员端-已送达", "您的行李订单:{orderNo}已送到{address},请及时取件,取件码:{code}。"), |
| | | MEMBER_DELIVERING("SMS_505715321", "会员端-配送中", "您的行李订单:{orderNo}已由司机{name}取件,正运往目的地。"), |
| | | VERIFY_CODE("SMS_333770877", "验证码短信", "您的验证码为:{code},请勿泄露于他人!"), |
| | | DRIVER_AUTH_REJECTED("SMS_505790115", "司机端-司机认证被拒绝", "尊敬的{driver},很遗憾,您的司机认证未通过审核。原因:{reason}。您可修改资料后重新提交。"), |
| | | DRIVER_AUTH_APPROVED("SMS_505885083", "司机端-司机认证通过", "尊敬的{driver},恭喜您已通过平台司机认证审核。您可登录司机端APP开始接单,配送过程中请注意安全,祝您接单顺利!"), |
| | | DRIVER_URGENT_DISPATCH("SMS_505940293", "司机端-加急派单", "您好,您有一个新的行李订单(编号:{orderNo})。起点:{address1},终点:{address2},配送费{money1}元(含加急费{money2}元)。请尽快确认订单任务。"), |
| | | SHOP_AUTH_REJECTED("SMS_505925106", "门店端-资料审核被拒绝", "很遗憾,您的门店\"{storeName}\"未通过审核,原因:{reason},您可修改资料后重新提交。"), |
| | | SHOP_AUTH_APPROVED_DEPOSIT("SMS_505705111", "门店端-审核通过需缴纳押金", "恭喜您!您的门店\"{storeName}\"已通过初步审核。请支付押金{money}元以完成入驻,支付后即可登录门店后台正式接单。"), |
| | | SHOP_AUTH_SUCCESS("SMS_505915289", "门店端-成功入驻通知", "恭喜您!您的门店\"{storeName}\"已通过平台审核,正式入驻成功。 您可登录商家后台开始接单,账号:注册手机号,初始密码::{password}(建议首次登录后修改)。"), |
| | | PLATFORM_WAIT_GRAB("SMS_505865290", "平台端-待抢单", "您好,订单:{orderNo}已超过{time}分钟无司机抢单,请尽快加急派单,避免客户过久等待。", true), |
| | | SHOP_REFUNDING("SMS_505905263", "门店端-退款中", "行李订单:{orderNo}客户已提交退款申请,请尽快处理。", false), |
| | | SHOP_WAIT_VERIFY("SMS_505915292", "门店端-待核验", "新行李订单:{orderNo}客户已支付,请尽快核验用户物品信息。", false), |
| | | DRIVER_REFUNDING("SMS_505905264", "司机端-退款中", "行李订单:{orderNo}用户已提交退款申请,该订单任务已取消,请勿前往。", true), |
| | | DRIVER_WAIT_PICKUP("SMS_505960277", "司机端-待取件", "您已抢单成功,订单{orderNo},请按时到{address}取件。", true), |
| | | MEMBER_CANCELLED("SMS_505615328", "会员端-已取消", "您的行李订单:{orderNo}已取消,感谢您的支持,欢迎下次再会。", true), |
| | | MEMBER_REFUNDED("SMS_505850299", "会员端-已退款", "您的行李订单:{orderNo}退款已完成,金额{money}元将原路退回,请注意查收。", true), |
| | | MEMBER_ARRIVED("SMS_505645328", "会员端-已送达", "您的行李订单:{orderNo}已送到{address},请及时取件,取件码:{code}。", true), |
| | | MEMBER_DELIVERING("SMS_505715321", "会员端-配送中", "您的行李订单:{orderNo}已由司机{name}取件,正运往目的地。", true), |
| | | VERIFY_CODE("SMS_333770877", "验证码短信", "您的验证码为:{code},请勿泄露于他人!", true), |
| | | DRIVER_AUTH_REJECTED("SMS_505790115", "司机端-司机认证被拒绝", "尊敬的{driver},很遗憾,您的司机认证未通过审核。原因:{reason}。您可修改资料后重新提交。", true), |
| | | DRIVER_AUTH_APPROVED("SMS_505885083", "司机端-司机认证通过", "尊敬的{driver},恭喜您已通过平台司机认证审核。您可登录司机端APP开始接单,配送过程中请注意安全,祝您接单顺利!", true), |
| | | DRIVER_URGENT_DISPATCH("SMS_505940293", "司机端-加急派单", "您好,您有一个新的行李订单(编号:{orderNo})。起点:{address1},终点:{address2},配送费{money1}元(含加急费{money2}元)。请尽快确认订单任务。", true), |
| | | SHOP_AUTH_REJECTED("SMS_505925106", "门店端-资料审核被拒绝", "很遗憾,您的门店\"{storeName}\"未通过审核,原因:{reason},您可修改资料后重新提交。", true), |
| | | SHOP_AUTH_APPROVED_DEPOSIT("SMS_506135030", "门店端-审核通过需缴纳押金", "恭喜您!您的门店\"{storeName}\"已通过初步审核。请支付押金{money}元以完成入驻,支付后即可登录门店后台正式接单。", true), |
| | | SHOP_AUTH_SUCCESS("SMS_505885083", "门店端-成功入驻通知", "恭喜您!您的门店\"{storeName}\"已通过平台审核,正式入驻成功。 您可登录商家后台开始接单,账号:注册手机号,初始密码::{password}(建议首次登录后修改)。", true), |
| | | MEMBER_TIME_OUT("SMS_506190182", "会员端-即将超时", "您的行李订单:{orderNo}即将到达预计取件时间,请尽快取件,超时将产生逾期费用,请知悉。", true), |
| | | ; |
| | | |
| | | private final String templateCode; |
| | | private final String title; |
| | | private final String content; |
| | | private final boolean enabled; |
| | | |
| | | public String format(String... params) { |
| | | String result = this.content; |
| | |
| | | @ApiModelProperty(value = "极光推送别名") |
| | | private String jpushAlias; |
| | | |
| | | @ApiModelProperty(value = "司机版本类型:0=正式版本;1=变更版本", example = "0") |
| | | private Integer versionType; |
| | | |
| | | @ApiModelProperty(value = "关联正式版本司机主键(变更版本使用)", example = "1") |
| | | private Integer relationDriverId; |
| | | |
| | | } |
| | |
| | | @ApiModelProperty(value = "用户类型:0=会员用户;1=司机;2=店铺人员;(司机与店铺均和会员表使用同主键值)", example = "1") |
| | | private Integer userType; |
| | | |
| | | @ApiModelProperty(value = "已登录的门店主键", example = "1") |
| | | private Integer loginShopId; |
| | | |
| | | @ApiModelProperty(value = "业务状态:0=未认证;1=认证通过;2=认证未通过 ;3=已支付押金", example = "1") |
| | | private Integer businessStatus; |
| | | |
| | |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "创建开始时间(查询用)", example = "2026-01-01 00:00:00") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | private Date createStartTime; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "创建结束时间(查询用)", example = "2026-12-31 23:59:59") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | private Date createEndTime; |
| | | |
| | | @TableField(exist = false) |
| | |
| | | private Integer shopId; |
| | | |
| | | |
| | | @ApiModelProperty(value = "店铺订单序号") |
| | | private Long autoNum; |
| | | |
| | | @ApiModelProperty(value = "取件时间即将到达通知状态:0=未通知;1=已通知") |
| | | private Integer pickUpNotifyStatus; |
| | | |
| | | @ApiModelProperty(value = "序号") |
| | | @TableField(exist = false) |
| | | private Integer sortNum; |
| | |
| | | @ApiModelProperty(value = "芯烨云打印机SN编号") |
| | | private String printerSn; |
| | | |
| | | @ApiModelProperty(value = "收益比例配置(JSON)", notes = "{\n" + |
| | | " \"localDeposit\": 5,\n" + |
| | | " \"remoteDeposit\": 5,\n" + |
| | | " \"remoteTake\": 5\n" + |
| | | "}") |
| | | private String revenueShareConfig; |
| | | |
| | | @ApiModelProperty(value = "门店版本类型:0=正式版本;1=变更版本", example = "0") |
| | | private Integer versionType; |
| | | |
| | | @ApiModelProperty(value = "关联正式版本门店主键(变更版本使用)", example = "1") |
| | | private Integer relationShopId; |
| | | |
| | | |
| | | @ApiModelProperty(value = "当前登录的会员主键", hidden = true) |
| | | @TableField(exist = false) |
| | | private Integer memberId; |
| | | |
| | | |
| | | // 非持久化:附件列表 |
| | | @TableField(exist = false) |
| | |
| | | @ApiModelProperty(value = "订单状态:3=已抢单;4=派送中", example = "3", required = true) |
| | | private Integer status; |
| | | |
| | | @ApiModelProperty(value = "搜索关键词(收件人/收件人电话模糊/订单号精准)") |
| | | private String keyword; |
| | | |
| | | } |
| | |
| | | @ApiModelProperty(value = "合并状态(可选,不传查全部): 0=待支付 1=待核验 2=待配送 3=待收货 4=已完成 5=退款 6会员首页 7门店待处理订单", example = "0") |
| | | private Integer combinedStatus; |
| | | |
| | | @ApiModelProperty(value = "搜索关键词(收件人/收件人电话模糊/订单号精准)") |
| | | private String keyword; |
| | | |
| | | } |
| | |
| | | @ApiModelProperty(value = "默认配送范围(km)", required = true) |
| | | private String defaultDeliveryRange; |
| | | |
| | | @ApiModelProperty(value = "即将到达取件时间提前通知(分钟)", required = true) |
| | | private String arrivalPickUpTime; |
| | | |
| | | @ApiModelProperty(value = "允许操作半径(m)", required = true) |
| | | private String operationRadius; |
| | | |
| | | } |
| | |
| | | @ApiModel("分成比例规则项") |
| | | public class RevenueShareItemDTO implements Serializable { |
| | | |
| | | @ApiModelProperty(value = "类型(0=企业寄, 1=个人寄, 2=企业取, 3=个人取, 4=配送员)", required = true, example = "0") |
| | | @ApiModelProperty(value = "类型(0=异地企业寄, 1=异地个人寄, 2=异地企业取, 3=异地个人取, 4=配送员, 5=就地企业存, 6=就地个人存)", required = true, example = "0") |
| | | @NotNull(message = "类型不能为空") |
| | | private Integer fieldType; |
| | | |
| | |
| | | @NotNull(message = "城市主键不能为空") |
| | | private Integer cityId; |
| | | |
| | | @ApiModelProperty(value = "规则明细列表(企业寄/个人寄/企业取/个人取/配送员共5条)", required = true) |
| | | @ApiModelProperty(value = "规则明细列表(异地企业寄/异地个人寄/异地企业取/异地个人取/配送员/就地企业存/就地个人存共7条)", required = true) |
| | | @NotEmpty(message = "规则明细不能为空") |
| | | @Valid |
| | | private List<RevenueShareItemDTO> items; |
| | |
| | | @ApiModelProperty(value = "支付宝实名姓名", required = true) |
| | | @NotBlank(message = "支付宝实名姓名不能为空") |
| | | private String aliName; |
| | | |
| | | @ApiModelProperty(value = "就地寄存分成占比(%)", required = true, example = "5.5") |
| | | private Double localDeposit; |
| | | |
| | | @ApiModelProperty(value = "异地存件分成占比(%)", required = true, example = "5.5") |
| | | private Double remoteDeposit; |
| | | |
| | | @ApiModelProperty(value = "异地取件分成占比(%)", required = true, example = "5.5") |
| | | private Double remoteTake; |
| | | } |
| | |
| | | @ApiModel("门店登录请求对象") |
| | | public class ShopLoginDTO { |
| | | |
| | | @ApiModelProperty(value = "openid") |
| | | private String openid; |
| | | @ApiModelProperty(value = "会员主键") |
| | | private Integer memberId; |
| | | |
| | | @ApiModelProperty(value = "登录手机号") |
| | | private String telephone; |
| | |
| | | @NotBlank(message = "支付宝实名姓名不能为空") |
| | | private String aliName; |
| | | |
| | | @ApiModelProperty(value = "就地寄存分成占比(%)", required = true, example = "5.5") |
| | | @NotNull(message = "就地寄存分成占比不能为空") |
| | | private Double localDeposit; |
| | | |
| | | @ApiModelProperty(value = "异地存件分成占比(%)", required = true, example = "5.5") |
| | | @NotNull(message = "异地存件分成占比不能为空") |
| | | private Double remoteDeposit; |
| | | |
| | | @ApiModelProperty(value = "异地取件分成占比(%)", required = true, example = "5.5") |
| | | @NotNull(message = "异地取件分成占比不能为空") |
| | | private Double remoteTake; |
| | | |
| | | } |
| | |
| | | |
| | | @ApiModelProperty(value = "禁寄物品") |
| | | private String prohibitedItems; |
| | | |
| | | @ApiModelProperty(value = "服务电话") |
| | | private String serverPhone; |
| | | } |
| | |
| | | @ApiModelProperty(value = "城市主键") |
| | | private Integer cityId; |
| | | |
| | | @ApiModelProperty(value = "类型(0=企业寄, 1=个人寄, 2=企业取, 3=个人取, 4=配送员)") |
| | | @ApiModelProperty(value = "类型(0=异地企业寄, 1=异地个人寄, 2=异地企业取, 3=异地个人取, 4=配送员, 5=就地企业存, 6=就地个人存)") |
| | | private Integer fieldType; |
| | | |
| | | @ApiModelProperty(value = "类型名称") |
| | |
| | | @ApiModelProperty(value = "门店评分") |
| | | private BigDecimal score; |
| | | |
| | | @ApiModelProperty(value = "配送距离") |
| | | private BigDecimal deliveryRange; |
| | | |
| | | @ApiModelProperty(value = "创建时间") |
| | | private Date createTime; |
| | | |
| | |
| | | |
| | | @ApiModelProperty(value = "门店头像(全路径)") |
| | | private String shopAvatar; |
| | | |
| | | @ApiModelProperty(value = "就地寄存分成占比(%)", example = "5.5") |
| | | private Double localDeposit; |
| | | |
| | | @ApiModelProperty(value = "异地存件分成占比(%)", example = "5.5") |
| | | private Double remoteDeposit; |
| | | |
| | | @ApiModelProperty(value = "异地取件分成占比(%)", example = "5.5") |
| | | private Double remoteTake; |
| | | |
| | | @ApiModelProperty(value = "门店版本类型:0=正式版本;1=变更版本", example = "0") |
| | | private Integer versionType; |
| | | |
| | | @ApiModelProperty(value = "关联正式版本门店主键") |
| | | private Integer relationShopId; |
| | | } |
| | |
| | | @ApiModelProperty(value = "我注册的门店主键(门店用户时返回)") |
| | | private Integer shopId; |
| | | |
| | | @ApiModelProperty(value = "我注册的门店审核状态(门店用户时返回): 0=待审核 1=已通过 2=已驳回 3=已缴纳保证金") |
| | | @ApiModelProperty(value = "我注册的门店审核状态: 0=待审批 1=已通过 2=已驳回 3=已支付押金 4=变更中 5=变更未通过") |
| | | private Integer shopAuditStatus; |
| | | |
| | | @ApiModelProperty(value = "我当前绑定的门店") |
| | |
| | | import com.doumee.dao.dto.UpdMobileRequest; |
| | | import com.doumee.dao.dto.WxPhoneRequest; |
| | | import com.doumee.dao.vo.AccountResponse; |
| | | import com.doumee.dao.vo.MemberContactVO; |
| | | import com.doumee.dao.vo.MemberDetailVO; |
| | | import com.doumee.dao.vo.MemberListVO; |
| | | import com.doumee.dao.vo.PlatformAboutVO; |
| | |
| | | |
| | | void logOff(String token,Integer memberId); |
| | | |
| | | MemberContactVO getContactInfo(Integer memberId); |
| | | |
| | | |
| | | /** |
| | | * 验证手机号 |
| | |
| | | */ |
| | | void printOrderLabel(Integer orderId, Integer shopId); |
| | | |
| | | /** |
| | | * 即将到达取件时间通知 |
| | | * @return 通知数量 |
| | | */ |
| | | int notifyArrivalPickUp(); |
| | | |
| | | /** |
| | | * 校验操作半径 |
| | | * @param orderId 订单主键 |
| | | * @param userId 操作用户主键 |
| | | * @param userType 用户类型:0=门店;1=司机 |
| | | * @param lng 操作人经度 |
| | | * @param lat 操作人纬度 |
| | | * @return true=在允许操作范围内;false=超出允许操作范围 |
| | | */ |
| | | Boolean checkOperationRadius(Integer orderId, Integer userId, Integer userType, Double lng, Double lat); |
| | | |
| | | } |
| | |
| | | String code = RandomStringUtils.randomNumeric(6); |
| | | // 发送短信 |
| | | String templateParam = "{\"code\":\"" + code + "\"}"; |
| | | if (Constants.SmsNotify.VERIFY_CODE.isEnabled()) { |
| | | AliSmsService.sendSms(telephone, Constants.SmsNotify.VERIFY_CODE.getTemplateCode(), templateParam); |
| | | } |
| | | // 保存短信记录 |
| | | Smsrecord smsrecord = new Smsrecord(); |
| | | smsrecord.setDeleted(Constants.ZERO); |
| | |
| | | driverInfo.setMemberId(member.getId()); |
| | | driverInfo.setStatus(Constants.ZERO); |
| | | driverInfo.setAuditStatus(99); |
| | | driverInfo.setVersionType(Constants.ZERO); |
| | | driverInfo.setJpushAlias(org.springframework.util.DigestUtils.md5DigestAsHex(telephone.getBytes())); |
| | | driverInfoMapper.insert(driverInfo); |
| | | } |
| | |
| | | .eq(Objects.nonNull(dto.getStatus()),Orders::getStatus, dto.getStatus()) |
| | | .eq(Orders::getDeleted, Constants.ZERO) |
| | | .orderByAsc(Orders::getAcceptTime); |
| | | // 关键词搜索:收件人/收件人电话模糊、订单号精准 |
| | | if (StringUtils.isNotBlank(dto.getKeyword())) { |
| | | String kw = dto.getKeyword().trim(); |
| | | wrapper.and(w -> w.like(Orders::getTakeUser, kw) |
| | | .or().like(Orders::getTakePhone, kw) |
| | | .or().eq(Orders::getCode, kw)); |
| | | } |
| | | |
| | | List<Orders> ordersList = ordersMapper.selectJoinList(Orders.class, wrapper); |
| | | |
| | |
| | | if (StringUtils.isBlank(phone)) { |
| | | return; |
| | | } |
| | | if (!smsNotify.isEnabled()) { |
| | | return; |
| | | } |
| | | String content = smsNotify.format(paramPairs); |
| | | try { |
| | | JSONObject templateParam = new JSONObject(); |
| | |
| | | .select("s1.name", Orders::getDepositShopName) |
| | | .select("s1.address", Orders::getDepositShopAddress) |
| | | .select("s2.name", Orders::getTakeShopName) |
| | | .select("s2.address", Orders::getDepositShopAddress) |
| | | .select("s2.address", Orders::getTakeShopAddress) |
| | | .select("s1.link_phone as takeShopLinkPhone") |
| | | .select("s2.link_phone as takeShopLinkPhone") |
| | | .select("c2.other_field as c2OtherField") |
| | |
| | | import com.doumee.dao.dto.UpdMobileRequest; |
| | | import com.doumee.dao.dto.WxPhoneRequest; |
| | | import com.doumee.dao.vo.AccountResponse; |
| | | import com.doumee.dao.vo.MemberContactVO; |
| | | import com.doumee.dao.vo.MemberDetailVO; |
| | | import com.doumee.dao.vo.MemberListVO; |
| | | import com.doumee.dao.vo.PlatformAboutVO; |
| | |
| | | * 门店用户身份时,填充门店审核状态 |
| | | */ |
| | | private void fillShopInfo(UserCenterVO userCenterVO, Member member) { |
| | | ShopInfo shopInfo = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda() |
| | | // 查询正式版本门店 |
| | | ShopInfo official = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda() |
| | | .eq(ShopInfo::getRegionMemberId, member.getId()) |
| | | .eq(ShopInfo::getVersionType, Constants.ZERO) |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | if (shopInfo != null) { |
| | | userCenterVO.setShopId(shopInfo.getId()); |
| | | userCenterVO.setShopAuditStatus(shopInfo.getAuditStatus()); |
| | | if (official != null) { |
| | | userCenterVO.setShopId(official.getId()); |
| | | if (Constants.equalsInteger(official.getAuditStatus(), Constants.THREE)) { |
| | | // 正式版本已支付押金,查询最新变更版本状态 |
| | | ShopInfo changeVersion = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda() |
| | | .eq(ShopInfo::getRelationShopId, official.getId()) |
| | | .eq(ShopInfo::getVersionType, Constants.ONE) |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .orderByDesc(ShopInfo::getCreateTime) |
| | | .last("limit 1")); |
| | | if (changeVersion != null) { |
| | | if (Constants.equalsInteger(changeVersion.getAuditStatus(), Constants.THREE)) { |
| | | userCenterVO.setShopAuditStatus(Constants.THREE); |
| | | } else if (Constants.equalsInteger(changeVersion.getAuditStatus(), Constants.ZERO)) { |
| | | userCenterVO.setShopAuditStatus(4); // 变更中 |
| | | } else if (Constants.equalsInteger(changeVersion.getAuditStatus(), Constants.TWO)) { |
| | | userCenterVO.setShopAuditStatus(5); // 变更未通过 |
| | | } else { |
| | | userCenterVO.setShopAuditStatus(Constants.THREE); |
| | | } |
| | | } else { |
| | | // 无变更版本,保持正式版本状态 |
| | | userCenterVO.setShopAuditStatus(Constants.THREE); |
| | | } |
| | | } else { |
| | | // 正式版本未支付押金,直接返回当前状态 |
| | | userCenterVO.setShopAuditStatus(official.getAuditStatus()); |
| | | } |
| | | } |
| | | // 根据openid查询当前绑定的门店 |
| | | if (StringUtils.isNotBlank(member.getOpenid())) { |
| | |
| | | vo.setDriverPrivacyPolicy(getDictValue(Constants.DRIVER_PRIVACY_POLICY)); |
| | | vo.setPriceDescription(getDictValue(Constants.PRICE_DESCRIPTION)); |
| | | vo.setProhibitedItems(getDictValue(Constants.PROHIBITED_ITEMS)); |
| | | vo.setServerPhone(StringUtils.trimToNull(systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.SERVER_PHONE).getCode())); |
| | | return vo; |
| | | } |
| | | |
| | |
| | | if(Constants.equalsInteger(userType,Constants.ZERO)){ |
| | | memberMapper.update(new UpdateWrapper<Member>().lambda().setSql(" openid = null ").eq(Member::getId,userId)); |
| | | }else if(Constants.equalsInteger(userType,Constants.TWO)){ |
| | | shopInfoMapper.update(new UpdateWrapper<ShopInfo>().lambda().setSql(" openid = null ").eq(ShopInfo::getId,userId)); |
| | | try { |
| | | Integer lastIndex = token.lastIndexOf("_")+1; |
| | | Integer tokenId = Integer.valueOf(token.substring(lastIndex)); |
| | | memberMapper.update(new UpdateWrapper<Member>().lambda().setSql(" LOGIN_SHOP_ID = null ").eq(Member::getId,tokenId)); |
| | | }catch (Exception e){ |
| | | |
| | | } |
| | | } |
| | | jwtTokenUtil.logout(token); |
| | | } |
| | |
| | | redisTemplate.delete(token); |
| | | } |
| | | |
| | | @Override |
| | | public MemberContactVO getContactInfo(Integer memberId) { |
| | | MemberContactVO vo = new MemberContactVO(); |
| | | // 优先从历史订单取收件人信息 |
| | | Orders lastOrder = ordersMapper.selectOne(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getMemberId, memberId) |
| | | .eq(Orders::getDeleted, Constants.ZERO) |
| | | .isNotNull(Orders::getTakeUser) |
| | | .ne(Orders::getTakeUser, "") |
| | | .orderByDesc(Orders::getId) |
| | | .last("limit 1")); |
| | | if (lastOrder != null && StringUtils.isNotBlank(lastOrder.getTakeUser())) { |
| | | vo.setName(lastOrder.getTakeUser()); |
| | | vo.setPhone(lastOrder.getTakePhone()); |
| | | return vo; |
| | | } |
| | | // 取用户信息 |
| | | Member member = memberMapper.selectById(memberId); |
| | | if (member != null) { |
| | | vo.setName(member.getName() != null ? member.getName() : ""); |
| | | vo.setPhone(member.getTelephone() != null ? member.getTelephone() : ""); |
| | | } |
| | | return vo; |
| | | } |
| | | |
| | | |
| | | /***************管理端会员列表接口*************/ |
| | | |
| | |
| | | wrapper.ge(OrdersRefund::getCreateTime, model.getCreateStartTime()); |
| | | } |
| | | if (model.getCreateEndTime() != null) { |
| | | wrapper.le(OrdersRefund::getCreateTime, model.getCreateEndTime()); |
| | | wrapper.le(OrdersRefund::getCreateTime, Utils.Date.getEnd(model.getCreateEndTime())); |
| | | } |
| | | } |
| | | |
| | |
| | | import com.doumee.core.model.PageData; |
| | | import com.doumee.core.model.PageWrap; |
| | | import com.doumee.core.utils.DateUtil; |
| | | import com.doumee.core.utils.GeoUtils; |
| | | import com.doumee.core.utils.ID; |
| | | import com.doumee.core.utils.geocode.MapUtil; |
| | | import com.doumee.core.utils.Utils; |
| | |
| | | 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, pageWrap.getModel().getCreateStartTime()); |
| | | queryWrapper.le(pageWrap.getModel().getCreateEndTime() != null, Orders::getCreateTime, pageWrap.getModel().getCreateEndTime()); |
| | | 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()); |
| | |
| | | if (o.getStatus() != null) { |
| | | Constants.OrderStatus os = Constants.OrderStatus.getByKey(o.getStatus()); |
| | | o.setStatusDesc(os != null ? os.getValue() : ""); |
| | | } |
| | | if(Constants.equalsInteger(o.getIsUrgent(),Constants.ZERO)){ |
| | | o.setUrgentAmount(Constants.ZERO.longValue()); |
| | | } |
| | | } |
| | | return pageData; |
| | |
| | | // 3. 逐项计算运费:起步价 + 超出部分阶梯价 |
| | | List<ItemPriceVO> itemList = new ArrayList<>(); |
| | | long itemPriceTotal = 0L; |
| | | long maxExtraFeeTotal = 0L; // 最大超出距离费用(单价×数量) |
| | | |
| | | for (OrderItemDTO item : dto.getItems()) { |
| | | PricingRule rule = ruleMap.get(String.valueOf(item.getCategoryId())); |
| | |
| | | long extraPricePerUnit = Long.parseLong(rule.getFieldE()); |
| | | |
| | | // 阶梯计价:距离 ≤ 起步距离取起步价,超出按 ceil(超出距离/单位) × 单价累加 |
| | | long extraFee = 0L; |
| | | 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; |
| | | extraFee = extraCount.longValue() * extraPricePerUnit; |
| | | unitPrice = startPrice + extraFee; |
| | | } |
| | | |
| | | long subtotal = unitPrice * item.getQuantity(); |
| | |
| | | vo.setExtraPrice(extraPricePerUnit); |
| | | itemList.add(vo); |
| | | |
| | | itemPriceTotal += subtotal; |
| | | // 所有物品的起步价×数量 累加 |
| | | itemPriceTotal += startPrice * item.getQuantity(); |
| | | // 记录最大的超出距离费用 |
| | | long extraFeeTotal = extraFee * item.getQuantity(); |
| | | if (extraFeeTotal > maxExtraFeeTotal) { |
| | | maxExtraFeeTotal = extraFeeTotal; |
| | | } |
| | | } |
| | | |
| | | // 多物品时只加最大的超出距离费用 |
| | | itemPriceTotal += maxExtraFeeTotal; |
| | | |
| | | // 4. 保价费用:报价金额 × 保价费率(字典 INSURANCE_RATE),元→分(保价金额>0时计费) |
| | | long insuranceFeeFen = 0L; |
| | |
| | | return; |
| | | } |
| | | Integer cityId = Integer.valueOf(orders.getCityId()); |
| | | boolean isRemote = Constants.equalsInteger(orders.getType(), Constants.ONE); |
| | | boolean isCompany = Constants.equalsInteger(depositShop.getCompanyType(), Constants.ONE); |
| | | |
| | | // 司机占比:fieldA=4(配送员) |
| | | // 司机占比: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); |
| | | // 取件门店占比:无取件门店时比例为0 |
| | | BigDecimal takeShopRata = BigDecimal.ZERO; |
| | | if (takeShop != null) { |
| | | int takeFieldA = Constants.equalsInteger(takeShop.getCompanyType(), Constants.ONE) ? Constants.TWO : Constants.THREE; |
| | | takeShopRata = getRevenueShareRata(cityId, takeFieldA); |
| | | |
| | | // 存件门店占比 |
| | | BigDecimal depositShopRata; |
| | | if (isRemote) { |
| | | int fallbackFieldA = isCompany ? Constants.ZERO : Constants.ONE; |
| | | depositShopRata = getShopRevenueShare(depositShop, "remoteDeposit", cityId, fallbackFieldA); |
| | | } else { |
| | | int fallbackFieldA = isCompany ? Constants.FIVE : Constants.SIX; |
| | | depositShopRata = getShopRevenueShare(depositShop, "localDeposit", cityId, fallbackFieldA); |
| | | } |
| | | |
| | | // 计算薪酬(分):totalAmount 为分,rata 为比例值(如 0.15 表示 15%) |
| | | // 取件门店占比 |
| | | BigDecimal takeShopRata = BigDecimal.ZERO; |
| | | if (isRemote && takeShop != null) { |
| | | boolean takeIsCompany = Constants.equalsInteger(takeShop.getCompanyType(), Constants.ONE); |
| | | int fallbackFieldA = takeIsCompany ? Constants.TWO : Constants.THREE; |
| | | takeShopRata = getShopRevenueShare(takeShop, "remoteTake", cityId, fallbackFieldA); |
| | | } |
| | | |
| | | // 计算薪酬(分) |
| | | long driverFee = new BigDecimal(totalAmount).multiply(driverRata).longValue(); |
| | | long depositShopFee = new BigDecimal(totalAmount).multiply(depositShopRata).longValue(); |
| | | long takeShopFee = new BigDecimal(totalAmount).multiply(takeShopRata).longValue(); |
| | |
| | | * 从 pricing_rule 表获取分成比例(type=4) |
| | | * |
| | | * @param cityId 城市主键 |
| | | * @param fieldA 类型:0=企业寄, 1=个人寄, 2=企业取, 3=个人取, 4=配送员 |
| | | * @param fieldA 类型:0=异地企业寄, 1=异地个人寄, 2=异地企业取, 3=异地个人取, 4=配送员, 5=就地企业存, 6=就地个人存 |
| | | * @return 分成比例(如 0.15 表示 15%) |
| | | */ |
| | | private BigDecimal getRevenueShareRata(Integer cityId, int fieldA) { |
| | |
| | | .eq(PricingRule::getFieldA, String.valueOf(fieldA)) |
| | | .last("limit 1")); |
| | | if (rule != null && StringUtils.isNotBlank(rule.getFieldB())) { |
| | | // fieldB 存储的是百分比整数(如15表示15%),转换为小数比例(0.15) |
| | | // fieldB 存储的是百分比数字(如15表示15%),转换为小数比例(0.15) |
| | | return new BigDecimal(rule.getFieldB()).divide(new BigDecimal("100"), 4, BigDecimal.ROUND_HALF_UP); |
| | | } |
| | | return BigDecimal.ZERO; |
| | | } |
| | | |
| | | /** |
| | | * 获取门店收益占比:优先从门店 revenueShareConfig 取,无则兜底城市 pricing_rule |
| | | * |
| | | * @param shop 门店信息 |
| | | * @param jsonKey revenueShareConfig 中的键名 |
| | | * @param cityId 城市主键(兜底用) |
| | | * @param fallbackFieldA 兜底 pricing_rule fieldA 值 |
| | | * @return 分成比例 |
| | | */ |
| | | private BigDecimal getShopRevenueShare(ShopInfo shop, String jsonKey, Integer cityId, int fallbackFieldA) { |
| | | if (shop != null && StringUtils.isNotBlank(shop.getRevenueShareConfig())) { |
| | | try { |
| | | JSONObject config = JSONObject.parseObject(shop.getRevenueShareConfig()); |
| | | if (config != null && config.containsKey(jsonKey)) { |
| | | Double value = config.getDouble(jsonKey); |
| | | if (value != null) { |
| | | return new BigDecimal(value).divide(new BigDecimal("100"), 4, BigDecimal.ROUND_HALF_UP); |
| | | } |
| | | } |
| | | } catch (Exception ignored) { |
| | | } |
| | | } |
| | | return getRevenueShareRata(cityId, fallbackFieldA); |
| | | } |
| | | |
| | | @Override |
| | |
| | | .eq(status != null, Orders::getStatus, status) |
| | | .in(statusList != null, Orders::getStatus, statusList) |
| | | .orderByDesc(Orders::getCreateTime); |
| | | // 关键词搜索:收件人/收件人电话模糊、订单号精准 |
| | | if (model != null && StringUtils.isNotBlank(model.getKeyword())) { |
| | | String kw = model.getKeyword().trim(); |
| | | wrapper.and(w -> w.like(Orders::getTakeUser, kw) |
| | | .or().like(Orders::getTakePhone, kw) |
| | | .or().eq(Orders::getCode, kw)); |
| | | } |
| | | |
| | | IPage<Orders> orderPage = ordersMapper.selectJoinPage(p, Orders.class, wrapper); |
| | | List<MyOrderVO> voList = new ArrayList<>(); |
| | |
| | | } |
| | | |
| | | wrapper.eq(status != null, Orders::getStatus, status) |
| | | .in(statusList != null && !Constants.equalsInteger(combinedStatus, Constants.SEVEN), Orders::getStatus, statusList) |
| | | .orderByDesc(Orders::getId); |
| | | .in(statusList != null && !Constants.equalsInteger(combinedStatus, Constants.SEVEN), Orders::getStatus, statusList); |
| | | if(Objects.nonNull(model.getCombinedStatus())&&Constants.equalsInteger(model.getCombinedStatus(),Constants.OrderCombinedStatus.finished.getKey())){ |
| | | wrapper.orderByDesc(Orders::getFinishTime); |
| | | }else{ |
| | | wrapper.orderByDesc(Orders::getId); |
| | | } |
| | | // 关键词搜索:收件人/收件人电话模糊、订单号精准 |
| | | MyOrderDTO shopModel = pageWrap.getModel(); |
| | | if (shopModel != null && StringUtils.isNotBlank(shopModel.getKeyword())) { |
| | | String kw = shopModel.getKeyword().trim(); |
| | | wrapper.and(w -> w.like(Orders::getTakeUser, kw) |
| | | .or().like(Orders::getTakePhone, kw) |
| | | .or().eq(Orders::getCode, kw)); |
| | | } |
| | | |
| | | IPage<Orders> orderPage = ordersMapper.selectJoinPage(p, Orders.class, wrapper); |
| | | List<MyOrderVO> voList = new ArrayList<>(); |
| | |
| | | order.setWxExternalNo(wxTradeNo); |
| | | order.setPayAmount(order.getTotalAmount()); |
| | | order.setUpdateTime(now); |
| | | // 计算店铺订单序号:当前存件门店当天已支付订单数 + 1 |
| | | Date todayStart = DateUtil.getStartOfDay(now); |
| | | Long currentCount = ordersMapper.selectCount(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getDepositShopId, order.getDepositShopId()) |
| | | .eq(Orders::getPayStatus, Constants.ONE) |
| | | .ge(Orders::getPayTime, todayStart) |
| | | .eq(Orders::getDeleted, Constants.ZERO)); |
| | | order.setAutoNum(currentCount + 1); |
| | | // 生成会员核销码 |
| | | order.setMemberVerifyCode(generateVerifyCode()); |
| | | // 异地寄存:计算预计送达时间 |
| | |
| | | otherOrders.setUpdateTime(now); |
| | | otherOrdersMapper.updateById(otherOrders); |
| | | |
| | | // 4. 查询门店信息(通过注册会员主键关联) |
| | | // 4. 查询变更版本门店信息(通过注册会员主键关联) |
| | | ShopInfo shopInfo = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda() |
| | | .eq(ShopInfo::getRegionMemberId, otherOrders.getMemberId()) |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .eq(ShopInfo::getVersionType, Constants.ONE) |
| | | .last("limit 1")); |
| | | if (shopInfo == null) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "门店不存在"); |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "门店变更记录不存在"); |
| | | } |
| | | // 5. 更新门店状态:已支付押金 |
| | | shopInfo.setAuditStatus(Constants.THREE); // 3=已支付押金 |
| | | // 5. 更新变更版本支付状态 |
| | | Member member = memberMapper.selectById(otherOrders.getMemberId()); |
| | | shopInfo.setAuditStatus(Constants.THREE); |
| | | shopInfo.setPayStatus(Constants.ONE); |
| | | shopInfo.setPayTime(now); |
| | | shopInfo.setWxExternalNo(wxTradeNo); |
| | | shopInfo.setCode(otherOrders.getCode()); |
| | | Member member = memberMapper.selectById(otherOrders.getMemberId()); |
| | | if (member != null) { |
| | | shopInfo.setPayMemberOpenId(member.getOpenid()); |
| | | } |
| | | shopInfo.setUpdateTime(now); |
| | | shopInfoMapper.updateById(shopInfo); |
| | | |
| | | // 6. 同步更新正式版本状态为已支付押金 |
| | | if (shopInfo.getRelationShopId() != null) { |
| | | ShopInfo officialShop = shopInfoMapper.selectById(shopInfo.getRelationShopId()); |
| | | if (officialShop != null) { |
| | | officialShop.setAuditStatus(Constants.THREE); |
| | | officialShop.setUpdateTime(now); |
| | | shopInfoMapper.updateById(officialShop); |
| | | } |
| | | } |
| | | |
| | | // 短信通知门店:成功入驻 |
| | | String rawPassword = shopInfo.getTelephone() != null && shopInfo.getTelephone().length() >= 6 |
| | |
| | | } |
| | | order.setMemberVerifyCode(generateVerifyCode()); |
| | | ordersMapper.updateById(order); |
| | | // 寄存时图片必填 |
| | | if (images == null || images.isEmpty()) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "请上传寄存图片"); |
| | | } |
| | | // 保存寄存图片(obj_type=2 订单寄存图片,最多3张) |
| | | saveVerifyImages(order.getId(), images, Constants.FileType.ORDER_DEPOSIT.getKey(), shopId); |
| | | // 记录订单日志 |
| | |
| | | order.setStatus(Constants.OrderStatus.finished.getStatus()); |
| | | order.setConfirmArriveTime(now); |
| | | ordersMapper.updateById(order); |
| | | // 就地寄存(type=0)取件时图片不必填,其他类型取件必填 |
| | | if (!Constants.equalsInteger(order.getType(), Constants.ZERO)) { |
| | | if (images == null || images.isEmpty()) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "请上传取件图片"); |
| | | } |
| | | } |
| | | // 订单完成,释放核销码 |
| | | String verifyCode = order.getMemberVerifyCode(); |
| | | if (StringUtils.isNotBlank(verifyCode)) { |
| | |
| | | return "司机已取件,正运往目的地"; |
| | | } |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.arrived.getStatus())) { |
| | | if(Constants.equalsInteger(order.getType(),Constants.ZERO)){ |
| | | return "行李已寄存,请凭取件码前往指定门店取件~"; |
| | | }else{ |
| | | return "行李已送达服务点,请及时前往取件"; |
| | | } |
| | | |
| | | } |
| | | if (Constants.equalsInteger(status, Constants.OrderStatus.finished.getStatus())) { |
| | | if (Constants.equalsInteger(order.getCommentStatus(), Constants.ONE)) { |
| | |
| | | "time", String.valueOf(noGrabMinutes)); |
| | | } |
| | | // 标记已通知 + 记录通知时间 |
| | | order.setPlatformSmsNotified(Constants.ONE); |
| | | order.setPlatformSmsNotifiedTime(now); |
| | | order.setUpdateTime(now); |
| | | ordersMapper.updateById(order); |
| | |
| | | if (StringUtils.isBlank(phone)) { |
| | | return; |
| | | } |
| | | if (!smsNotify.isEnabled()) { |
| | | return; |
| | | } |
| | | String content = smsNotify.format(paramPairs); |
| | | try { |
| | | JSONObject templateParam = new JSONObject(); |
| | |
| | | } |
| | | } |
| | | |
| | | //序号 |
| | | String sort = Constants.formatIntegerNum(shopId)+"-"+orders.getId(); |
| | | //序号:商铺ID-日期-自增长序号(如 32-06-001) |
| | | String dateStr = new SimpleDateFormat("dd").format(orders.getPayTime() != null ? orders.getPayTime() : new Date()); |
| | | String autoNumStr = String.format("%03d", orders.getAutoNum() != null ? orders.getAutoNum() : 0); |
| | | String sort = shopId + "-" + dateStr + "-" + autoNumStr; |
| | | // String content = printService.getPrintContent(shop.getName(), detailList, userInfo, orders.getCode(), orders.getRemark(), |
| | | String content = printService.getPrintContent(shop.getName(), detailList, userInfo, orders.getCode(), sort, |
| | | orders.getTakeLocationRemark(), |
| | |
| | | JPushUtil.sendByAliases(aliases, title, content, extras); |
| | | } |
| | | |
| | | @Override |
| | | public int notifyArrivalPickUp() { |
| | | String timeStr = operationConfigBiz.getConfig().getArrivalPickUpTime(); |
| | | if (StringUtils.isBlank(timeStr)) { |
| | | return 0; |
| | | } |
| | | int minutes; |
| | | try { |
| | | minutes = Integer.parseInt(timeStr); |
| | | } catch (NumberFormatException e) { |
| | | log.warn("即将到达取件时间配置异常: {}", timeStr); |
| | | return 0; |
| | | } |
| | | if (minutes <= 0) { |
| | | return 0; |
| | | } |
| | | // 计算时间窗口:当前时间 + minutes 就是"即将到达"的临界点 |
| | | Date now = new Date(); |
| | | Date threshold = new Date(now.getTime() + (long) minutes * 60 * 1000); |
| | | // 查询:status=5、未通知、就地寄存 or 异地(有取件门店)、预计取件时间在 now~threshold 之间 |
| | | List<Orders> orders = ordersMapper.selectList(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getStatus, Constants.OrderStatus.arrived.getStatus()) |
| | | .eq(Orders::getPayStatus, Constants.ONE) |
| | | .eq(Orders::getDeleted, Constants.ZERO) |
| | | .and(w -> w |
| | | .eq(Orders::getType, Constants.ZERO) |
| | | .or(w2 -> w2.eq(Orders::getType, Constants.ONE).isNotNull(Orders::getTakeShopId)) |
| | | ) |
| | | .ne(Orders::getPickUpNotifyStatus, Constants.ONE) |
| | | .isNotNull(Orders::getExpectedTakeTime) |
| | | .ge(Orders::getExpectedTakeTime, now) |
| | | .le(Orders::getExpectedTakeTime, threshold)); |
| | | if (orders == null || orders.isEmpty()) { |
| | | return 0; |
| | | } |
| | | int count = 0; |
| | | for (Orders order : orders) { |
| | | Member member = memberMapper.selectById(order.getMemberId()); |
| | | if (member != null && StringUtils.isNotBlank(member.getTelephone())) { |
| | | sendSmsNotify(member.getTelephone(), Constants.SmsNotify.MEMBER_TIME_OUT, |
| | | "orderNo", order.getCode()); |
| | | } |
| | | order.setPickUpNotifyStatus(Constants.ONE); |
| | | ordersMapper.updateById(order); |
| | | count++; |
| | | } |
| | | return count; |
| | | } |
| | | |
| | | @Override |
| | | public Boolean checkOperationRadius(Integer orderId, Integer userId, Integer userType, Double lng, Double lat) { |
| | | String radiusStr = operationConfigBiz.getConfig().getOperationRadius(); |
| | | if (StringUtils.isBlank(radiusStr)) { |
| | | return true; |
| | | } |
| | | double radiusM; |
| | | try { |
| | | radiusM = Double.parseDouble(radiusStr); |
| | | } catch (NumberFormatException e) { |
| | | return true; |
| | | } |
| | | if (radiusM <= 0) { |
| | | return true; |
| | | } |
| | | Orders order = ordersMapper.selectById(orderId); |
| | | if (order == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "订单不存在"); |
| | | } |
| | | BigDecimal targetLat; |
| | | BigDecimal targetLgt; |
| | | if (Constants.equalsInteger(userType, Constants.ZERO)) { |
| | | // 门店操作 |
| | | if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.waitDeposit.getStatus())) { |
| | | // status=1 门店寄存核验 |
| | | if (!Constants.equalsInteger(order.getDepositShopId(), userId)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单"); |
| | | } |
| | | targetLat = order.getDepositLat(); |
| | | targetLgt = order.getDepositLgt(); |
| | | } else if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.arrived.getStatus())) { |
| | | // status=5 门店完成核销 |
| | | if (Constants.equalsInteger(order.getType(), Constants.ZERO)) { |
| | | // 就地存取 → 对比存件门店 |
| | | if (!Constants.equalsInteger(order.getDepositShopId(), userId)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单"); |
| | | } |
| | | targetLat = order.getDepositLat(); |
| | | targetLgt = order.getDepositLgt(); |
| | | } else { |
| | | // 异地存取 → 对比取件门店 |
| | | if (!Constants.equalsInteger(order.getTakeShopId(), userId)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单"); |
| | | } |
| | | targetLat = order.getTakeLat(); |
| | | targetLgt = order.getTakeLgt(); |
| | | } |
| | | } else { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "订单状态不允许此操作"); |
| | | } |
| | | } else if (Constants.equalsInteger(userType, Constants.ONE)) { |
| | | // 司机操作 |
| | | if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.deposited.getStatus())) { |
| | | // status=2 司机取件 |
| | | if (!Constants.equalsInteger(order.getAcceptDriver(), userId)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单"); |
| | | } |
| | | targetLat = order.getDepositLat(); |
| | | targetLgt = order.getDepositLgt(); |
| | | } else if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.delivering.getStatus())) { |
| | | // status=4 司机送达 |
| | | if (!Constants.equalsInteger(order.getAcceptDriver(), userId)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单"); |
| | | } |
| | | targetLat = order.getTakeLat(); |
| | | targetLgt = order.getTakeLgt(); |
| | | } else { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "订单状态不允许此操作"); |
| | | } |
| | | } else { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "用户类型不合法"); |
| | | } |
| | | if (targetLat == null || targetLgt == null) { |
| | | return true; |
| | | } |
| | | double distanceKm = GeoUtils.haversineDistance(lat, lng, targetLat.doubleValue(), targetLgt.doubleValue()); |
| | | return distanceKm * 1000 <= radiusM; |
| | | } |
| | | |
| | | } |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void batchSaveRevenueShare(RevenueShareSaveDTO request) { |
| | | // 校验:必须包含 fieldType 0-4 各一条 |
| | | // 校验:必须包含 fieldType 0-6 各一条 |
| | | Set<Integer> fieldTypes = request.getItems().stream() |
| | | .map(RevenueShareItemDTO::getFieldType) |
| | | .collect(Collectors.toSet()); |
| | | if (fieldTypes.size() != Constants.FIVE) { |
| | | if (fieldTypes.size() != Constants.SEVEN) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), |
| | | "必须包含企业寄(0)、个人寄(1)、企业取(2)、个人取(3)、配送员(4)共5条数据"); |
| | | "必须包含异地企业寄(0)、异地个人寄(1)、异地企业取(2)、异地个人取(3)、配送员(4)、就地企业存(5)、就地个人存(6)共7条数据"); |
| | | } |
| | | for (int i = 0; i <= Constants.FOUR; i++) { |
| | | for (int i = 0; i <= Constants.SIX; i++) { |
| | | if (!fieldTypes.contains(i)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), |
| | | "缺少类型" + i + "的数据"); |
| | |
| | | Map<String, PricingRule> existingMap = rules.stream() |
| | | .collect(Collectors.toMap(PricingRule::getFieldA, r -> r)); |
| | | |
| | | // 固定返回5条:企业寄(0)、个人寄(1)、企业取(2)、个人取(3)、配送员(4) |
| | | // 固定返回7条:异地企业寄(0)、异地个人寄(1)、异地企业取(2)、异地个人取(3)、配送员(4)、就地企业存(5)、就地个人存(6) |
| | | List<RevenueShareVO> result = new ArrayList<>(); |
| | | String[] typeNames = {"企业寄", "个人寄", "企业取", "个人取", "配送员"}; |
| | | for (int i = 0; i <= Constants.FOUR; i++) { |
| | | String[] typeNames = {"异地企业寄件", "异地个人寄件", "异地企业取件", "异地个人取件", "配送员", "就地企业存件", "就地个人存件"}; |
| | | for (int i = 0; i <= Constants.SIX; i++) { |
| | | RevenueShareVO vo = new RevenueShareVO(); |
| | | vo.setFieldType(i); |
| | | vo.setFieldTypeName(typeNames[i]); |
| | |
| | | public void applyShop(ShopApplyDTO request) { |
| | | Member member = memberMapper.selectById(request.getMemberId()); |
| | | |
| | | // 根据类型校验附件 |
| | | validateCompanyTypeFields(request); |
| | | |
| | | // 2. 根据类型校验附件 |
| | | Date now = new Date(); |
| | | |
| | | // 查询该会员最新的变更版本记录 |
| | | QueryWrapper<ShopInfo> changeQw = new QueryWrapper<>(); |
| | | changeQw.lambda() |
| | | .eq(ShopInfo::getRegionMemberId, member.getId()) |
| | | .eq(ShopInfo::getVersionType, Constants.ONE) |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .orderByDesc(ShopInfo::getCreateTime) |
| | | .last("limit 1"); |
| | | ShopInfo changeVersion = shopInfoMapper.selectOne(changeQw); |
| | | |
| | | if (changeVersion == null) { |
| | | // 首次申请:创建正式版本 + 变更版本 |
| | | checkTelephoneUnique(request.getTelephone(), null); |
| | | |
| | | String rawPassword = generateDefaultPassword(request.getTelephone()); |
| | | String salt = RandomStringUtils.randomAlphabetic(6); |
| | | String encryptedPassword = Utils.Secure.encryptPassword(rawPassword, salt); |
| | | |
| | | // 正式版本 |
| | | ShopInfo official = new ShopInfo(); |
| | | applyFieldsFromRequest(official, request, member, encryptedPassword, salt, now); |
| | | official.setVersionType(Constants.ZERO); |
| | | official.setAuditStatus(Constants.ZERO); |
| | | official.setStatus(Constants.ZERO); |
| | | official.setDeleted(Constants.ZERO); |
| | | official.setCreateTime(now); |
| | | official.setUpdateTime(now); |
| | | official.setRegionMemberId(member.getId()); |
| | | setDepositAmountFromPricingRule(official); |
| | | setDefaultDeliveryRange(official); |
| | | shopInfoMapper.insert(official); |
| | | |
| | | // 保存正式版本附件 |
| | | saveShopAttachments(official.getId(), request, now); |
| | | |
| | | // 创建变更版本(拷贝正式版本数据) |
| | | createChangeVersion(official, official.getId(), now); |
| | | } else if (Constants.equalsInteger(changeVersion.getAuditStatus(), Constants.ONE)) { |
| | | // 审批通过待支付押金 |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "门店已审批通过,请完成押金支付"); |
| | | } else if (Constants.equalsInteger(changeVersion.getAuditStatus(), Constants.THREE)) { |
| | | // 最新变更版本已支付押金(status=3):生成新的变更版本 |
| | | Integer relationShopId = changeVersion.getRelationShopId(); |
| | | |
| | | // 校验手机号唯一性(排除正式版本和变更版本) |
| | | checkTelephoneUnique(request.getTelephone(), relationShopId); |
| | | |
| | | String rawPassword = generateDefaultPassword(request.getTelephone()); |
| | | String salt = RandomStringUtils.randomAlphabetic(6); |
| | | String encryptedPassword = Utils.Secure.encryptPassword(rawPassword, salt); |
| | | |
| | | ShopInfo newChange = new ShopInfo(); |
| | | applyFieldsFromRequest(newChange, request, member, encryptedPassword, salt, now); |
| | | newChange.setVersionType(Constants.ONE); |
| | | newChange.setRelationShopId(relationShopId); |
| | | newChange.setAuditStatus(Constants.ZERO); |
| | | newChange.setStatus(Constants.ZERO); |
| | | newChange.setDeleted(Constants.ZERO); |
| | | newChange.setCreateTime(now); |
| | | newChange.setUpdateTime(now); |
| | | newChange.setRegionMemberId(member.getId()); |
| | | setDepositAmountFromPricingRule(newChange); |
| | | shopInfoMapper.insert(newChange); |
| | | |
| | | // 保存新变更版本附件 |
| | | saveShopAttachments(newChange.getId(), request, now); |
| | | } else { |
| | | // 最新变更版本 status=0(待审批) 或 2(被驳回):直接更新 |
| | | Integer relationShopId = changeVersion.getRelationShopId(); |
| | | |
| | | // 校验手机号唯一性 |
| | | checkTelephoneUnique(request.getTelephone(), relationShopId); |
| | | |
| | | String rawPassword = generateDefaultPassword(request.getTelephone()); |
| | | String salt = RandomStringUtils.randomAlphabetic(6); |
| | | String encryptedPassword = Utils.Secure.encryptPassword(rawPassword, salt); |
| | | |
| | | applyFieldsFromRequest(changeVersion, request, member, encryptedPassword, salt, now); |
| | | changeVersion.setAuditStatus(Constants.ZERO); |
| | | changeVersion.setAuditRemark(null); |
| | | changeVersion.setAuditTime(null); |
| | | changeVersion.setAuditUserId(null); |
| | | changeVersion.setUpdateTime(now); |
| | | setDepositAmountFromPricingRule(changeVersion); |
| | | shopInfoMapper.updateById(changeVersion); |
| | | |
| | | // 删除旧附件 + 保存新附件 |
| | | deleteShopAttachments(changeVersion.getId()); |
| | | saveShopAttachments(changeVersion.getId(), request, now); |
| | | } |
| | | } |
| | | |
| | | private void validateCompanyTypeFields(ShopApplyDTO request) { |
| | | if (Constants.equalsInteger(request.getCompanyType(), Constants.ZERO)) { |
| | | // 个人类型:必须上传劳动合同和社保证明 |
| | | if (CollectionUtils.isEmpty(request.getLaborContractImgs())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "个人类型必须上传有效劳动合同"); |
| | | } |
| | |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "个人类型必须上传社保缴纳证明"); |
| | | } |
| | | } else if (Constants.equalsInteger(request.getCompanyType(), Constants.ONE)) { |
| | | // 企业类型:必须填写法人信息和营业执照 |
| | | if (StringUtils.isBlank(request.getBusinessImg())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "企业类型必须上传营业执照"); |
| | | } |
| | |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "企业类型必须填写法人身份证号码"); |
| | | } |
| | | } |
| | | |
| | | Date now = new Date(); |
| | | String rawPassword = generateDefaultPassword(request.getTelephone()); |
| | | String salt = RandomStringUtils.randomAlphabetic(6); |
| | | String encryptedPassword = Utils.Secure.encryptPassword(rawPassword, salt); |
| | | |
| | | // 3. 查询该会员是否已有门店记录 |
| | | QueryWrapper<ShopInfo> existQw = new QueryWrapper<>(); |
| | | existQw.lambda() |
| | | .eq(ShopInfo::getRegionMemberId, member.getId()) |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .last("limit 1"); |
| | | ShopInfo existing = shopInfoMapper.selectOne(existQw); |
| | | |
| | | Integer shopId; |
| | | if (existing != null) { |
| | | // 校验状态:只有待审批(0)和被驳回(2)可修改 |
| | | if (!Constants.equalsInteger(existing.getAuditStatus(), Constants.TWO)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "当前门店状态不允许修改"); |
| | | } |
| | | // 校验openid匹配:当前登录会员的openid必须与门店的openid一致 |
| | | if (existing.getOpenid() != null && !existing.getOpenid().equals(member.getOpenid())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权限操作当前门店信息"); |
| | | } |
| | | // 校验手机号唯一性(排除自身) |
| | | if (!request.getTelephone().equals(existing.getTelephone())) { |
| | | checkTelephoneUnique(request.getTelephone(), existing.getId()); |
| | | } |
| | | // 更新 |
| | | existing.setCompanyType(request.getCompanyType()); |
| | | existing.setName(request.getName()); |
| | | existing.setTelephone(request.getTelephone()); |
| | | existing.setLinkName(request.getLinkName()); |
| | | existing.setLinkPhone(request.getLinkPhone()); |
| | | existing.setIdcard(request.getIdcard()); |
| | | existing.setAreaId(request.getAreaId()); |
| | | existing.setLongitude(request.getLongitude()); |
| | | existing.setLatitude(request.getLatitude()); |
| | | existing.setAddress(request.getAddress()); |
| | | existing.setIdcardImg(request.getIdcardImg()); |
| | | existing.setIdcardImgBack(request.getIdcardImgBack()); |
| | | existing.setBusinessImg(request.getBusinessImg()); |
| | | existing.setLegalPersonName(request.getLegalPersonName()); |
| | | existing.setLegalPersonPhone(request.getLegalPersonPhone()); |
| | | existing.setLegalPersonCard(request.getLegalPersonCard()); |
| | | existing.setPassword(encryptedPassword); |
| | | existing.setSalt(salt); |
| | | existing.setAliAccount(request.getAliAccount()); |
| | | existing.setAliName(request.getAliName()); |
| | | existing.setUpdateTime(now); |
| | | existing.setAuditRemark(null); |
| | | existing.setAuditTime(null); |
| | | existing.setAuditUserId(null); |
| | | existing.setAuditStatus(Constants.ZERO); |
| | | // 读取押金金额 |
| | | setDepositAmountFromPricingRule(existing); |
| | | shopInfoMapper.updateById(existing); |
| | | shopId = existing.getId(); |
| | | } else { |
| | | // 1. 校验门店手机号唯一性(shop_info.telephone) |
| | | checkTelephoneUnique(request.getTelephone(), null); |
| | | // 新建 |
| | | ShopInfo shopInfo = new ShopInfo(); |
| | | shopInfo.setCompanyType(request.getCompanyType()); |
| | | shopInfo.setName(request.getName()); |
| | | shopInfo.setTelephone(request.getTelephone()); |
| | | shopInfo.setLinkName(request.getLinkName()); |
| | | shopInfo.setLinkPhone(request.getLinkPhone()); |
| | | shopInfo.setIdcard(request.getIdcard()); |
| | | shopInfo.setAreaId(request.getAreaId()); |
| | | shopInfo.setLongitude(request.getLongitude()); |
| | | shopInfo.setLatitude(request.getLatitude()); |
| | | shopInfo.setAddress(request.getAddress()); |
| | | shopInfo.setIdcardImg(request.getIdcardImg()); |
| | | shopInfo.setIdcardImgBack(request.getIdcardImgBack()); |
| | | shopInfo.setBusinessImg(request.getBusinessImg()); |
| | | shopInfo.setLegalPersonName(request.getLegalPersonName()); |
| | | shopInfo.setLegalPersonPhone(request.getLegalPersonPhone()); |
| | | shopInfo.setLegalPersonCard(request.getLegalPersonCard()); |
| | | shopInfo.setPassword(encryptedPassword); |
| | | shopInfo.setSalt(salt); |
| | | shopInfo.setAliAccount(request.getAliAccount()); |
| | | shopInfo.setAliName(request.getAliName()); |
| | | shopInfo.setAuditStatus(Constants.ZERO); |
| | | shopInfo.setStatus(Constants.ZERO); |
| | | shopInfo.setDeleted(Constants.ZERO); |
| | | shopInfo.setCreateTime(now); |
| | | shopInfo.setUpdateTime(now); |
| | | shopInfo.setRegionMemberId(member.getId()); |
| | | // 读取押金金额 |
| | | setDepositAmountFromPricingRule(shopInfo); |
| | | // 设置默认配送范围 |
| | | setDefaultDeliveryRange(shopInfo); |
| | | shopInfoMapper.insert(shopInfo); |
| | | shopId = shopInfo.getId(); |
| | | } |
| | | |
| | | // 4. 删除旧附件记录 |
| | | private void applyFieldsFromRequest(ShopInfo shop, ShopApplyDTO request, Member member, |
| | | String password, String salt, Date now) { |
| | | shop.setCompanyType(request.getCompanyType()); |
| | | shop.setName(request.getName()); |
| | | shop.setTelephone(request.getTelephone()); |
| | | shop.setLinkName(request.getLinkName()); |
| | | shop.setLinkPhone(request.getLinkPhone()); |
| | | shop.setIdcard(request.getIdcard()); |
| | | shop.setAreaId(request.getAreaId()); |
| | | shop.setLongitude(request.getLongitude()); |
| | | shop.setLatitude(request.getLatitude()); |
| | | shop.setAddress(request.getAddress()); |
| | | shop.setIdcardImg(request.getIdcardImg()); |
| | | shop.setIdcardImgBack(request.getIdcardImgBack()); |
| | | shop.setBusinessImg(request.getBusinessImg()); |
| | | shop.setLegalPersonName(request.getLegalPersonName()); |
| | | shop.setLegalPersonPhone(request.getLegalPersonPhone()); |
| | | shop.setLegalPersonCard(request.getLegalPersonCard()); |
| | | shop.setPassword(password); |
| | | shop.setSalt(salt); |
| | | shop.setAliAccount(request.getAliAccount()); |
| | | shop.setAliName(request.getAliName()); |
| | | shop.setRevenueShareConfig(buildRevenueShareConfig(request.getLocalDeposit(), request.getRemoteDeposit(), request.getRemoteTake())); |
| | | shop.setOpenid(member.getOpenid()); |
| | | } |
| | | |
| | | private void saveShopAttachments(Integer shopId, ShopApplyDTO request, Date now) { |
| | | saveMultifileList(shopId, Constants.FileType.STORE_FRONT.getKey(), request.getStoreFrontImgs(), now); |
| | | saveMultifileList(shopId, Constants.FileType.STORE_INTERIOR.getKey(), request.getStoreInteriorImgs(), now); |
| | | saveMultifileList(shopId, Constants.FileType.OTHER_MATERIAL.getKey(), request.getOtherMaterialImgs(), now); |
| | | saveMultifileList(shopId, Constants.FileType.LABOR_CONTRACT.getKey(), request.getLaborContractImgs(), now); |
| | | saveMultifileList(shopId, Constants.FileType.SOCIAL_SECURITY.getKey(), request.getSocialSecurityImgs(), now); |
| | | } |
| | | |
| | | private void deleteShopAttachments(Integer shopId) { |
| | | multifileMapper.delete(new QueryWrapper<Multifile>().lambda() |
| | | .eq(Multifile::getObjId, shopId) |
| | | .in(Multifile::getObjType, |
| | |
| | | Constants.FileType.OTHER_MATERIAL.getKey(), |
| | | Constants.FileType.LABOR_CONTRACT.getKey(), |
| | | Constants.FileType.SOCIAL_SECURITY.getKey())); |
| | | |
| | | // 5. 保存新附件记录 |
| | | saveMultifileList(shopId, Constants.FileType.STORE_FRONT.getKey(), request.getStoreFrontImgs(), now); |
| | | saveMultifileList(shopId, Constants.FileType.STORE_INTERIOR.getKey(), request.getStoreInteriorImgs(), now); |
| | | saveMultifileList(shopId, Constants.FileType.OTHER_MATERIAL.getKey(), request.getOtherMaterialImgs(), now); |
| | | saveMultifileList(shopId, Constants.FileType.LABOR_CONTRACT.getKey(), request.getLaborContractImgs(), now); |
| | | saveMultifileList(shopId, Constants.FileType.SOCIAL_SECURITY.getKey(), request.getSocialSecurityImgs(), now); |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | @Override |
| | | public ShopDetailVO getMyShop(Integer memberId) { |
| | | // 查询最新的变更版本 |
| | | QueryWrapper<ShopInfo> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(ShopInfo::getRegionMemberId, memberId) |
| | | .eq(ShopInfo::getVersionType, Constants.ONE) |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .orderByDesc(ShopInfo::getCreateTime) |
| | | .last("limit 1"); |
| | | ShopInfo shopInfo = shopInfoMapper.selectOne(qw); |
| | | if (shopInfo == null) { |
| | | // 无变更版本则查正式版本 |
| | | QueryWrapper<ShopInfo> officialQw = new QueryWrapper<>(); |
| | | officialQw.lambda() |
| | | .eq(ShopInfo::getRegionMemberId, memberId) |
| | | .eq(ShopInfo::getVersionType, Constants.ZERO) |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .last("limit 1"); |
| | | shopInfo = shopInfoMapper.selectOne(officialQw); |
| | | } |
| | | if (shopInfo == null) { |
| | | return null; |
| | | } |
| | |
| | | || (auditDTO.getAuditStatus() != 0 && auditDTO.getAuditStatus() != 1)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "审批状态参数错误"); |
| | | } |
| | | ShopInfo shopInfo = shopInfoMapper.selectById(auditDTO.getId()); |
| | | if (shopInfo == null || Constants.equalsInteger(shopInfo.getDeleted(), Constants.ONE)) { |
| | | // 审批的是变更版本 |
| | | ShopInfo changeVersion = shopInfoMapper.selectById(auditDTO.getId()); |
| | | if (changeVersion == null || Constants.equalsInteger(changeVersion.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | if (!Constants.equalsInteger(shopInfo.getAuditStatus(), Constants.ZERO)) { |
| | | if (!Constants.equalsInteger(changeVersion.getAuditStatus(), Constants.ZERO)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "当前状态不允许审批"); |
| | | } |
| | | |
| | | Date now = new Date(); |
| | | // auditDTO.auditStatus: 0=通过 → auditStatus=1, 1=驳回 → auditStatus=2 |
| | | // auditDTO.auditStatus: 0=通过 → 1, 1=驳回 → 2 |
| | | Integer newAuditStatus = Constants.equalsInteger(auditDTO.getAuditStatus(), Constants.ZERO) ? Constants.ONE : Constants.TWO; |
| | | shopInfo.setAuditStatus(newAuditStatus); |
| | | shopInfo.setAuditTime(now); |
| | | shopInfo.setAuditRemark(auditDTO.getAuditRemark()); |
| | | shopInfo.setAuditUserId(auditDTO.getAuditUser()); |
| | | shopInfo.setUpdateTime(now); |
| | | // 审批通过时,校验城市pricing_rule配置,读取押金金额 |
| | | |
| | | // 查找正式版本 |
| | | Integer officialId = changeVersion.getRelationShopId(); |
| | | ShopInfo official = officialId != null ? shopInfoMapper.selectById(officialId) : null; |
| | | boolean hasPaidOfficial = official != null |
| | | && Constants.equalsInteger(official.getAuditStatus(), Constants.THREE); |
| | | |
| | | if (!hasPaidOfficial) { |
| | | // 场景1:不存在auditStatus=3的正式版本(首次审批) |
| | | changeVersion.setAuditStatus(newAuditStatus); |
| | | changeVersion.setAuditTime(now); |
| | | changeVersion.setAuditRemark(auditDTO.getAuditRemark()); |
| | | changeVersion.setAuditUserId(auditDTO.getAuditUser()); |
| | | changeVersion.setUpdateTime(now); |
| | | |
| | | if (Constants.equalsInteger(newAuditStatus, Constants.ONE)) { |
| | | // 1. 解析门店所在城市 |
| | | validateCityAndSetDeposit(changeVersion); |
| | | } |
| | | shopInfoMapper.updateById(changeVersion); |
| | | |
| | | // 同步更新正式版本审批状态 |
| | | if (official != null) { |
| | | official.setAuditStatus(newAuditStatus); |
| | | official.setAuditTime(now); |
| | | official.setAuditRemark(auditDTO.getAuditRemark()); |
| | | official.setAuditUserId(auditDTO.getAuditUser()); |
| | | official.setUpdateTime(now); |
| | | if (Constants.equalsInteger(newAuditStatus, Constants.ONE)) { |
| | | official.setDepositAmount(changeVersion.getDepositAmount()); |
| | | } |
| | | shopInfoMapper.updateById(official); |
| | | } |
| | | |
| | | // 短信通知 |
| | | sendAuditSms(changeVersion, newAuditStatus, auditDTO.getAuditRemark()); |
| | | } else { |
| | | // 场景2:存在auditStatus=3的正式版本(变更审批) |
| | | if (Constants.equalsInteger(newAuditStatus, Constants.ONE)) { |
| | | // 审批通过:变更版本直接标记auditStatus=3,同步数据到正式版本 |
| | | changeVersion.setAuditStatus(Constants.THREE); |
| | | changeVersion.setAuditTime(now); |
| | | changeVersion.setAuditRemark(auditDTO.getAuditRemark()); |
| | | changeVersion.setAuditUserId(auditDTO.getAuditUser()); |
| | | changeVersion.setUpdateTime(now); |
| | | shopInfoMapper.updateById(changeVersion); |
| | | |
| | | // 同步变更版本数据到正式版本 |
| | | syncChangeToOfficial(changeVersion, official, now); |
| | | } else { |
| | | // 审批驳回:仅标记变更版本状态 |
| | | changeVersion.setAuditStatus(Constants.TWO); |
| | | changeVersion.setAuditTime(now); |
| | | changeVersion.setAuditRemark(auditDTO.getAuditRemark()); |
| | | changeVersion.setAuditUserId(auditDTO.getAuditUser()); |
| | | changeVersion.setUpdateTime(now); |
| | | shopInfoMapper.updateById(changeVersion); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void validateCityAndSetDeposit(ShopInfo shopInfo) { |
| | | Areas area = areasBiz.resolveArea(shopInfo.getAreaId()); |
| | | if (area == null || area.getParentId() == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "门店区划信息异常,无法确定所在城市"); |
| | | } |
| | | Integer cityId = area.getParentId(); |
| | | |
| | | // 2. 校验 pricing_rule 配置(城市开通在押金支付完成后处理) |
| | | Areas cityArea = areasService.findById(cityId, Constants.ONE); |
| | | if (cityArea == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "城市信息不存在"); |
| | |
| | | "城市[" + cityArea.getName() + "]尚未开通,定价规则未配置完整:" + String.join(";", errors)); |
| | | } |
| | | } |
| | | |
| | | // 3. 从PricingRule读取押金金额(审批时更新) |
| | | setDepositAmountFromPricingRule(shopInfo); |
| | | } |
| | | shopInfoMapper.updateById(shopInfo); |
| | | |
| | | // 短信通知 |
| | | private void syncChangeToOfficial(ShopInfo changeVersion, ShopInfo official, Date now) { |
| | | official.setCompanyType(changeVersion.getCompanyType()); |
| | | official.setName(changeVersion.getName()); |
| | | official.setTelephone(changeVersion.getTelephone()); |
| | | official.setLinkName(changeVersion.getLinkName()); |
| | | official.setLinkPhone(changeVersion.getLinkPhone()); |
| | | official.setIdcard(changeVersion.getIdcard()); |
| | | official.setAreaId(changeVersion.getAreaId()); |
| | | official.setLongitude(changeVersion.getLongitude()); |
| | | official.setLatitude(changeVersion.getLatitude()); |
| | | official.setAddress(changeVersion.getAddress()); |
| | | official.setIdcardImg(changeVersion.getIdcardImg()); |
| | | official.setIdcardImgBack(changeVersion.getIdcardImgBack()); |
| | | official.setBusinessImg(changeVersion.getBusinessImg()); |
| | | official.setLegalPersonName(changeVersion.getLegalPersonName()); |
| | | official.setLegalPersonPhone(changeVersion.getLegalPersonPhone()); |
| | | official.setLegalPersonCard(changeVersion.getLegalPersonCard()); |
| | | official.setPassword(changeVersion.getPassword()); |
| | | official.setSalt(changeVersion.getSalt()); |
| | | official.setAliAccount(changeVersion.getAliAccount()); |
| | | official.setAliName(changeVersion.getAliName()); |
| | | official.setRevenueShareConfig(changeVersion.getRevenueShareConfig()); |
| | | official.setDepositAmount(changeVersion.getDepositAmount()); |
| | | official.setUpdateTime(now); |
| | | shopInfoMapper.updateById(official); |
| | | |
| | | // 同步附件:先删正式版本旧附件,再从变更版本拷贝 |
| | | deleteShopAttachments(official.getId()); |
| | | List<Multifile> changeFiles = multifileMapper.selectList(new QueryWrapper<Multifile>().lambda() |
| | | .eq(Multifile::getObjId, changeVersion.getId()) |
| | | .eq(Multifile::getIsdeleted, Constants.ZERO) |
| | | .in(Multifile::getObjType, |
| | | Constants.FileType.STORE_FRONT.getKey(), |
| | | Constants.FileType.STORE_INTERIOR.getKey(), |
| | | Constants.FileType.OTHER_MATERIAL.getKey(), |
| | | Constants.FileType.LABOR_CONTRACT.getKey(), |
| | | Constants.FileType.SOCIAL_SECURITY.getKey())); |
| | | for (Multifile f : changeFiles) { |
| | | Multifile copy = new Multifile(); |
| | | copy.setCreator(f.getCreator()); |
| | | copy.setCreateDate(now); |
| | | copy.setIsdeleted(Constants.ZERO); |
| | | copy.setName(f.getName()); |
| | | copy.setInfo(f.getInfo()); |
| | | copy.setObjId(official.getId()); |
| | | copy.setType(f.getType()); |
| | | copy.setObjType(f.getObjType()); |
| | | copy.setFileurl(f.getFileurl()); |
| | | copy.setSortnum(f.getSortnum()); |
| | | multifileMapper.insert(copy); |
| | | } |
| | | } |
| | | |
| | | private void sendAuditSms(ShopInfo shopInfo, Integer newAuditStatus, String auditRemark) { |
| | | if (Constants.equalsInteger(newAuditStatus, Constants.ONE)) { |
| | | // 审核通过 → 通知缴纳押金 |
| | | String depositMoney = shopInfo.getDepositAmount() != null |
| | | ? new java.math.BigDecimal(shopInfo.getDepositAmount()) |
| | | .divide(new java.math.BigDecimal(100), 2, java.math.RoundingMode.HALF_UP).toPlainString() : "0"; |
| | |
| | | "storeName", shopInfo.getName(), |
| | | "money", depositMoney); |
| | | } else if (Constants.equalsInteger(newAuditStatus, Constants.TWO)) { |
| | | // 审核驳回 |
| | | sendSmsNotify(shopInfo.getTelephone(), |
| | | Constants.SmsNotify.SHOP_AUTH_REJECTED, |
| | | "storeName", shopInfo.getName(), |
| | | "reason", auditDTO.getAuditRemark() != null ? auditDTO.getAuditRemark() : ""); |
| | | "reason", auditRemark != null ? auditRemark : ""); |
| | | } |
| | | } |
| | | |
| | |
| | | shopInfo.setLegalPersonCard(request.getLegalPersonCard()); |
| | | shopInfo.setAliAccount(request.getAliAccount()); |
| | | shopInfo.setAliName(request.getAliName()); |
| | | shopInfo.setRevenueShareConfig(buildRevenueShareConfig(request.getLocalDeposit(), request.getRemoteDeposit(), request.getRemoteTake())); |
| | | shopInfo.setUpdateTime(now); |
| | | shopInfoMapper.updateById(shopInfo); |
| | | |
| | |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "手机号格式异常,无法生成默认密码"); |
| | | } |
| | | return telephone.substring(telephone.length() - 6) + "@123456"; |
| | | } |
| | | |
| | | private String buildRevenueShareConfig(Double localDeposit, Double remoteDeposit, Double remoteTake) { |
| | | if (localDeposit == null && remoteDeposit == null && remoteTake == null) { |
| | | return null; |
| | | } |
| | | JSONObject config = new JSONObject(); |
| | | if (localDeposit != null) { |
| | | config.put("localDeposit", localDeposit); |
| | | } |
| | | if (remoteDeposit != null) { |
| | | config.put("remoteDeposit", remoteDeposit); |
| | | } |
| | | if (remoteTake != null) { |
| | | config.put("remoteTake", remoteTake); |
| | | } |
| | | return config.toJSONString(); |
| | | } |
| | | |
| | | private void createChangeVersion(ShopInfo origin, Integer originShopId, Date now) { |
| | | ShopInfo changeShop = new ShopInfo(); |
| | | changeShop.setCompanyType(origin.getCompanyType()); |
| | | changeShop.setName(origin.getName()); |
| | | changeShop.setTelephone(origin.getTelephone()); |
| | | changeShop.setLinkName(origin.getLinkName()); |
| | | changeShop.setLinkPhone(origin.getLinkPhone()); |
| | | changeShop.setIdcard(origin.getIdcard()); |
| | | changeShop.setAreaId(origin.getAreaId()); |
| | | changeShop.setLongitude(origin.getLongitude()); |
| | | changeShop.setLatitude(origin.getLatitude()); |
| | | changeShop.setAddress(origin.getAddress()); |
| | | changeShop.setIdcardImg(origin.getIdcardImg()); |
| | | changeShop.setIdcardImgBack(origin.getIdcardImgBack()); |
| | | changeShop.setBusinessImg(origin.getBusinessImg()); |
| | | changeShop.setLegalPersonName(origin.getLegalPersonName()); |
| | | changeShop.setLegalPersonPhone(origin.getLegalPersonPhone()); |
| | | changeShop.setLegalPersonCard(origin.getLegalPersonCard()); |
| | | changeShop.setAliAccount(origin.getAliAccount()); |
| | | changeShop.setAliName(origin.getAliName()); |
| | | changeShop.setDepositAmount(origin.getDepositAmount()); |
| | | changeShop.setRevenueShareConfig(origin.getRevenueShareConfig()); |
| | | changeShop.setVersionType(Constants.ONE); |
| | | changeShop.setRelationShopId(originShopId); |
| | | changeShop.setRegionMemberId(origin.getRegionMemberId()); |
| | | changeShop.setOpenid(origin.getOpenid()); |
| | | changeShop.setStatus(Constants.ZERO); |
| | | changeShop.setDeleted(Constants.ZERO); |
| | | changeShop.setCreateTime(now); |
| | | changeShop.setUpdateTime(now); |
| | | shopInfoMapper.insert(changeShop); |
| | | |
| | | // 拷贝附件到变更版本 |
| | | List<Multifile> originFiles = multifileMapper.selectList(new QueryWrapper<Multifile>().lambda() |
| | | .eq(Multifile::getObjId, originShopId) |
| | | .eq(Multifile::getIsdeleted, Constants.ZERO) |
| | | .in(Multifile::getObjType, |
| | | Constants.FileType.STORE_FRONT.getKey(), |
| | | Constants.FileType.STORE_INTERIOR.getKey(), |
| | | Constants.FileType.OTHER_MATERIAL.getKey(), |
| | | Constants.FileType.LABOR_CONTRACT.getKey(), |
| | | Constants.FileType.SOCIAL_SECURITY.getKey())); |
| | | for (Multifile f : originFiles) { |
| | | Multifile copy = new Multifile(); |
| | | copy.setCreator(f.getCreator()); |
| | | copy.setCreateDate(now); |
| | | copy.setIsdeleted(Constants.ZERO); |
| | | copy.setName(f.getName()); |
| | | copy.setInfo(f.getInfo()); |
| | | copy.setObjId(changeShop.getId()); |
| | | copy.setType(f.getType()); |
| | | copy.setObjType(f.getObjType()); |
| | | copy.setFileurl(f.getFileurl()); |
| | | copy.setSortnum(f.getSortnum()); |
| | | multifileMapper.insert(copy); |
| | | } |
| | | } |
| | | |
| | | private void checkTelephoneUnique(String telephone, Integer excludeId) { |
| | |
| | | vo.setAliAccount(shopInfo.getAliAccount()); |
| | | vo.setAliName(shopInfo.getAliName()); |
| | | vo.setDepositAmount(shopInfo.getDepositAmount()); |
| | | vo.setDeliveryRange(shopInfo.getDeliveryArea()); |
| | | vo.setVersionType(shopInfo.getVersionType()); |
| | | vo.setRelationShopId(shopInfo.getRelationShopId()); |
| | | // 解析收益比例配置 |
| | | if (StringUtils.isNotBlank(shopInfo.getRevenueShareConfig())) { |
| | | try { |
| | | JSONObject config = JSONObject.parseObject(shopInfo.getRevenueShareConfig()); |
| | | if (config != null) { |
| | | vo.setLocalDeposit(config.getDouble("localDeposit")); |
| | | vo.setRemoteDeposit(config.getDouble("remoteDeposit")); |
| | | vo.setRemoteTake(config.getDouble("remoteTake")); |
| | | } |
| | | } catch (Exception ignored) { |
| | | } |
| | | } |
| | | |
| | | // 拼接图片前缀 |
| | | String imgPrefix = ""; |
| | |
| | | qw.lambda() |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .eq(ShopInfo::getStatus, Constants.ZERO) |
| | | .eq(ShopInfo::getVersionType, Constants.ZERO) |
| | | .eq(ShopInfo::getAuditStatus, Constants.THREE); |
| | | |
| | | // 门店营业类型筛选 |
| | |
| | | @Override |
| | | public ShopWebDetailVO getShopWebDetail(ShopDetailQueryDTO dto) { |
| | | ShopInfo shop = shopInfoMapper.selectById(dto.getId()); |
| | | if (Objects.isNull(shop) || Constants.equalsInteger(shop.getDeleted(), Constants.ONE)) { |
| | | if (Objects.isNull(shop) || Constants.equalsInteger(shop.getDeleted(), Constants.ONE) || Constants.equalsInteger(shop.getVersionType(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | |
| | |
| | | @Override |
| | | public ShopCenterVO getShopCenterInfo(Integer shopId) { |
| | | ShopInfo shop = shopInfoMapper.selectById(shopId); |
| | | if (shop == null || Constants.equalsInteger(shop.getDeleted(), Constants.ONE)) { |
| | | if (shop == null || Constants.equalsInteger(shop.getDeleted(), Constants.ONE) || Constants.equalsInteger(shop.getVersionType(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | ShopCenterVO vo = new ShopCenterVO(); |
| | |
| | | } |
| | | ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda().eq(ShopInfo::getTelephone, dto.getTelephone()) |
| | | .eq(ShopInfo::getDeleted,Constants.ZERO) |
| | | .eq(ShopInfo::getVersionType,Constants.ZERO) |
| | | .last("limit 1") |
| | | ); |
| | | if(shop==null){ |
| | |
| | | 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()) |
| | | if(Objects.nonNull(dto.getMemberId())){ |
| | | Member member = memberMapper.selectById(dto.getMemberId()); |
| | | if(Objects.nonNull(member)){ |
| | | memberMapper.update(new UpdateWrapper<Member>().lambda() |
| | | .set(Member::getLoginShopId,shop.getId()) |
| | | .eq(Member::getId,member.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()); |
| | | shop.setMemberId(member.getId()); |
| | | }else{ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"会员信息异常,请联系管理员"); |
| | | } |
| | | |
| | | } |
| | | // 创建token(generateTokenForRedis 已自动清除该用户旧token,保证唯一有效) |
| | | String token = JwtTokenUtil.generateTokenForRedis(shop.getId(), Constants.TWO, JSONObject.toJSONString(shop), redisTemplate); |
| | | String token = JwtTokenUtil.generateShopTokenForRedis(shop.getMemberId(), 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) { |
| | |
| | | @Override |
| | | public ShopLoginVO shopSilentLogin(Integer memberId) { |
| | | Member member = memberMapper.selectById(memberId); |
| | | if(Objects.isNull(member)||StringUtils.isBlank(member.getOpenid())){ |
| | | if(Objects.isNull(member)){ |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "当前登录会员身份异常,请联系管理员!"); |
| | | } |
| | | if (Objects.isNull(member.getLoginShopId())) { |
| | | return null; |
| | | } |
| | | ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda() |
| | | .eq(ShopInfo::getOpenid, member.getOpenid()) |
| | | .eq(ShopInfo::getId, member.getLoginShopId()) |
| | | .eq(ShopInfo::getVersionType,Constants.ZERO) |
| | | .eq(ShopInfo::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | if (shop == null) { |
| | |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"门店已禁用,请联系管理员"); |
| | | } |
| | | // 创建token(generateTokenForRedis 已自动清除该用户旧token,保证唯一有效) |
| | | String token = JwtTokenUtil.generateTokenForRedis(shop.getId(), Constants.TWO, JSONObject.toJSONString(shop), redisTemplate); |
| | | String token = JwtTokenUtil.generateShopTokenForRedis(member.getId(), JSONObject.toJSONString(shop), redisTemplate); |
| | | |
| | | ShopLoginVO vo = new ShopLoginVO(); |
| | | vo.setToken(token); |
| | |
| | | if (StringUtils.isBlank(phone)) { |
| | | return; |
| | | } |
| | | if (!smsNotify.isEnabled()) { |
| | | return; |
| | | } |
| | | String content = smsNotify.format(paramPairs); |
| | | try { |
| | | JSONObject templateParam = new JSONObject(); |
| | |
| | | String digits = Strings.randomNumeric(4); |
| | | //发送验证码 |
| | | String templateParam = "{\"code\":\"" + digits + "\"}"; |
| | | String error = AliSmsService.sendSms(phone, Constants.SmsNotify.VERIFY_CODE.getTemplateCode(), templateParam); |
| | | String error = null; |
| | | if (Constants.SmsNotify.VERIFY_CODE.isEnabled()) { |
| | | error = AliSmsService.sendSms(phone, Constants.SmsNotify.VERIFY_CODE.getTemplateCode(), templateParam); |
| | | } |
| | | if (error != null) { |
| | | throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "短信发送失败,请稍后重试"); |
| | | } |
| | |
| | | apiV3Key: NJTLJSTZYXZRGScaiwubuzichanbu666 #apiV3Key |
| | | serialNumer: 25D19D18217F4588841E5CD1AA0D1533DE8AF84A #商户证书序列号 |
| | | privateKeyPath: pay/pro/wx/apiclient_key.pem |
| | | v3NotifyUrl: http://xiaopiqiu2.natapp1.cc/web/api/wxPayV3Notify |
| | | v3RefundNotifyUrl: http://xiaopiqiu2.natapp1.cc/web/api/wxRefundV3Notify |
| | | v3NotifyUrl: https://test.doumee.cn/gtzxljc_web/web/api/wxPayV3Notify |
| | | v3RefundNotifyUrl: https://test.doumee.cn/gtzxljc_web/web/api/wxRefundV3Notify |
| | | |
| | | |
| | | alipay: |
| | |
| | | } |
| | | |
| | | |
| | | @LoginRequired |
| | | @ApiOperation(value = "门店账号密码登录", notes = "小程序端,门店用户通过手机号+密码登录") |
| | | @PostMapping("/shopLogin") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true), |
| | | }) |
| | | public ApiResponse<ShopLoginVO> shopLogin(@RequestBody @Validated ShopLoginDTO dto) { |
| | | dto.setMemberId(getMemberId()); |
| | | return ApiResponse.success("操作成功", shopInfoService.shopPasswordLogin(dto)); |
| | | } |
| | | |
| | |
| | | import com.doumee.dao.dto.AreasDto; |
| | | import com.doumee.dao.dto.CalculateLocalPriceDTO; |
| | | import com.doumee.dao.dto.CalculateRemotePriceDTO; |
| | | import com.doumee.dao.dto.DriverCheckRadiusDTO; |
| | | import com.doumee.dao.dto.ShopCheckRadiusDTO; |
| | | import com.doumee.dao.dto.DirectionInfoDTO; |
| | | import com.doumee.dao.dto.SameCityCheckDTO; |
| | | import com.doumee.dao.vo.PriceCalculateVO; |
| | |
| | | return ApiResponse.success("查询成功", appVersion); |
| | | } |
| | | |
| | | @LoginShopRequired |
| | | @ApiOperation(value = "门店校验操作半径", notes = "校验门店操作人当前位置是否在目标点允许操作半径内") |
| | | @PostMapping("/checkShopOperationRadius") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true) |
| | | }) |
| | | public ApiResponse<Boolean> checkShopOperationRadius(@RequestBody @Valid ShopCheckRadiusDTO dto) { |
| | | Boolean result = ordersService.checkOperationRadius(dto.getOrderId(), this.getShopId(), Constants.ZERO, dto.getLng(), dto.getLat()); |
| | | return ApiResponse.success("操作成功", result); |
| | | } |
| | | |
| | | @LoginDriverRequired |
| | | @ApiOperation(value = "司机校验操作半径", notes = "校验司机当前位置是否在目标点允许操作半径内") |
| | | @PostMapping("/checkDriverOperationRadius") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true) |
| | | }) |
| | | public ApiResponse<Boolean> checkDriverOperationRadius(@RequestBody @Valid DriverCheckRadiusDTO dto) { |
| | | Boolean result = ordersService.checkOperationRadius(dto.getOrderId(), this.getDriverId(), Constants.ONE, dto.getLng(), dto.getLat()); |
| | | return ApiResponse.success("操作成功", result); |
| | | } |
| | | |
| | | } |
| | |
| | | import com.doumee.core.model.ApiResponse; |
| | | import com.doumee.dao.business.model.Member; |
| | | import com.doumee.dao.dto.UpdMobileRequest; |
| | | import com.doumee.dao.vo.MemberContactVO; |
| | | import com.doumee.dao.vo.UserCenterVO; |
| | | import com.doumee.service.business.MemberService; |
| | | import com.doumee.service.business.SmsrecordService; |
| | |
| | | return ApiResponse.success("操作成功"); |
| | | } |
| | | |
| | | @LoginRequired |
| | | @ApiOperation("获取用户收件信息") |
| | | @GetMapping("/getContactInfo") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "用户token值", required = true) |
| | | }) |
| | | public ApiResponse<MemberContactVO> getContactInfo() { |
| | | return ApiResponse.success("查询成功", memberService.getContactInfo(getMemberId())); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | templateParam.put("orderNo", refundOrder.getCode()); |
| | | templateParam.put("money", String.valueOf(Constants.getFormatMoney( |
| | | refundOrder.getRefundAmount() != null ? refundOrder.getRefundAmount() : 0L))); |
| | | String smsError = AliSmsService.sendSms(refundMember.getTelephone(), |
| | | String smsError = null; |
| | | if (Constants.SmsNotify.MEMBER_REFUNDED.isEnabled()) { |
| | | smsError = AliSmsService.sendSms(refundMember.getTelephone(), |
| | | Constants.SmsNotify.MEMBER_REFUNDED.getTemplateCode(), |
| | | templateParam.toJSONString()); |
| | | } |
| | | if (smsError == null) { |
| | | log.info("退款短信发送成功: phone={}", refundMember.getTelephone()); |
| | | } else { |
| | |
| | | |
| | | spring: |
| | | profiles: |
| | | active: pro |
| | | active: dev |
| | | # JSON返回配置 |
| | | jackson: |
| | | # 默认时区 |