酒店迁移到超时模块

This commit is contained in:
zjf committed 2026-09-30 11:53:08 +08:00
1 parent 9013f51e2a
commit 8d62425d68
73 files changed
+975 -970

No files matched your search

@@ -1,28 +0,0 @@
package com.bsd.pjcloud.canteen.vo;
import com.bsd.pjcloud.canteen.entity.CanteenHotelDailyEntity;
import com.bsd.pjcloud.canteen.entity.CanteenHotelEntity;
import com.bsd.pjcloud.canteen.entity.CanteenHotelProductEntity;
import com.bsd.pjcloud.canteen.entity.CanteenHotelRoomEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
@Schema(description = "酒店详情(含上游拉取的房型/产品摘要)")
public class CanteenHotelDetailVO {
private CanteenHotelEntity hotel;
private List<CanteenHotelRoomEntity> rooms = new ArrayList<>();
private List<CanteenHotelProductEntity> products = new ArrayList<>();
@Schema(description = "日历条数(未来含今天)")
private Long dailyCount;
@Schema(description = "日历预览(默认最近一段,完整日历走分页接口)")
private List<CanteenHotelDailyEntity> dailyPreview = new ArrayList<>();
}
@@ -1,100 +0,0 @@
package com.bsd.pjcloud.canteen.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.canteen.entity.CanteenHotelEntity;
import com.bsd.pjcloud.canteen.service.CanteenHotelService;
import com.bsd.pjcloud.canteen.vo.CanteenHotelImportResultVO;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequiredArgsConstructor
@RequestMapping("/canteenHotel")
@Tag(name = "酒店管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class CanteenHotelController {
private final CanteenHotelService hotelService;
@Operation(summary = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
public R<Page<CanteenHotelEntity>> page(@ParameterObject Page<CanteenHotelEntity> page,
@ParameterObject CanteenHotelEntity query) {
var wrapper = Wrappers.<CanteenHotelEntity>lambdaQuery()
.like(StrUtil.isNotBlank(query.getHotelName()), CanteenHotelEntity::getHotelName, query.getHotelName())
.like(StrUtil.isNotBlank(query.getHotelCode()), CanteenHotelEntity::getHotelCode, query.getHotelCode())
.like(StrUtil.isNotBlank(query.getGroupCode()), CanteenHotelEntity::getGroupCode, query.getGroupCode())
.eq(StrUtil.isNotBlank(query.getSourceId()), CanteenHotelEntity::getSourceId, query.getSourceId())
.eq(StrUtil.isNotBlank(query.getSheetName()), CanteenHotelEntity::getSheetName, query.getSheetName())
.orderByDesc(CanteenHotelEntity::getCreateTime)
.orderByDesc(CanteenHotelEntity::getId);
// 启用:含未写状态的老数据;停用:仅 OFFLINE;空=全部
if ("OFFLINE".equalsIgnoreCase(query.getUpstreamStatus())) {
wrapper.eq(CanteenHotelEntity::getUpstreamStatus, "OFFLINE");
}
else if ("ACTIVE".equalsIgnoreCase(query.getUpstreamStatus())) {
wrapper.and(w -> w.isNull(CanteenHotelEntity::getUpstreamStatus)
.or()
.ne(CanteenHotelEntity::getUpstreamStatus, "OFFLINE"));
}
return R.ok(hotelService.pageScope(page, wrapper));
}
/** 上传文件会立刻 transferTo 临时目录,勿加 @SysLog */
@Operation(summary = "提交Excel异步导入(多Sheet流式)")
@PostMapping("/import")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_import')")
public R<CanteenHotelImportResultVO> importExcel(@RequestParam("file") MultipartFile file) {
return hotelService.startImport(file);
}
@Operation(summary = "查询酒店导入进度")
@GetMapping("/import/status/{taskId}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_import')")
public R<CanteenHotelImportResultVO> importStatus(@PathVariable String taskId) {
return hotelService.getImportStatus(taskId);
}
@Operation(summary = "详情")
@GetMapping("/{id}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
public R getById(@PathVariable Long id) {
return R.ok(hotelService.getById(id));
}
@SysLog("新增酒店")
@Operation(summary = "新增")
@PostMapping
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_add')")
public R save(@RequestBody CanteenHotelEntity entity) {
return R.ok(hotelService.saveHotel(entity));
}
@SysLog("修改酒店")
@Operation(summary = "修改")
@PutMapping
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_edit')")
public R update(@RequestBody CanteenHotelEntity entity) {
return R.ok(hotelService.updateHotel(entity));
}
@SysLog("删除酒店")
@Operation(summary = "删除")
@DeleteMapping
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_del')")
public R remove(@RequestBody Long[] ids) {
return R.ok(hotelService.removeHotels(ids));
}
}
@@ -1,9 +0,0 @@
package com.bsd.pjcloud.canteen.mapper;
import com.bsd.pjcloud.canteen.entity.CanteenHotelCallbackTaskEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CanteenHotelCallbackTaskMapper extends PjcloudBaseMapper<CanteenHotelCallbackTaskEntity> {
}
@@ -1,9 +0,0 @@
package com.bsd.pjcloud.canteen.mapper;
import com.bsd.pjcloud.canteen.entity.CanteenHotelDownstreamAppEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CanteenHotelDownstreamAppMapper extends PjcloudBaseMapper<CanteenHotelDownstreamAppEntity> {
}
@@ -1,14 +0,0 @@
package com.bsd.pjcloud.canteen.mapper;
import com.bsd.pjcloud.canteen.entity.CanteenHotelEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface CanteenHotelMapper extends PjcloudBaseMapper<CanteenHotelEntity> {
int insertBatch(@Param("list") List<CanteenHotelEntity> list);
}
@@ -1,9 +0,0 @@
package com.bsd.pjcloud.canteen.mapper;
import com.bsd.pjcloud.canteen.entity.CanteenHotelOrderEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CanteenHotelOrderMapper extends PjcloudBaseMapper<CanteenHotelOrderEntity> {
}
@@ -1,9 +0,0 @@
package com.bsd.pjcloud.canteen.mapper;
import com.bsd.pjcloud.canteen.entity.CanteenHotelPriceConfigEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CanteenHotelPriceConfigMapper extends PjcloudBaseMapper<CanteenHotelPriceConfigEntity> {
}
@@ -1,9 +0,0 @@
package com.bsd.pjcloud.canteen.mapper;
import com.bsd.pjcloud.canteen.entity.CanteenHotelSyncLogEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CanteenHotelSyncLogMapper extends PjcloudBaseMapper<CanteenHotelSyncLogEntity> {
}
@@ -1,19 +0,0 @@
package com.bsd.pjcloud.canteen.service;
import com.bsd.pjcloud.canteen.entity.CanteenHotelPriceConfigEntity;
import com.bsd.pjcloud.common.core.util.R;
import java.math.BigDecimal;
public interface CanteenHotelPriceConfigService {
R<CanteenHotelPriceConfigEntity> getCurrent();
R<Boolean> saveOrUpdateConfig(CanteenHotelPriceConfigEntity entity);
/** 当前加价百分比,未配置返回 0 */
BigDecimal currentMarkupPercent();
/** 底价按加价百分比计算卖价 */
BigDecimal applyMarkup(BigDecimal costPrice);
}
@@ -1,26 +0,0 @@
package com.bsd.pjcloud.canteen.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.canteen.entity.CanteenHotelEntity;
import com.bsd.pjcloud.canteen.vo.CanteenHotelImportResultVO;
import com.bsd.pjcloud.common.core.util.R;
import org.springframework.web.multipart.MultipartFile;
public interface CanteenHotelService extends IService<CanteenHotelEntity> {
Page<CanteenHotelEntity> pageScope(Page<CanteenHotelEntity> page, LambdaQueryWrapper<CanteenHotelEntity> wrapper);
Boolean saveHotel(CanteenHotelEntity entity);
Boolean updateHotel(CanteenHotelEntity entity);
Boolean removeHotels(Long[] ids);
/** 提交异步导入,立刻返回 taskId(status=RUNNING) */
R<CanteenHotelImportResultVO> startImport(MultipartFile file);
/** 查询导入任务进度 */
R<CanteenHotelImportResultVO> getImportStatus(String taskId);
}
@@ -29,105 +29,3 @@ security:
enable: true # 开启请求加解密
default-encrypt-type: AES # 可选:AES、SM4,默认 AES
aes-key: pigxpigxpigxpigx # AES 密钥必须为 16 位
## ========== 玉编电云 / TMC CRS 酒店上游(docs/shangyou)==========
## 生产对方通常只给一个根地址:https://onlink.yubdianyun.cn/link/provider
## 此时只配 base-url 即可:鉴权 POST {base-url}/oauth/token ,业务 POST {base-url}/hotel/...
## 测试若鉴权与业务拆成两个地址,再单独配 auth-base-url / biz-base-url
#shangyou-hotel:
# # 是否启用上游调用(false 时拉酒店/房价/下单都会直接报「未启用」)
# enabled: true
# # 上游根地址(生产常用这一项即可,同时用于鉴权+业务)
# base-url: https://onlink.yubdianyun.cn/link/provider
# # 鉴权根地址;一般留空,自动用 base-url。仅当测试环境鉴权与业务分离时才填,例 https://xxx/link
# # auth-base-url: ""
# # 业务根地址;一般留空,自动用 base-url。仅当业务地址与 base-url 不同时才填
# # biz-base-url: ""
# # OAuth clientId(对方开通账号时下发,用于换 access_token)
# client-id: F210AE02B74C48A3901B
# # OAuth clientSecret(与 client-id 配对,Basic 鉴权换 token)
# client-secret: 99165116A43F413CB799C91714861408
# # 业务卡号 cardId(账号),请求体 content 里会带
# card-id: 9082727358de43be96fe
# # 业务秘钥 cardPassWord,请求体 content 里会带;也可兼作回调验签 Secret
# card-password: 5bffd3c42e5a42219872bace3092983d
# # 房价/房量回调验签 Secret:sign=MD5(Secret+time);留空则用上面的 card-password
# callback-secret: 99165116A43F413CB799C91714861408
# # 下单预订人 bookerId;留空则用 card-id;以对方开通为准
# booker-id: ""
# # 是否总对总下单(企业中转一般 true;现付调试可 false)
# order-is-group: true
# # 担保模式:NONE / FIRST_NIGHT / FULL_AMOUNT,以对方开卡为准
# order-guarantee-mode: NONE
# # 房价接口路径。生产必须用 /hotel/getRoomPrice(/hotel/getTMCRoomPrice 会 404)
# room-price-path: /hotel/getRoomPrice
# # 会员等级,逗号分隔;对方要求传时再填,空则不传该字段
# member-levels: ""
# # 调上游 HTTP 超时(毫秒),含拉酒店列表/房价等
# timeout-ms: 60000
# # token 提前作废秒数(对方 token 默认约 21600 秒);避免边界时刻用到已失效 token
# token-skew-seconds: 120
# # 「拉取上游」时拉未来多少天房价;建议 1~90;接口单次约 31 天,代码会自动按段切片
# price-days: 90
# # 授权酒店列表 Redis 缓存分钟数(HASH+ZSET,不落 JVM 全量,支持十几万级)
# hotel-list-cache-minutes: 30
# # 授权酒店数量告警阈值(仅打日志告警,不截断);十几万级强制刷新建议低峰做
# hotel-list-warn-size: 100000
# # 回调无 TENANT-ID:写入任务/匹配本地酒店用的默认租户(酒店中转一般单租户)
# callback-tenant-id: 1
# # 是否启用回调异步队列 Worker(Redis BRPOP 消费后 pullFromUpstream)
# callback-queue-enabled: true
# # 单条回调任务最大尝试次数(含首次;失败会自动重入队)
# callback-max-attempts: 3
# # 回调队列处理完一家后的间隔毫秒(房价另有 QPS 限流,这里可较小)
# callback-task-interval-ms: 50
# # 房价 getRoomPrice 限流(对方约定约 20 QPS)。多实例请均分,如 2 实例各配 10;≤0 关闭
# price-api-qps: 20
# # ----- 日更 / 差集 -----
# # 酒店列表日同步开关(false 则定时/XXL 都跳过)
# hotel-list-daily-sync-enabled: true
# # 是否启用本服务 Spring Cron(改下面 cron 即可生效;已用 XXL 请设 false,避免一天跑两次)
# spring-schedule-enabled: true
# # 列表日更时间:默认每天 02:00(Spring Cron 6 段:秒 分 时 日 月 周)
# hotel-list-daily-cron: "0 0 2 * * ?"
# # 滚价日更时间:默认每天 03:00
# price-roll-daily-cron: "0 0 3 * * ?"
# # 列表同步后是否自动把「上游有本地无」写入本地主数据
# auto-import-new-hotels: true
# # 自动导入单次上限(剩余留在差集,可再点导入)
# auto-import-batch-size: 5000
# # 每日滚第 N 天房价开关
# price-roll-daily-enabled: true
# # 滚价偏移:today + N(文档第 91 天 → 90)
# price-roll-day-offset: 90
# # 滚价按本地酒店 id 游标每批数量(防 OOM)
# price-roll-batch-size: 100
# # 全量房价房量:每天最多次数 / 最小间隔小时(「拉取全部启用详情」受此限制)
# full-price-sync-max-per-day: 3
# full-price-sync-min-interval-hours: 6
# # 全量拉详情:每家间隔毫秒(落库已批量,默认 0;上游压力大时可调大)
# detail-pull-interval-ms: 0
# # 全量拉详情单次最多家数;0=不限制(酒店很多时建议先设 100 试跑)
# detail-pull-max-hotels: 0
# # 差集扫描 / 重建本地 code SET 批大小
# diff-scan-batch-size: 500
# # 同步后:本地有上游无 → 自动标 OFFLINE 停用
# auto-mark-offline-hotels: true
# # 同步后:已停用但上游又出现 → 自动恢复 ACTIVE
# auto-reactivate-online-hotels: true
#
## ========== 下游销售方推送(《第三方数据同步接口文档》)==========
## 本系统作为中转 A,主动把加价后的酒店/房价推到下游 B(与上面「上游」无关,可单独开关)
#hotel-downstream:
# # 是否启用向下游推送
# enabled: false
# # 下游 B 系统根地址(不含尾斜杠),实际请求 = base-url + /third/party/api/...
# base-url: https://b.example.com
# # B 系统分配给我们的 appKey(请求头/签名用)
# app-key: TP_xxx
# # B 系统分配的 appSecret(仅本地算签名,不落报文)
# app-secret: your-secret
# # 推下游 HTTP 超时(毫秒)
# timeout-ms: 30000
# # 兼容字段;实际上游拉取天数以 shangyou-hotel.price-days 为准
# daily-days: 90
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.entity;
package com.bsd.pjcloud.supermarket.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
@TableName("canteen_hotel_callback_task")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "上游酒店回调异步任务")
public class CanteenHotelCallbackTaskEntity extends Model<CanteenHotelCallbackTaskEntity> {
public class SmHotelCallbackTaskEntity extends Model<SmHotelCallbackTaskEntity> {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.entity;
package com.bsd.pjcloud.supermarket.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
@@ -16,7 +16,7 @@ import java.time.LocalDateTime;
@TableName("canteen_hotel_daily")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "酒店日历房")
public class CanteenHotelDailyEntity extends Model<CanteenHotelDailyEntity> {
public class SmHotelDailyEntity extends Model<SmHotelDailyEntity> {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.entity;
package com.bsd.pjcloud.supermarket.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
@TableName("canteen_hotel_downstream_app")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "下游销售应用")
public class CanteenHotelDownstreamAppEntity extends Model<CanteenHotelDownstreamAppEntity> {
public class SmHotelDownstreamAppEntity extends Model<SmHotelDownstreamAppEntity> {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.entity;
package com.bsd.pjcloud.supermarket.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
@TableName("canteen_hotel")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "酒店管理")
public class CanteenHotelEntity extends Model<CanteenHotelEntity> {
public class SmHotelEntity extends Model<SmHotelEntity> {
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "主键(系统生成)")
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.entity;
package com.bsd.pjcloud.supermarket.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
@@ -16,7 +16,7 @@ import java.time.LocalDateTime;
@TableName("canteen_hotel_order")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "酒店中转订单")
public class CanteenHotelOrderEntity extends Model<CanteenHotelOrderEntity> {
public class SmHotelOrderEntity extends Model<SmHotelOrderEntity> {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.entity;
package com.bsd.pjcloud.supermarket.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
@TableName("canteen_hotel_price_config")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "酒店全局加价配置")
public class CanteenHotelPriceConfigEntity extends Model<CanteenHotelPriceConfigEntity> {
public class SmHotelPriceConfigEntity extends Model<SmHotelPriceConfigEntity> {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.entity;
package com.bsd.pjcloud.supermarket.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
@TableName("canteen_hotel_product")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "酒店产品")
public class CanteenHotelProductEntity extends Model<CanteenHotelProductEntity> {
public class SmHotelProductEntity extends Model<SmHotelProductEntity> {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.entity;
package com.bsd.pjcloud.supermarket.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
@TableName("canteen_hotel_room")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "酒店房型")
public class CanteenHotelRoomEntity extends Model<CanteenHotelRoomEntity> {
public class SmHotelRoomEntity extends Model<SmHotelRoomEntity> {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.entity;
package com.bsd.pjcloud.supermarket.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
@TableName("canteen_hotel_sync_log")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "酒店上游同步日志")
public class CanteenHotelSyncLogEntity extends Model<CanteenHotelSyncLogEntity> {
public class SmHotelSyncLogEntity extends Model<SmHotelSyncLogEntity> {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@@ -0,0 +1,28 @@
package com.bsd.pjcloud.supermarket.vo;
import com.bsd.pjcloud.supermarket.entity.SmHotelDailyEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelProductEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelRoomEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
@Schema(description = "酒店详情(含上游拉取的房型/产品摘要)")
public class SmHotelDetailVO {
private SmHotelEntity hotel;
private List<SmHotelRoomEntity> rooms = new ArrayList<>();
private List<SmHotelProductEntity> products = new ArrayList<>();
@Schema(description = "日历条数(未来含今天)")
private Long dailyCount;
@Schema(description = "日历预览(默认最近一段,完整日历走分页接口)")
private List<SmHotelDailyEntity> dailyPreview = new ArrayList<>();
}
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.vo;
package com.bsd.pjcloud.supermarket.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -8,7 +8,7 @@ import java.util.List;
@Data
@Schema(description = "酒店Excel导入任务/结果")
public class CanteenHotelImportResultVO {
public class SmHotelImportResultVO {
@Schema(description = "任务ID(异步导入)")
private String taskId;
@@ -127,6 +127,11 @@
<artifactId>pjcloud-common-sequence</artifactId>
<version>5.7.0</version>
</dependency>
<!-- 酒店日更 XXL-JOB -->
<dependency>
<groupId>com.bsd</groupId>
<artifactId>pjcloud-common-job</artifactId>
</dependency>
</dependencies>
<profiles>
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.config;
package com.bsd.pjcloud.supermarket.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.config;
package com.bsd.pjcloud.supermarket.config;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.config;
package com.bsd.pjcloud.supermarket.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
@@ -8,5 +8,5 @@ import org.springframework.scheduling.annotation.EnableScheduling;
*/
@Configuration
@EnableScheduling
public class CanteenSchedulingConfig {
public class SupermarketSchedulingConfig {
}
@@ -1,8 +1,8 @@
package com.bsd.pjcloud.canteen.controller;
package com.bsd.pjcloud.supermarket.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.canteen.entity.CanteenHotelCallbackTaskEntity;
import com.bsd.pjcloud.canteen.service.CanteenHotelCallbackTaskService;
import com.bsd.pjcloud.supermarket.entity.SmHotelCallbackTaskEntity;
import com.bsd.pjcloud.supermarket.service.SmHotelCallbackTaskService;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import io.swagger.v3.oas.annotations.Operation;
@@ -19,32 +19,32 @@ import org.springframework.web.bind.annotation.*;
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/canteenHotelCallback")
@RequestMapping("/smHotelCallback")
@Tag(name = "酒店上游回调任务")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class CanteenHotelCallbackTaskController {
public class SmHotelCallbackTaskController {
private final CanteenHotelCallbackTaskService callbackTaskService;
private final SmHotelCallbackTaskService callbackTaskService;
@Operation(summary = "回调任务分页")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotelCallback_view')")
public R<Page<CanteenHotelCallbackTaskEntity>> page(@ParameterObject Page<CanteenHotelCallbackTaskEntity> page,
@ParameterObject CanteenHotelCallbackTaskEntity query) {
@PreAuthorize("@pms.hasPermission('supermarket_smHotelCallback_view')")
public R<Page<SmHotelCallbackTaskEntity>> page(@ParameterObject Page<SmHotelCallbackTaskEntity> page,
@ParameterObject SmHotelCallbackTaskEntity query) {
return R.ok(callbackTaskService.pageTasks(page, query));
}
@Operation(summary = "回调任务详情")
@GetMapping("/{id}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotelCallback_view')")
public R<CanteenHotelCallbackTaskEntity> detail(@PathVariable Long id) {
@PreAuthorize("@pms.hasPermission('supermarket_smHotelCallback_view')")
public R<SmHotelCallbackTaskEntity> detail(@PathVariable Long id) {
return R.ok(callbackTaskService.getDetail(id));
}
@SysLog("酒店回调任务重试")
@Operation(summary = "失败/跳过任务重新入队")
@PostMapping("/retry/{id}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotelCallback_retry')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotelCallback_retry')")
public R<Boolean> retry(@PathVariable Long id) {
return callbackTaskService.retry(id);
}
@@ -0,0 +1,100 @@
package com.bsd.pjcloud.supermarket.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.supermarket.entity.SmHotelEntity;
import com.bsd.pjcloud.supermarket.service.SmHotelService;
import com.bsd.pjcloud.supermarket.vo.SmHotelImportResultVO;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequiredArgsConstructor
@RequestMapping("/smHotel")
@Tag(name = "酒店管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class SmHotelController {
private final SmHotelService hotelService;
@Operation(summary = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<Page<SmHotelEntity>> page(@ParameterObject Page<SmHotelEntity> page,
@ParameterObject SmHotelEntity query) {
var wrapper = Wrappers.<SmHotelEntity>lambdaQuery()
.like(StrUtil.isNotBlank(query.getHotelName()), SmHotelEntity::getHotelName, query.getHotelName())
.like(StrUtil.isNotBlank(query.getHotelCode()), SmHotelEntity::getHotelCode, query.getHotelCode())
.like(StrUtil.isNotBlank(query.getGroupCode()), SmHotelEntity::getGroupCode, query.getGroupCode())
.eq(StrUtil.isNotBlank(query.getSourceId()), SmHotelEntity::getSourceId, query.getSourceId())
.eq(StrUtil.isNotBlank(query.getSheetName()), SmHotelEntity::getSheetName, query.getSheetName())
.orderByDesc(SmHotelEntity::getCreateTime)
.orderByDesc(SmHotelEntity::getId);
// 启用:含未写状态的老数据;停用:仅 OFFLINE;空=全部
if ("OFFLINE".equalsIgnoreCase(query.getUpstreamStatus())) {
wrapper.eq(SmHotelEntity::getUpstreamStatus, "OFFLINE");
}
else if ("ACTIVE".equalsIgnoreCase(query.getUpstreamStatus())) {
wrapper.and(w -> w.isNull(SmHotelEntity::getUpstreamStatus)
.or()
.ne(SmHotelEntity::getUpstreamStatus, "OFFLINE"));
}
return R.ok(hotelService.pageScope(page, wrapper));
}
/** 上传文件会立刻 transferTo 临时目录,勿加 @SysLog */
@Operation(summary = "提交Excel异步导入(多Sheet流式)")
@PostMapping("/import")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_import')")
public R<SmHotelImportResultVO> importExcel(@RequestParam("file") MultipartFile file) {
return hotelService.startImport(file);
}
@Operation(summary = "查询酒店导入进度")
@GetMapping("/import/status/{taskId}")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_import')")
public R<SmHotelImportResultVO> importStatus(@PathVariable String taskId) {
return hotelService.getImportStatus(taskId);
}
@Operation(summary = "详情")
@GetMapping("/{id}")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R getById(@PathVariable Long id) {
return R.ok(hotelService.getById(id));
}
@SysLog("新增酒店")
@Operation(summary = "新增")
@PostMapping
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_add')")
public R save(@RequestBody SmHotelEntity entity) {
return R.ok(hotelService.saveHotel(entity));
}
@SysLog("修改酒店")
@Operation(summary = "修改")
@PutMapping
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_edit')")
public R update(@RequestBody SmHotelEntity entity) {
return R.ok(hotelService.updateHotel(entity));
}
@SysLog("删除酒店")
@Operation(summary = "删除")
@DeleteMapping
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_del')")
public R remove(@RequestBody Long[] ids) {
return R.ok(hotelService.removeHotels(ids));
}
}
@@ -1,9 +1,9 @@
package com.bsd.pjcloud.canteen.controller;
package com.bsd.pjcloud.supermarket.controller;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.bsd.pjcloud.canteen.integration.downstream.DownstreamInboundAuth;
import com.bsd.pjcloud.canteen.service.CanteenHotelOrderService;
import com.bsd.pjcloud.supermarket.integration.downstream.DownstreamInboundAuth;
import com.bsd.pjcloud.supermarket.service.SmHotelOrderService;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.security.annotation.Inner;
import io.swagger.v3.oas.annotations.Operation;
@@ -22,11 +22,11 @@ import java.util.Map;
@RequiredArgsConstructor
@RequestMapping("/third/party/hotel/order")
@Tag(name = "下游酒店订单回传")
public class CanteenHotelDownstreamOrderController {
public class SmHotelDownstreamOrderController {
private final DownstreamInboundAuth inboundAuth;
private final CanteenHotelOrderService orderService;
private final SmHotelOrderService orderService;
@Inner(value = false)
@Operation(summary = "下游下单回传(我方再调上游创建)")
@@ -1,13 +1,13 @@
package com.bsd.pjcloud.canteen.controller;
package com.bsd.pjcloud.supermarket.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.canteen.entity.CanteenHotelDailyEntity;
import com.bsd.pjcloud.canteen.entity.CanteenHotelPriceConfigEntity;
import com.bsd.pjcloud.canteen.entity.CanteenHotelSyncLogEntity;
import com.bsd.pjcloud.canteen.service.CanteenHotelMidService;
import com.bsd.pjcloud.canteen.service.CanteenHotelPriceConfigService;
import com.bsd.pjcloud.canteen.service.CanteenHotelSyncService;
import com.bsd.pjcloud.canteen.vo.CanteenHotelDetailVO;
import com.bsd.pjcloud.supermarket.entity.SmHotelDailyEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelPriceConfigEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelSyncLogEntity;
import com.bsd.pjcloud.supermarket.service.SmHotelMidService;
import com.bsd.pjcloud.supermarket.service.SmHotelPriceConfigService;
import com.bsd.pjcloud.supermarket.service.SmHotelSyncService;
import com.bsd.pjcloud.supermarket.vo.SmHotelDetailVO;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import io.swagger.v3.oas.annotations.Operation;
@@ -25,79 +25,79 @@ import java.util.Map;
@RestController
@RequiredArgsConstructor
@RequestMapping("/canteenHotel")
@RequestMapping("/smHotel")
@Tag(name = "酒店中转(拉取/推送/加价)")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class CanteenHotelMidController {
public class SmHotelMidController {
private final CanteenHotelMidService midService;
private final SmHotelMidService midService;
private final CanteenHotelPriceConfigService priceConfigService;
private final SmHotelPriceConfigService priceConfigService;
private final CanteenHotelSyncService syncService;
private final SmHotelSyncService syncService;
@Operation(summary = "查询全局加价配置")
@GetMapping("/priceConfig")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotelPrice_view')")
public R<CanteenHotelPriceConfigEntity> getPriceConfig() {
@PreAuthorize("@pms.hasPermission('supermarket_smHotelPrice_view')")
public R<SmHotelPriceConfigEntity> getPriceConfig() {
return priceConfigService.getCurrent();
}
@SysLog("保存酒店加价配置")
@Operation(summary = "保存全局加价配置")
@PutMapping("/priceConfig")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotelPrice_edit')")
public R<Boolean> savePriceConfig(@RequestBody CanteenHotelPriceConfigEntity entity) {
@PreAuthorize("@pms.hasPermission('supermarket_smHotelPrice_edit')")
public R<Boolean> savePriceConfig(@RequestBody SmHotelPriceConfigEntity entity) {
return priceConfigService.saveOrUpdateConfig(entity);
}
@Operation(summary = "酒店详情(含已拉取房型/产品/日历预览)")
@GetMapping("/detail/{id}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
public R<CanteenHotelDetailVO> detail(@PathVariable Long id) {
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<SmHotelDetailVO> detail(@PathVariable Long id) {
return midService.getHotelDetail(id);
}
@Operation(summary = "酒店日历分页")
@GetMapping("/detail/{id}/daily")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
public R<Page<CanteenHotelDailyEntity>> dailyPage(@PathVariable Long id,
@ParameterObject Page<CanteenHotelDailyEntity> page,
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<Page<SmHotelDailyEntity>> dailyPage(@PathVariable Long id,
@ParameterObject Page<SmHotelDailyEntity> page,
@RequestParam(required = false) String productCode) {
return midService.pageDaily(id, page, productCode);
}
@Operation(summary = "从上游拉取房型产品并加价落库")
@PostMapping("/mid/pull/{id}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_edit')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_edit')")
public R<Map<String, Object>> pull(@PathVariable Long id) {
return midService.pullFromUpstream(id);
}
@Operation(summary = "推送到下游销售方")
@PostMapping("/mid/push/{id}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_push')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_push')")
public R<Map<String, Object>> push(@PathVariable Long id) {
return midService.pushToDownstream(id);
}
@Operation(summary = "拉取上游并推送下游")
@PostMapping("/mid/pullAndPush/{id}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_push')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_push')")
public R<Map<String, Object>> pullAndPush(@PathVariable Long id) {
return midService.pullAndPush(id);
}
@Operation(summary = "批量拉取并推送")
@PostMapping("/mid/pullAndPush/batch")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_push')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_push')")
public R<Map<String, Object>> pullAndPushBatch(@RequestBody List<Long> ids) {
return midService.pullAndPushBatch(ids);
}
@Operation(summary = "查询上游账号已授权酒店列表")
@GetMapping("/mid/authorizedHotels")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<Map<String, Object>> authorizedHotels(@RequestParam(required = false) String keyword,
@RequestParam(required = false, defaultValue = "1") long current,
@RequestParam(required = false, defaultValue = "20") long size,
@@ -108,7 +108,7 @@ public class CanteenHotelMidController {
@SysLog("导入上游授权酒店到本地")
@Operation(summary = "将上游授权酒店写入本地")
@PostMapping("/mid/authorizedHotels/import")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_add')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_add')")
public R<Map<String, Object>> importAuthorizedHotels(@RequestBody List<Map<String, Object>> hotels) {
return midService.importAuthorizedHotels(hotels);
}
@@ -116,7 +116,7 @@ public class CanteenHotelMidController {
@SysLog("同步上游酒店列表并差集")
@Operation(summary = "异步同步 getHotelList + Redis 差集(立刻返回 logId,轮询进度)")
@PostMapping("/mid/syncHotelList")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_edit')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_edit')")
public R<Map<String, Object>> syncHotelList(
@RequestParam(required = false, defaultValue = "true") boolean autoImport) {
return syncService.syncHotelListAndDiff(autoImport);
@@ -124,29 +124,29 @@ public class CanteenHotelMidController {
@Operation(summary = "同步日志分页")
@GetMapping("/mid/syncLog/page")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
public R<Page<CanteenHotelSyncLogEntity>> syncLogPage(@ParameterObject Page<CanteenHotelSyncLogEntity> page,
@ParameterObject CanteenHotelSyncLogEntity query) {
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<Page<SmHotelSyncLogEntity>> syncLogPage(@ParameterObject Page<SmHotelSyncLogEntity> page,
@ParameterObject SmHotelSyncLogEntity query) {
return R.ok(syncService.pageSyncLogs(page, query));
}
@Operation(summary = "查询单次同步进度/结果")
@GetMapping("/mid/syncLog/{id}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
public R<CanteenHotelSyncLogEntity> syncLog(@PathVariable Long id) {
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<SmHotelSyncLogEntity> syncLog(@PathVariable Long id) {
return syncService.getSyncLog(id);
}
@Operation(summary = "日更时间配置(只读展示)")
@GetMapping("/mid/syncSchedule")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<Map<String, Object>> syncSchedule() {
return R.ok(syncService.getSyncSchedule());
}
@Operation(summary = "分页查看酒店差集 new|offline")
@GetMapping("/mid/hotelDiff")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<Map<String, Object>> hotelDiff(@RequestParam(required = false, defaultValue = "new") String type,
@RequestParam(required = false, defaultValue = "1") long current,
@RequestParam(required = false, defaultValue = "20") long size) {
@@ -156,7 +156,7 @@ public class CanteenHotelMidController {
@SysLog("导入差集新增酒店")
@Operation(summary = "将差集中的新增酒店导入本地")
@PostMapping("/mid/hotelDiff/importNew")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_add')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_add')")
public R<Map<String, Object>> importDiffNew(@RequestParam(required = false) Integer limit) {
return syncService.importDiffNewHotels(limit);
}
@@ -164,9 +164,9 @@ public class CanteenHotelMidController {
@SysLog("手动执行滚一天房价")
@Operation(summary = "异步滚一天房价(立刻返回 logId)")
@PostMapping("/mid/rollDailyPrice")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_edit')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_edit')")
public R<Map<String, Object>> rollDailyPrice() {
R<CanteenHotelSyncLogEntity> started = syncService.startPriceRollAsync("MANUAL");
R<SmHotelSyncLogEntity> started = syncService.startPriceRollAsync("MANUAL");
if (started.getCode() != 0) {
return R.failed(started.getMsg());
}
@@ -180,10 +180,10 @@ public class CanteenHotelMidController {
@SysLog("全量拉取启用酒店详情")
@Operation(summary = "异步拉取全部启用酒店详情(房型+产品+未来房价),立刻返回 logId")
@PostMapping("/mid/pullAllActiveDetails")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_edit')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_edit')")
public R<Map<String, Object>> pullAllActiveDetails(
@RequestParam(required = false) Integer limit) {
R<CanteenHotelSyncLogEntity> started = syncService.startDetailPullAsync(limit, "MANUAL");
R<SmHotelSyncLogEntity> started = syncService.startDetailPullAsync(limit, "MANUAL");
if (started.getCode() != 0) {
return R.failed(started.getMsg());
}
@@ -198,9 +198,9 @@ public class CanteenHotelMidController {
@SysLog("重试同步失败酒店")
@Operation(summary = "根据某次同步日志的失败明细,只重试失败酒店(详情/滚价)")
@PostMapping("/mid/retryFailedFromLog")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_edit')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_edit')")
public R<Map<String, Object>> retryFailedFromLog(@RequestParam Long logId) {
R<CanteenHotelSyncLogEntity> started = syncService.startRetryFailedAsync(logId);
R<SmHotelSyncLogEntity> started = syncService.startRetryFailedAsync(logId);
if (started.getCode() != 0) {
return R.failed(started.getMsg());
}
@@ -1,8 +1,8 @@
package com.bsd.pjcloud.canteen.controller;
package com.bsd.pjcloud.supermarket.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.canteen.entity.CanteenHotelOrderEntity;
import com.bsd.pjcloud.canteen.service.CanteenHotelOrderService;
import com.bsd.pjcloud.supermarket.entity.SmHotelOrderEntity;
import com.bsd.pjcloud.supermarket.service.SmHotelOrderService;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import io.swagger.v3.oas.annotations.Operation;
@@ -18,32 +18,32 @@ import java.util.Map;
@RestController
@RequiredArgsConstructor
@RequestMapping("/canteenHotelOrder")
@RequestMapping("/smHotelOrder")
@Tag(name = "酒店中转订单")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class CanteenHotelOrderController {
public class SmHotelOrderController {
private final CanteenHotelOrderService orderService;
private final SmHotelOrderService orderService;
@Operation(summary = "订单分页")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotelOrder_view')")
public R<Page<CanteenHotelOrderEntity>> page(@ParameterObject Page<CanteenHotelOrderEntity> page,
@ParameterObject CanteenHotelOrderEntity query) {
@PreAuthorize("@pms.hasPermission('supermarket_smHotelOrder_view')")
public R<Page<SmHotelOrderEntity>> page(@ParameterObject Page<SmHotelOrderEntity> page,
@ParameterObject SmHotelOrderEntity query) {
return R.ok(orderService.pageOrders(page, query));
}
@Operation(summary = "订单详情")
@GetMapping("/{id}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotelOrder_view')")
public R<CanteenHotelOrderEntity> detail(@PathVariable Long id) {
@PreAuthorize("@pms.hasPermission('supermarket_smHotelOrder_view')")
public R<SmHotelOrderEntity> detail(@PathVariable Long id) {
return R.ok(orderService.getDetail(id));
}
@SysLog("后台取消酒店订单")
@Operation(summary = "后台取消订单")
@PostMapping("/cancel/{id}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotelOrder_cancel')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotelOrder_cancel')")
public R<Boolean> cancel(@PathVariable Long id, @RequestBody(required = false) Map<String, Object> body) {
String reason = body == null ? null : String.valueOf(body.getOrDefault("reason", "后台取消"));
return orderService.cancelByAdmin(id, reason);
@@ -52,7 +52,7 @@ public class CanteenHotelOrderController {
@SysLog("后台试下单(调上游)")
@Operation(summary = "后台试下单:校验可定后调上游 order/add")
@PostMapping("/create")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_edit')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_edit')")
public R<cn.hutool.json.JSONObject> createByAdmin(@RequestBody Map<String, Object> body) {
return orderService.createByAdmin(body);
}
@@ -60,7 +60,7 @@ public class CanteenHotelOrderController {
@SysLog("酒店订单补偿查询")
@Operation(summary = "立即补偿查询(queryByRequestNo)")
@PostMapping("/compensate/{id}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotelOrder_view')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotelOrder_view')")
public R<Boolean> compensate(@PathVariable Long id) {
return orderService.compensateNow(id);
}
@@ -1,7 +1,7 @@
package com.bsd.pjcloud.canteen.controller;
package com.bsd.pjcloud.supermarket.controller;
import cn.hutool.json.JSONObject;
import com.bsd.pjcloud.canteen.service.CanteenHotelUpstreamService;
import com.bsd.pjcloud.supermarket.service.SmHotelUpstreamService;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.security.annotation.Inner;
import io.swagger.v3.oas.annotations.Operation;
@@ -20,44 +20,44 @@ import java.util.Map;
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/canteenHotel/upstream")
@RequestMapping("/smHotel/upstream")
@Tag(name = "酒店上游对接")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class CanteenHotelUpstreamController {
public class SmHotelUpstreamController {
private final CanteenHotelUpstreamService upstreamService;
private final SmHotelUpstreamService upstreamService;
@Operation(summary = "同步上游酒店信息到本地")
@PostMapping("/sync/{id}")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_edit')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_edit')")
public R<JSONObject> sync(@PathVariable Long id) {
return upstreamService.syncHotelInfo(id);
}
@Operation(summary = "批量同步上游酒店信息")
@PostMapping("/sync/batch")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_edit')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_edit')")
public R<Map<String, Object>> syncBatch(@RequestBody List<Long> ids) {
return upstreamService.syncHotelInfoBatch(ids);
}
@Operation(summary = "上游-酒店综合信息")
@PostMapping("/hotelInfo")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<JSONObject> hotelInfo(@RequestBody Map<String, Object> body) {
return upstreamService.hotelInfo(str(body.get("groupCode")), str(body.get("hotelCode")));
}
@Operation(summary = "上游-房型列表")
@PostMapping("/roomTypeList")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<JSONObject> roomTypeList(@RequestBody Map<String, Object> body) {
return upstreamService.roomTypeList(str(body.get("groupCode")), str(body.get("hotelCode")));
}
@Operation(summary = "上游-房价房量样例")
@PostMapping("/productList")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<JSONObject> productList(@RequestBody Map<String, Object> body) {
return upstreamService.productList(str(body.get("groupCode")), str(body.get("hotelCode")),
str(body.get("channelCode")));
@@ -65,28 +65,28 @@ public class CanteenHotelUpstreamController {
@Operation(summary = "上游-可定查询")
@PostMapping("/order/check")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<JSONObject> orderCheck(@RequestBody Map<String, Object> body) {
return upstreamService.orderCheck(body);
}
@Operation(summary = "上游-下单")
@PostMapping("/order/create")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_edit')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_edit')")
public R<JSONObject> orderCreate(@RequestBody Map<String, Object> body) {
return upstreamService.orderCreate(body);
}
@Operation(summary = "上游-取消订单")
@PostMapping("/order/cancel")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_edit')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_edit')")
public R<JSONObject> orderCancel(@RequestBody Map<String, Object> body) {
return upstreamService.orderCancel(body);
}
@Operation(summary = "上游-订单详情")
@PostMapping("/order/getById")
@PreAuthorize("@pms.hasPermission('canteen_canteenHotel_view')")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_view')")
public R<JSONObject> orderGetById(@RequestBody Map<String, Object> body) {
return upstreamService.orderGetById(body);
}
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.integration.downstream;
package com.bsd.pjcloud.supermarket.integration.downstream;
/**
* 下游销售方(B系统)接收接口路径。
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.integration.downstream;
package com.bsd.pjcloud.supermarket.integration.downstream;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
@@ -6,7 +6,7 @@ import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.bsd.pjcloud.canteen.config.HotelDownstreamProperties;
import com.bsd.pjcloud.supermarket.config.HotelDownstreamProperties;
import com.bsd.pjcloud.common.core.exception.CheckedException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -1,10 +1,10 @@
package com.bsd.pjcloud.canteen.integration.downstream;
package com.bsd.pjcloud.supermarket.integration.downstream;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bsd.pjcloud.canteen.entity.CanteenHotelDownstreamAppEntity;
import com.bsd.pjcloud.canteen.mapper.CanteenHotelDownstreamAppMapper;
import com.bsd.pjcloud.supermarket.entity.SmHotelDownstreamAppEntity;
import com.bsd.pjcloud.supermarket.mapper.SmHotelDownstreamAppMapper;
import com.bsd.pjcloud.common.core.exception.CheckedException;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
@@ -21,11 +21,11 @@ public class DownstreamInboundAuth {
private static final String NONCE_KEY = "canteen:hotel:downstream:nonce:";
private final CanteenHotelDownstreamAppMapper appMapper;
private final SmHotelDownstreamAppMapper appMapper;
private final StringRedisTemplate redisTemplate;
public CanteenHotelDownstreamAppEntity verify(String appKey, String timestamp, String nonce, String sign,
public SmHotelDownstreamAppEntity verify(String appKey, String timestamp, String nonce, String sign,
String bodyJson) {
if (StrUtil.isBlank(appKey) || StrUtil.isBlank(timestamp) || StrUtil.isBlank(nonce) || StrUtil.isBlank(sign)) {
throw new CheckedException("缺少鉴权参数");
@@ -44,9 +44,9 @@ public class DownstreamInboundAuth {
if (Boolean.FALSE.equals(ok)) {
throw new CheckedException("nonce 重复");
}
CanteenHotelDownstreamAppEntity app = appMapper.selectOne(Wrappers.<CanteenHotelDownstreamAppEntity>lambdaQuery()
.eq(CanteenHotelDownstreamAppEntity::getAppKey, appKey)
.eq(CanteenHotelDownstreamAppEntity::getStatus, "1")
SmHotelDownstreamAppEntity app = appMapper.selectOne(Wrappers.<SmHotelDownstreamAppEntity>lambdaQuery()
.eq(SmHotelDownstreamAppEntity::getAppKey, appKey)
.eq(SmHotelDownstreamAppEntity::getStatus, "1")
.last("limit 1"));
if (app == null) {
throw new CheckedException("appKey 无效");
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.integration.downstream;
package com.bsd.pjcloud.supermarket.integration.downstream;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.core.util.StrUtil;
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.integration.shangyou;
package com.bsd.pjcloud.supermarket.integration.shangyou;
import cn.hutool.core.util.StrUtil;
@@ -1,7 +1,7 @@
package com.bsd.pjcloud.canteen.integration.shangyou;
package com.bsd.pjcloud.supermarket.integration.shangyou;
import com.bsd.pjcloud.canteen.config.ShangyouHotelProperties;
import com.bsd.pjcloud.canteen.service.CanteenHotelCallbackTaskService;
import com.bsd.pjcloud.supermarket.config.ShangyouHotelProperties;
import com.bsd.pjcloud.supermarket.service.SmHotelCallbackTaskService;
import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -26,7 +26,7 @@ public class ShangyouCallbackQueueWorker implements ApplicationRunner {
private final StringRedisTemplate redisTemplate;
private final CanteenHotelCallbackTaskService callbackTaskService;
private final SmHotelCallbackTaskService callbackTaskService;
private final AtomicBoolean running = new AtomicBoolean(true);
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.integration.shangyou;
package com.bsd.pjcloud.supermarket.integration.shangyou;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.integration.shangyou;
package com.bsd.pjcloud.supermarket.integration.shangyou;
/**
* 玉编电云 CRS 上游路径(相对 biz-base-url / auth-base-url)。
@@ -24,40 +24,40 @@ public final class ShangyouHotelApi {
public static final String ORDER_QUERY_BY_REQUEST_NO = "/order/queryByRequestNo";
public static final String REDIS_TOKEN_KEY = "canteen:shangyou:hotel:token";
public static final String REDIS_TOKEN_KEY = "supermarket:shangyou:hotel:token";
public static final String REDIS_TOKEN_LOCK = "canteen:shangyou:hotel:token:lock";
public static final String REDIS_TOKEN_LOCK = "supermarket:shangyou:hotel:token:lock";
/** 授权酒店 HASH:field=hotelId value=hotelName(适配十几万量级) */
public static final String REDIS_HOTEL_HASH_KEY = "canteen:shangyou:hotel:hash:v4";
public static final String REDIS_HOTEL_HASH_KEY = "supermarket:shangyou:hotel:hash:v4";
/** 授权酒店 ZSET:score=序号 member=hotelId,深分页 O(logN) */
public static final String REDIS_HOTEL_ZSET_KEY = "canteen:shangyou:hotel:zset:v4";
public static final String REDIS_HOTEL_ZSET_KEY = "supermarket:shangyou:hotel:zset:v4";
/** 酒店列表同步锁 */
public static final String REDIS_HOTEL_LIST_LOCK = "canteen:shangyou:hotel:list:lock";
public static final String REDIS_HOTEL_LIST_LOCK = "supermarket:shangyou:hotel:list:lock";
/** 房价/房量回调异步队列(LIST,元素=taskId) */
public static final String REDIS_CALLBACK_QUEUE = "canteen:shangyou:hotel:callback:queue";
public static final String REDIS_CALLBACK_QUEUE = "supermarket:shangyou:hotel:callback:queue";
/** 上游授权 hotelId 集合(与 HASH/ZSET 同步重建,供 SDIFF) */
public static final String REDIS_UPSTREAM_ID_SET = "canteen:shangyou:hotel:idset:v4";
public static final String REDIS_UPSTREAM_ID_SET = "supermarket:shangyou:hotel:idset:v4";
/** 本地 hotel_code 集合(分批从 DB 重建) */
public static final String REDIS_LOCAL_CODE_SET = "canteen:shangyou:hotel:local:codes:v1";
public static final String REDIS_LOCAL_CODE_SET = "supermarket:shangyou:hotel:local:codes:v1";
/** 差集:上游有本地无(待导入) */
public static final String REDIS_DIFF_NEW_SET = "canteen:shangyou:hotel:diff:new:v1";
public static final String REDIS_DIFF_NEW_SET = "supermarket:shangyou:hotel:diff:new:v1";
/** 差集:本地有上游无(疑似下线) */
public static final String REDIS_DIFF_OFFLINE_SET = "canteen:shangyou:hotel:diff:offline:v1";
public static final String REDIS_DIFF_OFFLINE_SET = "supermarket:shangyou:hotel:diff:offline:v1";
/** 今日全量房价同步次数 */
public static final String REDIS_FULL_PRICE_SYNC_COUNT = "canteen:shangyou:hotel:fullprice:count";
public static final String REDIS_FULL_PRICE_SYNC_COUNT = "supermarket:shangyou:hotel:fullprice:count";
/** 上次全量房价同步时间 epochMs */
public static final String REDIS_FULL_PRICE_SYNC_LAST = "canteen:shangyou:hotel:fullprice:last";
public static final String REDIS_FULL_PRICE_SYNC_LAST = "supermarket:shangyou:hotel:fullprice:last";
/** 房价接口 QPS 秒窗计数前缀,完整 key = 前缀 + ":" + epochSecond */
public static final String REDIS_PRICE_QPS_PREFIX = "canteen:shangyou:hotel:price:qps";
public static final String REDIS_PRICE_QPS_PREFIX = "supermarket:shangyou:hotel:price:qps";
}
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.integration.shangyou;
package com.bsd.pjcloud.supermarket.integration.shangyou;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
@@ -6,7 +6,7 @@ import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsd.pjcloud.canteen.config.ShangyouHotelProperties;
import com.bsd.pjcloud.supermarket.config.ShangyouHotelProperties;
import com.bsd.pjcloud.common.core.exception.CheckedException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -261,8 +261,8 @@ public class ShangyouHotelClient {
redisTemplate.delete(ShangyouHotelApi.REDIS_HOTEL_ZSET_KEY);
redisTemplate.delete(ShangyouHotelApi.REDIS_UPSTREAM_ID_SET);
// 兼容清理旧版 LIST/压缩缓存 key
redisTemplate.delete("canteen:shangyou:hotel:list:v3");
redisTemplate.delete("canteen:shangyou:hotel:list:v2");
redisTemplate.delete("supermarket:shangyou:hotel:list:v3");
redisTemplate.delete("supermarket:shangyou:hotel:list:v2");
}
private List<HotelBrief> loadBriefsByIds(Set<String> ids) {
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.integration.shangyou;
package com.bsd.pjcloud.supermarket.integration.shangyou;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
@@ -1,7 +1,7 @@
package com.bsd.pjcloud.canteen.integration.shangyou;
package com.bsd.pjcloud.supermarket.integration.shangyou;
import com.bsd.pjcloud.canteen.config.ShangyouHotelProperties;
import com.bsd.pjcloud.canteen.service.CanteenHotelOrderService;
import com.bsd.pjcloud.supermarket.config.ShangyouHotelProperties;
import com.bsd.pjcloud.supermarket.service.SmHotelOrderService;
import com.bsd.pjcloud.common.data.tenant.TenantBroker;
import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
@@ -22,7 +22,7 @@ public class ShangyouOrderCompensateWorker implements ApplicationRunner {
private final ShangyouHotelProperties properties;
private final CanteenHotelOrderService orderService;
private final SmHotelOrderService orderService;
private final AtomicBoolean running = new AtomicBoolean(true);
@@ -1,7 +1,7 @@
package com.bsd.pjcloud.canteen.job;
package com.bsd.pjcloud.supermarket.job;
import com.bsd.pjcloud.canteen.config.ShangyouHotelProperties;
import com.bsd.pjcloud.canteen.service.CanteenHotelSyncService;
import com.bsd.pjcloud.supermarket.config.ShangyouHotelProperties;
import com.bsd.pjcloud.supermarket.service.SmHotelSyncService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
@@ -16,11 +16,11 @@ import org.springframework.stereotype.Component;
@Slf4j
@Component
@RequiredArgsConstructor
public class CanteenHotelShangyouSpringSchedule {
public class SmHotelShangyouSpringSchedule {
private final ShangyouHotelProperties properties;
private final CanteenHotelSyncService syncService;
private final SmHotelSyncService syncService;
@Scheduled(cron = "${shangyou-hotel.hotel-list-daily-cron:0 0 2 * * ?}")
public void scheduledListSync() {
@@ -1,6 +1,6 @@
package com.bsd.pjcloud.canteen.job;
package com.bsd.pjcloud.supermarket.job;
import com.bsd.pjcloud.canteen.service.CanteenHotelSyncService;
import com.bsd.pjcloud.supermarket.service.SmHotelSyncService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
@@ -20,36 +20,36 @@ import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class CanteenHotelShangyouSyncJob {
public class SmHotelShangyouSyncJob {
public static final String HANDLER_LIST_SYNC = "canteenHotelListSyncJobHandler";
public static final String HANDLER_LIST_SYNC = "smHotelListSyncJobHandler";
public static final String HANDLER_PRICE_ROLL = "canteenHotelPriceRollJobHandler";
public static final String HANDLER_PRICE_ROLL = "smHotelPriceRollJobHandler";
private final CanteenHotelSyncService syncService;
private final SmHotelSyncService syncService;
@XxlJob(HANDLER_LIST_SYNC)
public void canteenHotelListSyncJobHandler() {
public void smHotelListSyncJobHandler() {
try {
Map<String, Object> r = syncService.jobSyncHotelList();
XxlJobHelper.log("hotel list sync: " + r);
XxlJobHelper.handleSuccess(String.valueOf(r));
}
catch (Exception e) {
log.error("canteenHotelListSyncJobHandler 异常", e);
log.error("smHotelListSyncJobHandler 异常", e);
XxlJobHelper.handleFail(e.getMessage());
}
}
@XxlJob(HANDLER_PRICE_ROLL)
public void canteenHotelPriceRollJobHandler() {
public void smHotelPriceRollJobHandler() {
try {
Map<String, Object> r = syncService.jobRollDailyPrice();
XxlJobHelper.log("hotel price roll: " + r);
XxlJobHelper.handleSuccess(String.valueOf(r));
}
catch (Exception e) {
log.error("canteenHotelPriceRollJobHandler 异常", e);
log.error("smHotelPriceRollJobHandler 异常", e);
XxlJobHelper.handleFail(e.getMessage());
}
}
@@ -0,0 +1,9 @@
package com.bsd.pjcloud.supermarket.mapper;
import com.bsd.pjcloud.supermarket.entity.SmHotelCallbackTaskEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SmHotelCallbackTaskMapper extends PjcloudBaseMapper<SmHotelCallbackTaskEntity> {
}
@@ -1,6 +1,6 @@
package com.bsd.pjcloud.canteen.mapper;
package com.bsd.pjcloud.supermarket.mapper;
import com.bsd.pjcloud.canteen.entity.CanteenHotelDailyEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelDailyEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
@@ -13,7 +13,7 @@ import java.util.List;
import java.util.Map;
@Mapper
public interface CanteenHotelDailyMapper extends PjcloudBaseMapper<CanteenHotelDailyEntity> {
public interface SmHotelDailyMapper extends PjcloudBaseMapper<SmHotelDailyEntity> {
/**
* 物理删除未来日历。唯一键 uk_product_date 不含 del_flag,软删后再插入会冲突。
@@ -21,7 +21,7 @@ public interface CanteenHotelDailyMapper extends PjcloudBaseMapper<CanteenHotelD
@Delete("DELETE FROM canteen_hotel_daily WHERE hotel_id = #{hotelId} AND stay_date >= #{fromDate}")
int physicalDeleteFromDate(@Param("hotelId") Long hotelId, @Param("fromDate") LocalDate fromDate);
int insertBatch(@Param("list") List<CanteenHotelDailyEntity> list);
int insertBatch(@Param("list") List<SmHotelDailyEntity> list);
@Select("""
<script>
@@ -0,0 +1,9 @@
package com.bsd.pjcloud.supermarket.mapper;
import com.bsd.pjcloud.supermarket.entity.SmHotelDownstreamAppEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SmHotelDownstreamAppMapper extends PjcloudBaseMapper<SmHotelDownstreamAppEntity> {
}
@@ -0,0 +1,14 @@
package com.bsd.pjcloud.supermarket.mapper;
import com.bsd.pjcloud.supermarket.entity.SmHotelEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface SmHotelMapper extends PjcloudBaseMapper<SmHotelEntity> {
int insertBatch(@Param("list") List<SmHotelEntity> list);
}
@@ -0,0 +1,9 @@
package com.bsd.pjcloud.supermarket.mapper;
import com.bsd.pjcloud.supermarket.entity.SmHotelOrderEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SmHotelOrderMapper extends PjcloudBaseMapper<SmHotelOrderEntity> {
}
@@ -0,0 +1,9 @@
package com.bsd.pjcloud.supermarket.mapper;
import com.bsd.pjcloud.supermarket.entity.SmHotelPriceConfigEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SmHotelPriceConfigMapper extends PjcloudBaseMapper<SmHotelPriceConfigEntity> {
}
@@ -1,6 +1,6 @@
package com.bsd.pjcloud.canteen.mapper;
package com.bsd.pjcloud.supermarket.mapper;
import com.bsd.pjcloud.canteen.entity.CanteenHotelProductEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelProductEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -11,9 +11,9 @@ import java.util.List;
import java.util.Map;
@Mapper
public interface CanteenHotelProductMapper extends PjcloudBaseMapper<CanteenHotelProductEntity> {
public interface SmHotelProductMapper extends PjcloudBaseMapper<SmHotelProductEntity> {
int insertBatch(@Param("list") List<CanteenHotelProductEntity> list);
int insertBatch(@Param("list") List<SmHotelProductEntity> list);
@Select("""
<script>
@@ -1,6 +1,6 @@
package com.bsd.pjcloud.canteen.mapper;
package com.bsd.pjcloud.supermarket.mapper;
import com.bsd.pjcloud.canteen.entity.CanteenHotelRoomEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelRoomEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -11,9 +11,9 @@ import java.util.List;
import java.util.Map;
@Mapper
public interface CanteenHotelRoomMapper extends PjcloudBaseMapper<CanteenHotelRoomEntity> {
public interface SmHotelRoomMapper extends PjcloudBaseMapper<SmHotelRoomEntity> {
int insertBatch(@Param("list") List<CanteenHotelRoomEntity> list);
int insertBatch(@Param("list") List<SmHotelRoomEntity> list);
@Select("""
<script>
@@ -0,0 +1,9 @@
package com.bsd.pjcloud.supermarket.mapper;
import com.bsd.pjcloud.supermarket.entity.SmHotelSyncLogEntity;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SmHotelSyncLogMapper extends PjcloudBaseMapper<SmHotelSyncLogEntity> {
}
@@ -1,7 +1,7 @@
package com.bsd.pjcloud.canteen.service;
package com.bsd.pjcloud.supermarket.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.canteen.entity.CanteenHotelCallbackTaskEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelCallbackTaskEntity;
import com.bsd.pjcloud.common.core.util.R;
import java.util.Map;
@@ -9,7 +9,7 @@ import java.util.Map;
/**
* 上游房价/房量回调:落库入队 + 异步拉取 + 后台查询。
*/
public interface CanteenHotelCallbackTaskService {
public interface SmHotelCallbackTaskService {
/**
* 验签通过后调用:只落库 + 入 Redis 队列,不做上游拉取。
@@ -18,10 +18,10 @@ public interface CanteenHotelCallbackTaskService {
Map<String, Object> enqueueFromNotify(String notifyType, Map<String, Object> body, String time, String sign);
/** 后台分页 */
Page<CanteenHotelCallbackTaskEntity> pageTasks(Page<CanteenHotelCallbackTaskEntity> page,
CanteenHotelCallbackTaskEntity query);
Page<SmHotelCallbackTaskEntity> pageTasks(Page<SmHotelCallbackTaskEntity> page,
SmHotelCallbackTaskEntity query);
CanteenHotelCallbackTaskEntity getDetail(Long id);
SmHotelCallbackTaskEntity getDetail(Long id);
/** 失败/跳过任务重新入队 */
R<Boolean> retry(Long id);
@@ -1,8 +1,8 @@
package com.bsd.pjcloud.canteen.service;
package com.bsd.pjcloud.supermarket.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.canteen.entity.CanteenHotelDailyEntity;
import com.bsd.pjcloud.canteen.vo.CanteenHotelDetailVO;
import com.bsd.pjcloud.supermarket.entity.SmHotelDailyEntity;
import com.bsd.pjcloud.supermarket.vo.SmHotelDetailVO;
import com.bsd.pjcloud.common.core.util.R;
import java.util.List;
@@ -11,7 +11,7 @@ import java.util.Map;
/**
* 上游拉取落库 + 加价后推下游。
*/
public interface CanteenHotelMidService {
public interface SmHotelMidService {
/** 从上游拉取房型/产品并按加价生成日历,落本地库 */
R<Map<String, Object>> pullFromUpstream(Long hotelId);
@@ -30,10 +30,10 @@ public interface CanteenHotelMidService {
R<Map<String, Object>> pullAndPushBatch(List<Long> hotelIds);
/** 酒店详情:主数据 + 已拉取的房型/产品/日历预览 */
R<CanteenHotelDetailVO> getHotelDetail(Long hotelId);
R<SmHotelDetailVO> getHotelDetail(Long hotelId);
/** 日历分页 */
R<Page<CanteenHotelDailyEntity>> pageDaily(Long hotelId, Page<CanteenHotelDailyEntity> page, String productCode);
R<Page<SmHotelDailyEntity>> pageDaily(Long hotelId, Page<SmHotelDailyEntity> page, String productCode);
/** 查询当前上游账号已授权酒店列表(getHotelList,支持关键字与分页) */
R<Map<String, Object>> listAuthorizedHotels(String keyword, long current, long size, boolean refresh);
@@ -1,17 +1,17 @@
package com.bsd.pjcloud.canteen.service;
package com.bsd.pjcloud.supermarket.service;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.canteen.entity.CanteenHotelOrderEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelOrderEntity;
import com.bsd.pjcloud.common.core.util.R;
import java.util.Map;
public interface CanteenHotelOrderService {
public interface SmHotelOrderService {
Page<CanteenHotelOrderEntity> pageOrders(Page<CanteenHotelOrderEntity> page, CanteenHotelOrderEntity query);
Page<SmHotelOrderEntity> pageOrders(Page<SmHotelOrderEntity> page, SmHotelOrderEntity query);
CanteenHotelOrderEntity getDetail(Long id);
SmHotelOrderEntity getDetail(Long id);
/** 下游回传下单 → 可定校验 → 上游创建 → 必要时挂补偿 */
R<JSONObject> createFromDownstream(String appKey, Map<String, Object> body);
@@ -0,0 +1,19 @@
package com.bsd.pjcloud.supermarket.service;
import com.bsd.pjcloud.supermarket.entity.SmHotelPriceConfigEntity;
import com.bsd.pjcloud.common.core.util.R;
import java.math.BigDecimal;
public interface SmHotelPriceConfigService {
R<SmHotelPriceConfigEntity> getCurrent();
R<Boolean> saveOrUpdateConfig(SmHotelPriceConfigEntity entity);
/** 当前加价百分比,未配置返回 0 */
BigDecimal currentMarkupPercent();
/** 底价按加价百分比计算卖价 */
BigDecimal applyMarkup(BigDecimal costPrice);
}
@@ -0,0 +1,26 @@
package com.bsd.pjcloud.supermarket.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.supermarket.entity.SmHotelEntity;
import com.bsd.pjcloud.supermarket.vo.SmHotelImportResultVO;
import com.bsd.pjcloud.common.core.util.R;
import org.springframework.web.multipart.MultipartFile;
public interface SmHotelService extends IService<SmHotelEntity> {
Page<SmHotelEntity> pageScope(Page<SmHotelEntity> page, LambdaQueryWrapper<SmHotelEntity> wrapper);
Boolean saveHotel(SmHotelEntity entity);
Boolean updateHotel(SmHotelEntity entity);
Boolean removeHotels(Long[] ids);
/** 提交异步导入,立刻返回 taskId(status=RUNNING) */
R<SmHotelImportResultVO> startImport(MultipartFile file);
/** 查询导入任务进度 */
R<SmHotelImportResultVO> getImportStatus(String taskId);
}
@@ -1,7 +1,7 @@
package com.bsd.pjcloud.canteen.service;
package com.bsd.pjcloud.supermarket.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.canteen.entity.CanteenHotelSyncLogEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelSyncLogEntity;
import com.bsd.pjcloud.common.core.util.R;
import java.util.Map;
@@ -9,20 +9,20 @@ import java.util.Map;
/**
* 上游酒店列表日更、Redis 差集、滚一天房价(异步 + 进度日志)。
*/
public interface CanteenHotelSyncService {
public interface SmHotelSyncService {
/**
* 提交列表同步(立刻返回 logId,后台异步执行)。
* @param autoImport 是否自动导入新增
* @param triggerType MANUAL / XXL / CRON
*/
R<CanteenHotelSyncLogEntity> startListSyncAsync(boolean autoImport, String triggerType);
R<SmHotelSyncLogEntity> startListSyncAsync(boolean autoImport, String triggerType);
/** 查询同步任务进度/结果 */
R<CanteenHotelSyncLogEntity> getSyncLog(Long id);
R<SmHotelSyncLogEntity> getSyncLog(Long id);
/** 同步日志分页 */
Page<CanteenHotelSyncLogEntity> pageSyncLogs(Page<CanteenHotelSyncLogEntity> page, CanteenHotelSyncLogEntity query);
Page<SmHotelSyncLogEntity> pageSyncLogs(Page<SmHotelSyncLogEntity> page, SmHotelSyncLogEntity query);
/** 分页查看差集:type=new|offline */
R<Map<String, Object>> pageHotelDiff(String type, long current, long size);
@@ -31,18 +31,18 @@ public interface CanteenHotelSyncService {
R<Map<String, Object>> importDiffNewHotels(Integer limit);
/** 提交滚价异步任务 */
R<CanteenHotelSyncLogEntity> startPriceRollAsync(String triggerType);
R<SmHotelSyncLogEntity> startPriceRollAsync(String triggerType);
/**
* 异步拉取全部启用酒店详情(房型+产品+未来 price-days 房价)。
* @param limit 最多处理家数,null/≤0 用配置 detail-pull-max-hotels(0=不限)
*/
R<CanteenHotelSyncLogEntity> startDetailPullAsync(Integer limit, String triggerType);
R<SmHotelSyncLogEntity> startDetailPullAsync(Integer limit, String triggerType);
/**
* 根据某次同步日志的 failDetail,只重试失败酒店(支持 DETAIL_PULL / PRICE_ROLL)。
*/
R<CanteenHotelSyncLogEntity> startRetryFailedAsync(Long sourceLogId);
R<SmHotelSyncLogEntity> startRetryFailedAsync(Long sourceLogId);
/** 兼容旧同步入口(内部转异步) */
R<Map<String, Object>> syncHotelListAndDiff(boolean autoImport);
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.service;
package com.bsd.pjcloud.supermarket.service;
import cn.hutool.json.JSONObject;
import com.bsd.pjcloud.common.core.util.R;
@@ -9,7 +9,7 @@ import java.util.Map;
/**
* 玉编电云酒店上游对接(查询/同步/下单代理)。
*/
public interface CanteenHotelUpstreamService {
public interface SmHotelUpstreamService {
/** 按本地酒店主键拉取上游综合信息并回写名称等 */
R<JSONObject> syncHotelInfo(Long hotelId);
@@ -1,20 +1,20 @@
package com.bsd.pjcloud.canteen.service.impl;
package com.bsd.pjcloud.supermarket.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.canteen.config.ShangyouHotelProperties;
import com.bsd.pjcloud.canteen.entity.CanteenHotelCallbackTaskEntity;
import com.bsd.pjcloud.canteen.entity.CanteenHotelEntity;
import com.bsd.pjcloud.canteen.integration.shangyou.ShangyouCallbackSignHelper;
import com.bsd.pjcloud.canteen.integration.shangyou.ShangyouHotelApi;
import com.bsd.pjcloud.canteen.integration.shangyou.ShangyouHotelClient;
import com.bsd.pjcloud.canteen.mapper.CanteenHotelCallbackTaskMapper;
import com.bsd.pjcloud.canteen.mapper.CanteenHotelMapper;
import com.bsd.pjcloud.canteen.service.CanteenHotelCallbackTaskService;
import com.bsd.pjcloud.canteen.service.CanteenHotelMidService;
import com.bsd.pjcloud.canteen.service.CanteenHotelOrderService;
import com.bsd.pjcloud.supermarket.config.ShangyouHotelProperties;
import com.bsd.pjcloud.supermarket.entity.SmHotelCallbackTaskEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelEntity;
import com.bsd.pjcloud.supermarket.integration.shangyou.ShangyouCallbackSignHelper;
import com.bsd.pjcloud.supermarket.integration.shangyou.ShangyouHotelApi;
import com.bsd.pjcloud.supermarket.integration.shangyou.ShangyouHotelClient;
import com.bsd.pjcloud.supermarket.mapper.SmHotelCallbackTaskMapper;
import com.bsd.pjcloud.supermarket.mapper.SmHotelMapper;
import com.bsd.pjcloud.supermarket.service.SmHotelCallbackTaskService;
import com.bsd.pjcloud.supermarket.service.SmHotelMidService;
import com.bsd.pjcloud.supermarket.service.SmHotelOrderService;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.tenant.TenantBroker;
import lombok.RequiredArgsConstructor;
@@ -32,7 +32,7 @@ import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class CanteenHotelCallbackTaskServiceImpl implements CanteenHotelCallbackTaskService {
public class SmHotelCallbackTaskServiceImpl implements SmHotelCallbackTaskService {
public static final String STATUS_PENDING = "PENDING";
@@ -48,13 +48,13 @@ public class CanteenHotelCallbackTaskServiceImpl implements CanteenHotelCallback
private final ShangyouHotelClient client;
private final CanteenHotelCallbackTaskMapper taskMapper;
private final SmHotelCallbackTaskMapper taskMapper;
private final CanteenHotelMapper hotelMapper;
private final SmHotelMapper hotelMapper;
private final CanteenHotelMidService midService;
private final SmHotelMidService midService;
private final CanteenHotelOrderService orderService;
private final SmHotelOrderService orderService;
private final StringRedisTemplate redisTemplate;
@@ -74,7 +74,7 @@ public class CanteenHotelCallbackTaskServiceImpl implements CanteenHotelCallback
Long tenantId = properties.getCallbackTenantId() == null ? 1L : properties.getCallbackTenantId();
try {
TenantBroker.runAs(tenantId, tid -> {
CanteenHotelCallbackTaskEntity task = buildTask(notifyType, body, time, tid);
SmHotelCallbackTaskEntity task = buildTask(notifyType, body, time, tid);
taskMapper.insert(task);
if (properties.isCallbackQueueEnabled()) {
redisTemplate.opsForList().leftPush(ShangyouHotelApi.REDIS_CALLBACK_QUEUE,
@@ -93,27 +93,27 @@ public class CanteenHotelCallbackTaskServiceImpl implements CanteenHotelCallback
}
@Override
public Page<CanteenHotelCallbackTaskEntity> pageTasks(Page<CanteenHotelCallbackTaskEntity> page,
CanteenHotelCallbackTaskEntity query) {
return taskMapper.selectPage(page, Wrappers.<CanteenHotelCallbackTaskEntity>lambdaQuery()
.eq(StrUtil.isNotBlank(query.getNotifyType()), CanteenHotelCallbackTaskEntity::getNotifyType,
public Page<SmHotelCallbackTaskEntity> pageTasks(Page<SmHotelCallbackTaskEntity> page,
SmHotelCallbackTaskEntity query) {
return taskMapper.selectPage(page, Wrappers.<SmHotelCallbackTaskEntity>lambdaQuery()
.eq(StrUtil.isNotBlank(query.getNotifyType()), SmHotelCallbackTaskEntity::getNotifyType,
query.getNotifyType())
.eq(StrUtil.isNotBlank(query.getStatus()), CanteenHotelCallbackTaskEntity::getStatus, query.getStatus())
.like(StrUtil.isNotBlank(query.getHotelCode()), CanteenHotelCallbackTaskEntity::getHotelCode,
.eq(StrUtil.isNotBlank(query.getStatus()), SmHotelCallbackTaskEntity::getStatus, query.getStatus())
.like(StrUtil.isNotBlank(query.getHotelCode()), SmHotelCallbackTaskEntity::getHotelCode,
query.getHotelCode())
.like(StrUtil.isNotBlank(query.getHotelName()), CanteenHotelCallbackTaskEntity::getHotelName,
.like(StrUtil.isNotBlank(query.getHotelName()), SmHotelCallbackTaskEntity::getHotelName,
query.getHotelName())
.orderByDesc(CanteenHotelCallbackTaskEntity::getCreateTime));
.orderByDesc(SmHotelCallbackTaskEntity::getCreateTime));
}
@Override
public CanteenHotelCallbackTaskEntity getDetail(Long id) {
public SmHotelCallbackTaskEntity getDetail(Long id) {
return taskMapper.selectById(id);
}
@Override
public R<Boolean> retry(Long id) {
CanteenHotelCallbackTaskEntity task = taskMapper.selectById(id);
SmHotelCallbackTaskEntity task = taskMapper.selectById(id);
if (task == null) {
return R.failed("任务不存在");
}
@@ -121,8 +121,8 @@ public class CanteenHotelCallbackTaskServiceImpl implements CanteenHotelCallback
return R.failed("任务处理中或已在队列,请稍候");
}
if (task.getHotelId() == null && StrUtil.isNotBlank(task.getHotelCode())) {
CanteenHotelEntity hotel = hotelMapper.selectOne(Wrappers.<CanteenHotelEntity>lambdaQuery()
.eq(CanteenHotelEntity::getHotelCode, task.getHotelCode())
SmHotelEntity hotel = hotelMapper.selectOne(Wrappers.<SmHotelEntity>lambdaQuery()
.eq(SmHotelEntity::getHotelCode, task.getHotelCode())
.last("limit 1"));
if (hotel != null) {
task.setHotelId(hotel.getId());
@@ -153,12 +153,12 @@ public class CanteenHotelCallbackTaskServiceImpl implements CanteenHotelCallback
public int requeueStalePending() {
Long tenantId = properties.getCallbackTenantId() == null ? 1L : properties.getCallbackTenantId();
return TenantBroker.applyAs(tenantId, tid -> {
var list = taskMapper.selectList(Wrappers.<CanteenHotelCallbackTaskEntity>lambdaQuery()
.eq(CanteenHotelCallbackTaskEntity::getStatus, STATUS_PENDING)
.orderByAsc(CanteenHotelCallbackTaskEntity::getCreateTime)
var list = taskMapper.selectList(Wrappers.<SmHotelCallbackTaskEntity>lambdaQuery()
.eq(SmHotelCallbackTaskEntity::getStatus, STATUS_PENDING)
.orderByAsc(SmHotelCallbackTaskEntity::getCreateTime)
.last("limit 200"));
int n = 0;
for (CanteenHotelCallbackTaskEntity t : list) {
for (SmHotelCallbackTaskEntity t : list) {
// 队尾恢复,避免一启动就顶着打
redisTemplate.opsForList().rightPush(ShangyouHotelApi.REDIS_CALLBACK_QUEUE, String.valueOf(t.getId()));
n++;
@@ -172,7 +172,7 @@ public class CanteenHotelCallbackTaskServiceImpl implements CanteenHotelCallback
/** @return true 成功或跳过;false 失败/待重试 */
private boolean doProcess(Long taskId) {
CanteenHotelCallbackTaskEntity task = taskMapper.selectById(taskId);
SmHotelCallbackTaskEntity task = taskMapper.selectById(taskId);
if (task == null) {
log.warn("|回调队列|任务不存在|taskId={}|", taskId);
return true;
@@ -199,8 +199,8 @@ public class CanteenHotelCallbackTaskServiceImpl implements CanteenHotelCallback
return true;
}
if (task.getHotelId() == null && StrUtil.isNotBlank(task.getHotelCode())) {
CanteenHotelEntity hotel = hotelMapper.selectOne(Wrappers.<CanteenHotelEntity>lambdaQuery()
.eq(CanteenHotelEntity::getHotelCode, task.getHotelCode())
SmHotelEntity hotel = hotelMapper.selectOne(Wrappers.<SmHotelEntity>lambdaQuery()
.eq(SmHotelEntity::getHotelCode, task.getHotelCode())
.last("limit 1"));
if (hotel != null) {
task.setHotelId(hotel.getId());
@@ -230,7 +230,7 @@ public class CanteenHotelCallbackTaskServiceImpl implements CanteenHotelCallback
}
}
private void handleFailOrRetry(CanteenHotelCallbackTaskEntity task, String msg, long t0, int max) {
private void handleFailOrRetry(SmHotelCallbackTaskEntity task, String msg, long t0, int max) {
int attempts = task.getAttemptCount() == null ? 1 : task.getAttemptCount();
if (attempts < max) {
task.setStatus(STATUS_PENDING);
@@ -245,7 +245,7 @@ public class CanteenHotelCallbackTaskServiceImpl implements CanteenHotelCallback
finish(task, STATUS_FAILED, msg, t0);
}
private void finish(CanteenHotelCallbackTaskEntity task, String status, String msg, long t0) {
private void finish(SmHotelCallbackTaskEntity task, String status, String msg, long t0) {
task.setStatus(status);
task.setResultMsg(StrUtil.maxLength(msg, 1000));
task.setCostMs(System.currentTimeMillis() - t0);
@@ -256,16 +256,16 @@ public class CanteenHotelCallbackTaskServiceImpl implements CanteenHotelCallback
task.getResultMsg());
}
private CanteenHotelCallbackTaskEntity buildTask(String notifyType, Map<String, Object> body, String time,
private SmHotelCallbackTaskEntity buildTask(String notifyType, Map<String, Object> body, String time,
Long tenantId) {
String hotelCode = str(body, "hotelId");
CanteenHotelEntity hotel = null;
SmHotelEntity hotel = null;
if (StrUtil.isNotBlank(hotelCode)) {
hotel = hotelMapper.selectOne(Wrappers.<CanteenHotelEntity>lambdaQuery()
.eq(CanteenHotelEntity::getHotelCode, hotelCode)
hotel = hotelMapper.selectOne(Wrappers.<SmHotelEntity>lambdaQuery()
.eq(SmHotelEntity::getHotelCode, hotelCode)
.last("limit 1"));
}
CanteenHotelCallbackTaskEntity task = new CanteenHotelCallbackTaskEntity();
SmHotelCallbackTaskEntity task = new SmHotelCallbackTaskEntity();
task.setTenantId(tenantId);
task.setNotifyType(StrUtil.blankToDefault(notifyType, "UNKNOWN"));
task.setHotelCode(hotelCode);
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.service.impl;
package com.bsd.pjcloud.supermarket.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
@@ -8,16 +8,16 @@ import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.bsd.pjcloud.canteen.config.HotelDownstreamProperties;
import com.bsd.pjcloud.canteen.config.ShangyouHotelProperties;
import com.bsd.pjcloud.canteen.entity.*;
import com.bsd.pjcloud.canteen.integration.downstream.DownstreamHotelClient;
import com.bsd.pjcloud.canteen.integration.shangyou.ShangyouHotelApi;
import com.bsd.pjcloud.canteen.integration.shangyou.ShangyouHotelClient;
import com.bsd.pjcloud.canteen.mapper.*;
import com.bsd.pjcloud.canteen.service.CanteenHotelMidService;
import com.bsd.pjcloud.canteen.service.CanteenHotelPriceConfigService;
import com.bsd.pjcloud.canteen.vo.CanteenHotelDetailVO;
import com.bsd.pjcloud.supermarket.config.HotelDownstreamProperties;
import com.bsd.pjcloud.supermarket.config.ShangyouHotelProperties;
import com.bsd.pjcloud.supermarket.entity.*;
import com.bsd.pjcloud.supermarket.integration.downstream.DownstreamHotelClient;
import com.bsd.pjcloud.supermarket.integration.shangyou.ShangyouHotelApi;
import com.bsd.pjcloud.supermarket.integration.shangyou.ShangyouHotelClient;
import com.bsd.pjcloud.supermarket.mapper.*;
import com.bsd.pjcloud.supermarket.service.SmHotelMidService;
import com.bsd.pjcloud.supermarket.service.SmHotelPriceConfigService;
import com.bsd.pjcloud.supermarket.vo.SmHotelDetailVO;
import com.bsd.pjcloud.common.core.constant.CommonConstants;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.tenant.TenantContextHolder;
@@ -38,7 +38,7 @@ import java.util.*;
@Slf4j
@Service
@RequiredArgsConstructor
public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
public class SmHotelMidServiceImpl implements SmHotelMidService {
/** 多值 INSERT / JDBC 批更新分片大小 */
private static final int PERSIST_BATCH = 300;
@@ -54,22 +54,22 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
private final HotelDownstreamProperties downstreamProperties;
private final CanteenHotelPriceConfigService priceConfigService;
private final SmHotelPriceConfigService priceConfigService;
private final CanteenHotelMapper hotelMapper;
private final SmHotelMapper hotelMapper;
private final CanteenHotelRoomMapper roomMapper;
private final SmHotelRoomMapper roomMapper;
private final CanteenHotelProductMapper productMapper;
private final SmHotelProductMapper productMapper;
private final CanteenHotelDailyMapper dailyMapper;
private final SmHotelDailyMapper dailyMapper;
private final StringRedisTemplate stringRedisTemplate;
@Override
@Transactional(rollbackFor = Exception.class)
public R<Map<String, Object>> pullFromUpstream(Long hotelId) {
CanteenHotelEntity hotel = requireHotel(hotelId);
SmHotelEntity hotel = requireHotel(hotelId);
String hotelCode = hotel.getHotelCode();
List<String> upstreamTips = new ArrayList<>();
@@ -103,7 +103,7 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
LocalDate start = LocalDate.now();
LocalDate endExclusive = start.plusDays(priceDays);
Map<String, CanteenHotelProductEntity> productMap = new LinkedHashMap<>();
Map<String, SmHotelProductEntity> productMap = new LinkedHashMap<>();
List<DailyDraft> dailyDrafts = new ArrayList<>();
Set<String> roomTypesFromPrice = new HashSet<>();
@@ -168,14 +168,14 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
@Override
@Transactional(rollbackFor = Exception.class)
public R<Map<String, Object>> pullPriceRange(Long hotelId, LocalDate startInclusive, LocalDate endExclusive) {
CanteenHotelEntity hotel = requireHotel(hotelId);
SmHotelEntity hotel = requireHotel(hotelId);
if (startInclusive == null || endExclusive == null || !startInclusive.isBefore(endExclusive)) {
return R.failed("日期区间无效");
}
String hotelCode = hotel.getHotelCode();
// 若本地尚无房型,先补综合信息
Long roomCnt = roomMapper.selectCount(Wrappers.<CanteenHotelRoomEntity>lambdaQuery()
.eq(CanteenHotelRoomEntity::getHotelId, hotelId));
Long roomCnt = roomMapper.selectCount(Wrappers.<SmHotelRoomEntity>lambdaQuery()
.eq(SmHotelRoomEntity::getHotelId, hotelId));
if (roomCnt == null || roomCnt == 0) {
JSONObject complexResp = upstreamClient.getHotelComplexListRaw(Collections.singletonList(hotelCode));
JSONArray complexList = asContentArray(complexResp.get("content"));
@@ -185,7 +185,7 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
upsertRoomsFromComplex(hotel, complex);
}
Map<String, CanteenHotelProductEntity> productMap = new LinkedHashMap<>();
Map<String, SmHotelProductEntity> productMap = new LinkedHashMap<>();
List<DailyDraft> dailyDrafts = new ArrayList<>();
Set<String> roomTypesFromPrice = new HashSet<>();
LocalDate cursor = startInclusive;
@@ -236,7 +236,7 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
@Override
public R<Map<String, Object>> pushToDownstream(Long hotelId) {
CanteenHotelEntity hotel = requireHotel(hotelId);
SmHotelEntity hotel = requireHotel(hotelId);
String extHotelId = StrUtil.blankToDefault(hotel.getHotelCode(), String.valueOf(hotel.getId()));
Map<String, Object> hotelBody = new LinkedHashMap<>();
@@ -245,13 +245,13 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
parseRemarkAddress(hotel.getRemark(), hotelBody);
downstreamClient.hotelSync(hotelBody);
List<CanteenHotelRoomEntity> rooms = roomMapper.selectList(Wrappers.<CanteenHotelRoomEntity>lambdaQuery()
.eq(CanteenHotelRoomEntity::getHotelId, hotelId));
List<CanteenHotelProductEntity> products = productMapper
.selectList(Wrappers.<CanteenHotelProductEntity>lambdaQuery()
.eq(CanteenHotelProductEntity::getHotelId, hotelId));
List<SmHotelRoomEntity> rooms = roomMapper.selectList(Wrappers.<SmHotelRoomEntity>lambdaQuery()
.eq(SmHotelRoomEntity::getHotelId, hotelId));
List<SmHotelProductEntity> products = productMapper
.selectList(Wrappers.<SmHotelProductEntity>lambdaQuery()
.eq(SmHotelProductEntity::getHotelId, hotelId));
Map<String, Integer> roomQtyMap = new HashMap<>();
for (CanteenHotelRoomEntity room : rooms) {
for (SmHotelRoomEntity room : rooms) {
int qty = room.getRoomNumber() == null ? 0 : room.getRoomNumber();
if (qty <= 0) {
qty = products.stream()
@@ -267,7 +267,7 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
}
if (CollUtil.isNotEmpty(rooms)) {
List<Map<String, Object>> list = new ArrayList<>();
for (CanteenHotelRoomEntity room : rooms) {
for (SmHotelRoomEntity room : rooms) {
Map<String, Object> item = new LinkedHashMap<>();
item.put("extApartmentId", room.getRoomTypeCode());
item.put("apartmentName", StrUtil.blankToDefault(room.getRoomTypeName(), room.getRoomTypeCode()));
@@ -287,7 +287,7 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
List<String> productErrors = new ArrayList<>();
int productOk = 0;
Set<String> pricePlanKeys = new HashSet<>();
for (CanteenHotelProductEntity p : products) {
for (SmHotelProductEntity p : products) {
String roomCode = StrUtil.blankToDefault(p.getRoomTypeCode(), "_");
int breakfast = p.getMealCount() == null ? 0 : p.getMealCount();
int canCancel = p.getCanCancel() == null ? 0 : p.getCanCancel();
@@ -322,13 +322,13 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
}
}
List<CanteenHotelDailyEntity> dailies = dailyMapper.selectList(Wrappers.<CanteenHotelDailyEntity>lambdaQuery()
.eq(CanteenHotelDailyEntity::getHotelId, hotelId)
.ge(CanteenHotelDailyEntity::getStayDate, LocalDate.now())
.orderByAsc(CanteenHotelDailyEntity::getStayDate));
List<SmHotelDailyEntity> dailies = dailyMapper.selectList(Wrappers.<SmHotelDailyEntity>lambdaQuery()
.eq(SmHotelDailyEntity::getHotelId, hotelId)
.ge(SmHotelDailyEntity::getStayDate, LocalDate.now())
.orderByAsc(SmHotelDailyEntity::getStayDate));
int dailyPush = 0;
List<Map<String, Object>> dailyBatch = new ArrayList<>();
for (CanteenHotelDailyEntity d : dailies) {
for (SmHotelDailyEntity d : dailies) {
Map<String, Object> item = new LinkedHashMap<>();
item.put("extApartmentId", d.getRoomTypeCode());
item.put("extProductId", d.getProductCode());
@@ -407,42 +407,42 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
}
@Override
public R<CanteenHotelDetailVO> getHotelDetail(Long hotelId) {
CanteenHotelEntity hotel = hotelMapper.selectById(hotelId);
public R<SmHotelDetailVO> getHotelDetail(Long hotelId) {
SmHotelEntity hotel = hotelMapper.selectById(hotelId);
if (hotel == null) {
return R.failed("酒店不存在");
}
CanteenHotelDetailVO vo = new CanteenHotelDetailVO();
SmHotelDetailVO vo = new SmHotelDetailVO();
vo.setHotel(hotel);
vo.setRooms(roomMapper.selectList(Wrappers.<CanteenHotelRoomEntity>lambdaQuery()
.eq(CanteenHotelRoomEntity::getHotelId, hotelId)
.orderByAsc(CanteenHotelRoomEntity::getRoomTypeCode)));
vo.setProducts(productMapper.selectList(Wrappers.<CanteenHotelProductEntity>lambdaQuery()
.eq(CanteenHotelProductEntity::getHotelId, hotelId)
.orderByAsc(CanteenHotelProductEntity::getProductCode)));
Long dailyCount = dailyMapper.selectCount(Wrappers.<CanteenHotelDailyEntity>lambdaQuery()
.eq(CanteenHotelDailyEntity::getHotelId, hotelId)
.ge(CanteenHotelDailyEntity::getStayDate, LocalDate.now()));
vo.setRooms(roomMapper.selectList(Wrappers.<SmHotelRoomEntity>lambdaQuery()
.eq(SmHotelRoomEntity::getHotelId, hotelId)
.orderByAsc(SmHotelRoomEntity::getRoomTypeCode)));
vo.setProducts(productMapper.selectList(Wrappers.<SmHotelProductEntity>lambdaQuery()
.eq(SmHotelProductEntity::getHotelId, hotelId)
.orderByAsc(SmHotelProductEntity::getProductCode)));
Long dailyCount = dailyMapper.selectCount(Wrappers.<SmHotelDailyEntity>lambdaQuery()
.eq(SmHotelDailyEntity::getHotelId, hotelId)
.ge(SmHotelDailyEntity::getStayDate, LocalDate.now()));
vo.setDailyCount(dailyCount);
vo.setDailyPreview(dailyMapper.selectList(Wrappers.<CanteenHotelDailyEntity>lambdaQuery()
.eq(CanteenHotelDailyEntity::getHotelId, hotelId)
.ge(CanteenHotelDailyEntity::getStayDate, LocalDate.now())
.orderByAsc(CanteenHotelDailyEntity::getStayDate)
.orderByAsc(CanteenHotelDailyEntity::getProductCode)
vo.setDailyPreview(dailyMapper.selectList(Wrappers.<SmHotelDailyEntity>lambdaQuery()
.eq(SmHotelDailyEntity::getHotelId, hotelId)
.ge(SmHotelDailyEntity::getStayDate, LocalDate.now())
.orderByAsc(SmHotelDailyEntity::getStayDate)
.orderByAsc(SmHotelDailyEntity::getProductCode)
.last("limit 30")));
return R.ok(vo);
}
@Override
public R<Page<CanteenHotelDailyEntity>> pageDaily(Long hotelId, Page<CanteenHotelDailyEntity> page,
public R<Page<SmHotelDailyEntity>> pageDaily(Long hotelId, Page<SmHotelDailyEntity> page,
String productCode) {
Page<CanteenHotelDailyEntity> result = dailyMapper.selectPage(page,
Wrappers.<CanteenHotelDailyEntity>lambdaQuery()
.eq(CanteenHotelDailyEntity::getHotelId, hotelId)
.eq(StrUtil.isNotBlank(productCode), CanteenHotelDailyEntity::getProductCode, productCode)
.ge(CanteenHotelDailyEntity::getStayDate, LocalDate.now())
.orderByAsc(CanteenHotelDailyEntity::getStayDate)
.orderByAsc(CanteenHotelDailyEntity::getProductCode));
Page<SmHotelDailyEntity> result = dailyMapper.selectPage(page,
Wrappers.<SmHotelDailyEntity>lambdaQuery()
.eq(SmHotelDailyEntity::getHotelId, hotelId)
.eq(StrUtil.isNotBlank(productCode), SmHotelDailyEntity::getProductCode, productCode)
.ge(SmHotelDailyEntity::getStayDate, LocalDate.now())
.orderByAsc(SmHotelDailyEntity::getStayDate)
.orderByAsc(SmHotelDailyEntity::getProductCode));
return R.ok(result);
}
@@ -499,16 +499,16 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
long total = 0L;
int batch = Math.max(100, upstreamProperties.getDiffScanBatchSize());
while (true) {
List<CanteenHotelEntity> rows = hotelMapper.selectList(Wrappers.<CanteenHotelEntity>lambdaQuery()
.select(CanteenHotelEntity::getId, CanteenHotelEntity::getHotelCode)
.gt(CanteenHotelEntity::getId, lastId)
.orderByAsc(CanteenHotelEntity::getId)
List<SmHotelEntity> rows = hotelMapper.selectList(Wrappers.<SmHotelEntity>lambdaQuery()
.select(SmHotelEntity::getId, SmHotelEntity::getHotelCode)
.gt(SmHotelEntity::getId, lastId)
.orderByAsc(SmHotelEntity::getId)
.last("limit " + batch));
if (CollUtil.isEmpty(rows)) {
break;
}
List<String> codes = new ArrayList<>(rows.size());
for (CanteenHotelEntity h : rows) {
for (SmHotelEntity h : rows) {
lastId = h.getId();
if (StrUtil.isNotBlank(h.getHotelCode())) {
codes.add(h.getHotelCode());
@@ -543,13 +543,13 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
skip++;
continue;
}
Long cnt = hotelMapper.selectCount(Wrappers.<CanteenHotelEntity>lambdaQuery()
.eq(CanteenHotelEntity::getHotelCode, hotelId));
Long cnt = hotelMapper.selectCount(Wrappers.<SmHotelEntity>lambdaQuery()
.eq(SmHotelEntity::getHotelCode, hotelId));
if (cnt != null && cnt > 0) {
skip++;
continue;
}
CanteenHotelEntity hotel = new CanteenHotelEntity();
SmHotelEntity hotel = new SmHotelEntity();
hotel.setHotelCode(hotelId);
hotel.setHotelName(StrUtil.blankToDefault(hotelName, hotelId));
hotel.setSheetName("上游授权列表");
@@ -564,11 +564,11 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
return R.ok(result);
}
private CanteenHotelEntity requireHotel(Long hotelId) {
private SmHotelEntity requireHotel(Long hotelId) {
if (hotelId == null) {
throw new IllegalArgumentException("酒店ID不能为空");
}
CanteenHotelEntity hotel = hotelMapper.selectById(hotelId);
SmHotelEntity hotel = hotelMapper.selectById(hotelId);
if (hotel == null) {
throw new IllegalArgumentException("酒店不存在");
}
@@ -581,7 +581,7 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
return hotel;
}
private void applyHotelComplex(CanteenHotelEntity hotel, JSONObject data) {
private void applyHotelComplex(SmHotelEntity hotel, JSONObject data) {
if (data == null || data.isEmpty()) {
return;
}
@@ -605,7 +605,7 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
}
}
private int upsertRoomsFromComplex(CanteenHotelEntity hotel, JSONObject complex) {
private int upsertRoomsFromComplex(SmHotelEntity hotel, JSONObject complex) {
if (complex == null) {
return 0;
}
@@ -613,9 +613,9 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
if (list == null || list.isEmpty()) {
return 0;
}
Map<String, CanteenHotelRoomEntity> existMap = loadRoomMap(hotel.getId());
List<CanteenHotelRoomEntity> toInsert = new ArrayList<>();
List<CanteenHotelRoomEntity> toUpdate = new ArrayList<>();
Map<String, SmHotelRoomEntity> existMap = loadRoomMap(hotel.getId());
List<SmHotelRoomEntity> toInsert = new ArrayList<>();
List<SmHotelRoomEntity> toUpdate = new ArrayList<>();
LocalDateTime now = LocalDateTime.now();
Long tenantId = resolveTenantId();
for (int i = 0; i < list.size(); i++) {
@@ -624,8 +624,8 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
if (StrUtil.isBlank(code)) {
continue;
}
CanteenHotelRoomEntity exist = existMap.get(code);
CanteenHotelRoomEntity room = exist == null ? new CanteenHotelRoomEntity() : exist;
SmHotelRoomEntity exist = existMap.get(code);
SmHotelRoomEntity room = exist == null ? new SmHotelRoomEntity() : exist;
room.setHotelId(hotel.getId());
room.setGroupCode(hotel.getGroupCode());
room.setHotelCode(hotel.getHotelCode());
@@ -654,8 +654,8 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
* 合并房价房量:产品维度 = rateCode + roomTypeId;日历按 bizDate 展开。
* 房型不在此落库,收集到 roomTypesOut,最后 {@link #ensureRoomsBatch} 一次补齐。
*/
private void mergeRoomPrice(CanteenHotelEntity hotel, JSONObject priceContent,
Map<String, CanteenHotelProductEntity> productMap, List<DailyDraft> dailyDrafts,
private void mergeRoomPrice(SmHotelEntity hotel, JSONObject priceContent,
Map<String, SmHotelProductEntity> productMap, List<DailyDraft> dailyDrafts,
Set<String> roomTypesOut) {
if (priceContent == null || priceContent.isEmpty()) {
return;
@@ -727,9 +727,9 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
}
String productCode = rateCode + "_" + roomTypeId;
CanteenHotelProductEntity product = productMap.get(productCode);
SmHotelProductEntity product = productMap.get(productCode);
if (product == null) {
product = new CanteenHotelProductEntity();
product = new SmHotelProductEntity();
product.setHotelId(hotel.getId());
product.setGroupCode(hotel.getGroupCode());
product.setHotelCode(hotel.getHotelCode());
@@ -774,19 +774,19 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
}
/** 房价里出现但综合信息未含的房型,一次批量补齐 */
private void ensureRoomsBatch(CanteenHotelEntity hotel, Set<String> roomTypeCodes) {
private void ensureRoomsBatch(SmHotelEntity hotel, Set<String> roomTypeCodes) {
if (CollUtil.isEmpty(roomTypeCodes)) {
return;
}
Map<String, CanteenHotelRoomEntity> existMap = loadRoomMap(hotel.getId());
List<CanteenHotelRoomEntity> toInsert = new ArrayList<>();
Map<String, SmHotelRoomEntity> existMap = loadRoomMap(hotel.getId());
List<SmHotelRoomEntity> toInsert = new ArrayList<>();
LocalDateTime now = LocalDateTime.now();
Long tenantId = resolveTenantId();
for (String code : roomTypeCodes) {
if (StrUtil.isBlank(code) || existMap.containsKey(code)) {
continue;
}
CanteenHotelRoomEntity room = new CanteenHotelRoomEntity();
SmHotelRoomEntity room = new SmHotelRoomEntity();
room.setHotelId(hotel.getId());
room.setGroupCode(hotel.getGroupCode());
room.setHotelCode(hotel.getHotelCode());
@@ -799,20 +799,20 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
insertRoomsBatch(toInsert);
}
private int persistProducts(CanteenHotelEntity hotel, Map<String, CanteenHotelProductEntity> productMap) {
private int persistProducts(SmHotelEntity hotel, Map<String, SmHotelProductEntity> productMap) {
if (productMap == null || productMap.isEmpty()) {
return 0;
}
Map<String, CanteenHotelRoomEntity> roomMap = loadRoomMap(hotel.getId());
Map<String, CanteenHotelProductEntity> existMap = loadProductMap(hotel.getId());
List<CanteenHotelProductEntity> toInsert = new ArrayList<>();
List<CanteenHotelProductEntity> toUpdate = new ArrayList<>();
Map<String, SmHotelRoomEntity> roomMap = loadRoomMap(hotel.getId());
Map<String, SmHotelProductEntity> existMap = loadProductMap(hotel.getId());
List<SmHotelProductEntity> toInsert = new ArrayList<>();
List<SmHotelProductEntity> toUpdate = new ArrayList<>();
LocalDateTime now = LocalDateTime.now();
Long tenantId = resolveTenantId();
for (CanteenHotelProductEntity product : productMap.values()) {
CanteenHotelRoomEntity room = roomMap.get(product.getRoomTypeCode());
for (SmHotelProductEntity product : productMap.values()) {
SmHotelRoomEntity room = roomMap.get(product.getRoomTypeCode());
product.setRoomId(room == null ? null : room.getId());
CanteenHotelProductEntity exist = existMap.get(product.getProductCode());
SmHotelProductEntity exist = existMap.get(product.getProductCode());
product.setUpdateTime(now);
if (exist == null) {
fillNewMeta(product, tenantId, now);
@@ -829,17 +829,17 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
return toInsert.size() + toUpdate.size();
}
private int persistDailies(CanteenHotelEntity hotel, List<DailyDraft> drafts) {
private int persistDailies(SmHotelEntity hotel, List<DailyDraft> drafts) {
dailyMapper.physicalDeleteFromDate(hotel.getId(), LocalDate.now());
if (CollUtil.isEmpty(drafts)) {
return 0;
}
Map<String, Long> productIdMap = new HashMap<>();
List<CanteenHotelProductEntity> products = productMapper
.selectList(Wrappers.<CanteenHotelProductEntity>lambdaQuery()
.select(CanteenHotelProductEntity::getId, CanteenHotelProductEntity::getProductCode)
.eq(CanteenHotelProductEntity::getHotelId, hotel.getId()));
for (CanteenHotelProductEntity p : products) {
List<SmHotelProductEntity> products = productMapper
.selectList(Wrappers.<SmHotelProductEntity>lambdaQuery()
.select(SmHotelProductEntity::getId, SmHotelProductEntity::getProductCode)
.eq(SmHotelProductEntity::getHotelId, hotel.getId()));
for (SmHotelProductEntity p : products) {
productIdMap.put(p.getProductCode(), p.getId());
}
Map<String, DailyDraft> unique = new LinkedHashMap<>();
@@ -848,13 +848,13 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
}
LocalDateTime now = LocalDateTime.now();
Long tenantId = resolveTenantId();
List<CanteenHotelDailyEntity> toInsert = new ArrayList<>(unique.size());
List<SmHotelDailyEntity> toInsert = new ArrayList<>(unique.size());
for (DailyDraft d : unique.values()) {
Long productId = productIdMap.get(d.productCode);
if (productId == null) {
continue;
}
CanteenHotelDailyEntity daily = new CanteenHotelDailyEntity();
SmHotelDailyEntity daily = new SmHotelDailyEntity();
daily.setHotelId(hotel.getId());
daily.setProductId(productId);
daily.setRoomTypeCode(d.roomTypeCode);
@@ -871,11 +871,11 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
return toInsert.size();
}
private Map<String, CanteenHotelRoomEntity> loadRoomMap(Long hotelId) {
List<CanteenHotelRoomEntity> rows = roomMapper.selectList(Wrappers.<CanteenHotelRoomEntity>lambdaQuery()
.eq(CanteenHotelRoomEntity::getHotelId, hotelId));
Map<String, CanteenHotelRoomEntity> map = new HashMap<>(Math.max(16, rows.size() * 2));
for (CanteenHotelRoomEntity r : rows) {
private Map<String, SmHotelRoomEntity> loadRoomMap(Long hotelId) {
List<SmHotelRoomEntity> rows = roomMapper.selectList(Wrappers.<SmHotelRoomEntity>lambdaQuery()
.eq(SmHotelRoomEntity::getHotelId, hotelId));
Map<String, SmHotelRoomEntity> map = new HashMap<>(Math.max(16, rows.size() * 2));
for (SmHotelRoomEntity r : rows) {
if (StrUtil.isNotBlank(r.getRoomTypeCode())) {
map.put(r.getRoomTypeCode(), r);
}
@@ -883,12 +883,12 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
return map;
}
private Map<String, CanteenHotelProductEntity> loadProductMap(Long hotelId) {
List<CanteenHotelProductEntity> rows = productMapper
.selectList(Wrappers.<CanteenHotelProductEntity>lambdaQuery()
.eq(CanteenHotelProductEntity::getHotelId, hotelId));
Map<String, CanteenHotelProductEntity> map = new HashMap<>(Math.max(16, rows.size() * 2));
for (CanteenHotelProductEntity p : rows) {
private Map<String, SmHotelProductEntity> loadProductMap(Long hotelId) {
List<SmHotelProductEntity> rows = productMapper
.selectList(Wrappers.<SmHotelProductEntity>lambdaQuery()
.eq(SmHotelProductEntity::getHotelId, hotelId));
Map<String, SmHotelProductEntity> map = new HashMap<>(Math.max(16, rows.size() * 2));
for (SmHotelProductEntity p : rows) {
if (StrUtil.isNotBlank(p.getProductCode())) {
map.put(p.getProductCode(), p);
}
@@ -896,7 +896,7 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
return map;
}
private void insertRoomsBatch(List<CanteenHotelRoomEntity> list) {
private void insertRoomsBatch(List<SmHotelRoomEntity> list) {
if (CollUtil.isEmpty(list)) {
return;
}
@@ -905,14 +905,14 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
}
}
private void updateRoomsBatch(List<CanteenHotelRoomEntity> list) {
private void updateRoomsBatch(List<SmHotelRoomEntity> list) {
if (CollUtil.isEmpty(list)) {
return;
}
Db.updateBatchById(list, PERSIST_BATCH);
}
private void insertProductsBatch(List<CanteenHotelProductEntity> list) {
private void insertProductsBatch(List<SmHotelProductEntity> list) {
if (CollUtil.isEmpty(list)) {
return;
}
@@ -921,14 +921,14 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
}
}
private void updateProductsBatch(List<CanteenHotelProductEntity> list) {
private void updateProductsBatch(List<SmHotelProductEntity> list) {
if (CollUtil.isEmpty(list)) {
return;
}
Db.updateBatchById(list, PERSIST_BATCH);
}
private void insertDailiesBatch(List<CanteenHotelDailyEntity> list) {
private void insertDailiesBatch(List<SmHotelDailyEntity> list) {
if (CollUtil.isEmpty(list)) {
return;
}
@@ -937,7 +937,7 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
}
}
private static void fillNewMeta(CanteenHotelRoomEntity e, Long tenantId, LocalDateTime now) {
private static void fillNewMeta(SmHotelRoomEntity e, Long tenantId, LocalDateTime now) {
e.setId(IdWorker.getId());
e.setTenantId(tenantId);
e.setCreateTime(now);
@@ -945,7 +945,7 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
e.setDelFlag(CommonConstants.STATUS_NORMAL);
}
private static void fillNewMeta(CanteenHotelProductEntity e, Long tenantId, LocalDateTime now) {
private static void fillNewMeta(SmHotelProductEntity e, Long tenantId, LocalDateTime now) {
e.setId(IdWorker.getId());
e.setTenantId(tenantId);
e.setCreateTime(now);
@@ -953,7 +953,7 @@ public class CanteenHotelMidServiceImpl implements CanteenHotelMidService {
e.setDelFlag(CommonConstants.STATUS_NORMAL);
}
private static void fillNewMeta(CanteenHotelDailyEntity e, Long tenantId, LocalDateTime now) {
private static void fillNewMeta(SmHotelDailyEntity e, Long tenantId, LocalDateTime now) {
e.setId(IdWorker.getId());
e.setTenantId(tenantId);
e.setCreateTime(now);
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.service.impl;
package com.bsd.pjcloud.supermarket.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
@@ -7,13 +7,13 @@ import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.canteen.entity.*;
import com.bsd.pjcloud.canteen.integration.shangyou.ShangyouBookStatus;
import com.bsd.pjcloud.canteen.integration.shangyou.ShangyouHotelClient;
import com.bsd.pjcloud.canteen.integration.shangyou.ShangyouOrderCallResult;
import com.bsd.pjcloud.canteen.mapper.*;
import com.bsd.pjcloud.canteen.service.CanteenHotelOrderService;
import com.bsd.pjcloud.canteen.service.CanteenHotelPriceConfigService;
import com.bsd.pjcloud.supermarket.entity.*;
import com.bsd.pjcloud.supermarket.integration.shangyou.ShangyouBookStatus;
import com.bsd.pjcloud.supermarket.integration.shangyou.ShangyouHotelClient;
import com.bsd.pjcloud.supermarket.integration.shangyou.ShangyouOrderCallResult;
import com.bsd.pjcloud.supermarket.mapper.*;
import com.bsd.pjcloud.supermarket.service.SmHotelOrderService;
import com.bsd.pjcloud.supermarket.service.SmHotelPriceConfigService;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.tenant.TenantBroker;
import com.bsd.pjcloud.common.data.tenant.TenantContextHolder;
@@ -35,8 +35,8 @@ import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderMapper, CanteenHotelOrderEntity>
implements CanteenHotelOrderService {
public class SmHotelOrderServiceImpl extends ServiceImpl<SmHotelOrderMapper, SmHotelOrderEntity>
implements SmHotelOrderService {
/** 文档:下单后第 3 / 5 / 10 分钟查询 */
private static final int[] COMPENSATE_DELAY_MINUTES = { 3, 5, 10 };
@@ -49,50 +49,50 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
private static final String COMP_NEED_MANUAL = "NEED_MANUAL";
private final CanteenHotelDownstreamAppMapper appMapper;
private final SmHotelDownstreamAppMapper appMapper;
private final CanteenHotelMapper hotelMapper;
private final SmHotelMapper hotelMapper;
private final CanteenHotelProductMapper productMapper;
private final SmHotelProductMapper productMapper;
private final CanteenHotelDailyMapper dailyMapper;
private final SmHotelDailyMapper dailyMapper;
private final ShangyouHotelClient upstreamClient;
private final CanteenHotelPriceConfigService priceConfigService;
private final SmHotelPriceConfigService priceConfigService;
private final com.bsd.pjcloud.canteen.config.ShangyouHotelProperties shangyouProperties;
private final com.bsd.pjcloud.supermarket.config.ShangyouHotelProperties shangyouProperties;
@Override
public Page<CanteenHotelOrderEntity> pageOrders(Page<CanteenHotelOrderEntity> page, CanteenHotelOrderEntity query) {
return baseMapper.selectPage(page, Wrappers.<CanteenHotelOrderEntity>lambdaQuery()
.like(StrUtil.isNotBlank(query.getChannelNo()), CanteenHotelOrderEntity::getChannelNo, query.getChannelNo())
.like(StrUtil.isNotBlank(query.getPlatformNo()), CanteenHotelOrderEntity::getPlatformNo,
public Page<SmHotelOrderEntity> pageOrders(Page<SmHotelOrderEntity> page, SmHotelOrderEntity query) {
return baseMapper.selectPage(page, Wrappers.<SmHotelOrderEntity>lambdaQuery()
.like(StrUtil.isNotBlank(query.getChannelNo()), SmHotelOrderEntity::getChannelNo, query.getChannelNo())
.like(StrUtil.isNotBlank(query.getPlatformNo()), SmHotelOrderEntity::getPlatformNo,
query.getPlatformNo())
.eq(StrUtil.isNotBlank(query.getOrderStatus()), CanteenHotelOrderEntity::getOrderStatus,
.eq(StrUtil.isNotBlank(query.getOrderStatus()), SmHotelOrderEntity::getOrderStatus,
query.getOrderStatus())
.eq(StrUtil.isNotBlank(query.getBookStatus()), CanteenHotelOrderEntity::getBookStatus, query.getBookStatus())
.eq(StrUtil.isNotBlank(query.getCompensateStatus()), CanteenHotelOrderEntity::getCompensateStatus,
.eq(StrUtil.isNotBlank(query.getBookStatus()), SmHotelOrderEntity::getBookStatus, query.getBookStatus())
.eq(StrUtil.isNotBlank(query.getCompensateStatus()), SmHotelOrderEntity::getCompensateStatus,
query.getCompensateStatus())
.eq(StrUtil.isNotBlank(query.getHotelCode()), CanteenHotelOrderEntity::getHotelCode, query.getHotelCode())
.orderByDesc(CanteenHotelOrderEntity::getCreateTime));
.eq(StrUtil.isNotBlank(query.getHotelCode()), SmHotelOrderEntity::getHotelCode, query.getHotelCode())
.orderByDesc(SmHotelOrderEntity::getCreateTime));
}
@Override
public CanteenHotelOrderEntity getDetail(Long id) {
public SmHotelOrderEntity getDetail(Long id) {
return baseMapper.selectById(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public R<JSONObject> createFromDownstream(String appKey, Map<String, Object> body) {
CanteenHotelDownstreamAppEntity app = requireApp(appKey);
SmHotelDownstreamAppEntity app = requireApp(appKey);
String channelNo = str(body.get("channelNo"));
if (StrUtil.isBlank(channelNo)) {
return R.failed("channelNo 不能为空");
}
CanteenHotelOrderEntity exist = baseMapper.selectOne(Wrappers.<CanteenHotelOrderEntity>lambdaQuery()
.eq(CanteenHotelOrderEntity::getChannelNo, channelNo)
SmHotelOrderEntity exist = baseMapper.selectOne(Wrappers.<SmHotelOrderEntity>lambdaQuery()
.eq(SmHotelOrderEntity::getChannelNo, channelNo)
.last("limit 1"));
if (exist != null) {
JSONObject data = buildOut(exist);
@@ -102,9 +102,9 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
String hotelCode = str(body.get("hotelCode"));
String groupCode = str(body.get("groupCode"));
String productCode = str(body.get("productCode"));
CanteenHotelEntity hotel = hotelMapper.selectOne(Wrappers.<CanteenHotelEntity>lambdaQuery()
.eq(CanteenHotelEntity::getHotelCode, hotelCode)
.eq(StrUtil.isNotBlank(groupCode), CanteenHotelEntity::getGroupCode, groupCode)
SmHotelEntity hotel = hotelMapper.selectOne(Wrappers.<SmHotelEntity>lambdaQuery()
.eq(SmHotelEntity::getHotelCode, hotelCode)
.eq(StrUtil.isNotBlank(groupCode), SmHotelEntity::getGroupCode, groupCode)
.last("limit 1"));
if (hotel == null) {
return R.failed("本地无此酒店,请先同步导入:" + hotelCode);
@@ -112,11 +112,11 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
if ("OFFLINE".equalsIgnoreCase(hotel.getUpstreamStatus())) {
return R.failed("酒店已停用,无法下单");
}
CanteenHotelProductEntity product = null;
SmHotelProductEntity product = null;
if (StrUtil.isNotBlank(productCode)) {
product = productMapper.selectOne(Wrappers.<CanteenHotelProductEntity>lambdaQuery()
.eq(CanteenHotelProductEntity::getHotelId, hotel.getId())
.eq(CanteenHotelProductEntity::getProductCode, productCode)
product = productMapper.selectOne(Wrappers.<SmHotelProductEntity>lambdaQuery()
.eq(SmHotelProductEntity::getHotelId, hotel.getId())
.eq(SmHotelProductEntity::getProductCode, productCode)
.last("limit 1"));
}
if (product == null && StrUtil.isBlank(str(body.get("roomTypeCode")))
@@ -124,7 +124,7 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
return R.failed("产品不存在,且未传 roomTypeCode/priceCode");
}
CanteenHotelOrderEntity order = new CanteenHotelOrderEntity();
SmHotelOrderEntity order = new SmHotelOrderEntity();
order.setDownstreamAppId(app.getId());
order.setHotelId(hotel.getId());
order.setChannelNo(channelNo);
@@ -199,15 +199,15 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
if (hotelIdObj != null && StrUtil.isNotBlank(String.valueOf(hotelIdObj))) {
hotelId = Long.valueOf(String.valueOf(hotelIdObj));
}
CanteenHotelEntity hotel = null;
SmHotelEntity hotel = null;
if (hotelId != null) {
hotel = hotelMapper.selectById(hotelId);
}
if (hotel == null) {
String hotelCode = str(body.get("hotelCode"));
if (StrUtil.isNotBlank(hotelCode)) {
hotel = hotelMapper.selectOne(Wrappers.<CanteenHotelEntity>lambdaQuery()
.eq(CanteenHotelEntity::getHotelCode, hotelCode)
hotel = hotelMapper.selectOne(Wrappers.<SmHotelEntity>lambdaQuery()
.eq(SmHotelEntity::getHotelCode, hotelCode)
.last("limit 1"));
}
}
@@ -221,9 +221,9 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
if (StrUtil.isBlank(productCode)) {
return R.failed("productCode 不能为空");
}
CanteenHotelProductEntity product = productMapper.selectOne(Wrappers.<CanteenHotelProductEntity>lambdaQuery()
.eq(CanteenHotelProductEntity::getHotelId, hotel.getId())
.eq(CanteenHotelProductEntity::getProductCode, productCode)
SmHotelProductEntity product = productMapper.selectOne(Wrappers.<SmHotelProductEntity>lambdaQuery()
.eq(SmHotelProductEntity::getHotelId, hotel.getId())
.eq(SmHotelProductEntity::getProductCode, productCode)
.last("limit 1"));
if (product == null) {
return R.failed("产品不存在,请先拉取酒店详情");
@@ -246,8 +246,8 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
if (StrUtil.isBlank(channelNo)) {
channelNo = "ADMIN" + System.currentTimeMillis() + (int) (Math.random() * 900 + 100);
}
CanteenHotelOrderEntity exist = baseMapper.selectOne(Wrappers.<CanteenHotelOrderEntity>lambdaQuery()
.eq(CanteenHotelOrderEntity::getChannelNo, channelNo)
SmHotelOrderEntity exist = baseMapper.selectOne(Wrappers.<SmHotelOrderEntity>lambdaQuery()
.eq(SmHotelOrderEntity::getChannelNo, channelNo)
.last("limit 1"));
if (exist != null) {
return R.ok(buildOut(exist), "订单已存在(幂等)");
@@ -258,7 +258,7 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
count = 1;
}
CanteenHotelOrderEntity order = new CanteenHotelOrderEntity();
SmHotelOrderEntity order = new SmHotelOrderEntity();
order.setDownstreamAppId(null);
order.setHotelId(hotel.getId());
order.setChannelNo(channelNo);
@@ -373,7 +373,7 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
return null;
}
private void applyCreateResult(CanteenHotelOrderEntity order, ShangyouOrderCallResult call,
private void applyCreateResult(SmHotelOrderEntity order, ShangyouOrderCallResult call,
com.alibaba.fastjson.JSONObject upstreamBody) {
if (call.getRaw() != null) {
order.setUpstreamRespJson(call.getRaw().toJSONString());
@@ -424,7 +424,7 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
}
}
private void scheduleCompensate(CanteenHotelOrderEntity order, String reason) {
private void scheduleCompensate(SmHotelOrderEntity order, String reason) {
order.setCompensateStatus(COMP_WAITING);
order.setCompensateRound(0);
LocalDateTime base = order.getCreateTime() == null ? LocalDateTime.now() : order.getCreateTime();
@@ -437,13 +437,13 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
@Override
public int processDueCompensate(int limit) {
LocalDateTime now = LocalDateTime.now();
List<CanteenHotelOrderEntity> due = baseMapper.selectList(Wrappers.<CanteenHotelOrderEntity>lambdaQuery()
.eq(CanteenHotelOrderEntity::getCompensateStatus, COMP_WAITING)
.le(CanteenHotelOrderEntity::getNextCompensateTime, now)
.orderByAsc(CanteenHotelOrderEntity::getNextCompensateTime)
List<SmHotelOrderEntity> due = baseMapper.selectList(Wrappers.<SmHotelOrderEntity>lambdaQuery()
.eq(SmHotelOrderEntity::getCompensateStatus, COMP_WAITING)
.le(SmHotelOrderEntity::getNextCompensateTime, now)
.orderByAsc(SmHotelOrderEntity::getNextCompensateTime)
.last("limit " + Math.max(1, limit)));
int n = 0;
for (CanteenHotelOrderEntity row : due) {
for (SmHotelOrderEntity row : due) {
Long tenantId = row.getTenantId() != null ? row.getTenantId() : TenantContextHolder.getTenantId();
if (tenantId == null) {
tenantId = 1L;
@@ -463,7 +463,7 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
@Override
@Transactional(rollbackFor = Exception.class)
public R<Boolean> compensateNow(Long id) {
CanteenHotelOrderEntity order = baseMapper.selectById(id);
SmHotelOrderEntity order = baseMapper.selectById(id);
if (order == null) {
return R.failed("订单不存在");
}
@@ -472,7 +472,7 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
}
private void compensateOne(Long orderId, boolean force) {
CanteenHotelOrderEntity order = baseMapper.selectById(orderId);
SmHotelOrderEntity order = baseMapper.selectById(orderId);
if (order == null) {
return;
}
@@ -522,15 +522,15 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
applyCompensateSuccess(order, query, nextRound, "queryByRequestNo");
}
private ShangyouOrderCallResult retryOrderAdd(CanteenHotelOrderEntity order) {
private ShangyouOrderCallResult retryOrderAdd(SmHotelOrderEntity order) {
try {
Map<String, Object> body = StrUtil.isBlank(order.getReqJson()) ? Map.of()
: JSONUtil.parseObj(order.getReqJson());
CanteenHotelProductEntity product = null;
SmHotelProductEntity product = null;
if (order.getHotelId() != null && StrUtil.isNotBlank(order.getProductCode())) {
product = productMapper.selectOne(Wrappers.<CanteenHotelProductEntity>lambdaQuery()
.eq(CanteenHotelProductEntity::getHotelId, order.getHotelId())
.eq(CanteenHotelProductEntity::getProductCode, order.getProductCode())
product = productMapper.selectOne(Wrappers.<SmHotelProductEntity>lambdaQuery()
.eq(SmHotelProductEntity::getHotelId, order.getHotelId())
.eq(SmHotelProductEntity::getProductCode, order.getProductCode())
.last("limit 1"));
}
com.alibaba.fastjson.JSONObject upstreamBody = buildUpstreamOrderBody(order, product, body);
@@ -542,7 +542,7 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
}
}
private void applyCompensateSuccess(CanteenHotelOrderEntity order, ShangyouOrderCallResult call, int round,
private void applyCompensateSuccess(SmHotelOrderEntity order, ShangyouOrderCallResult call, int round,
String source) {
if (call.getRaw() != null) {
order.setUpstreamRespJson(call.getRaw().toJSONString());
@@ -580,7 +580,7 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
baseMapper.updateById(order);
}
private void bumpOrManual(CanteenHotelOrderEntity order, int round, String msg) {
private void bumpOrManual(SmHotelOrderEntity order, int round, String msg) {
order.setCompensateRound(round);
if (round >= COMPENSATE_DELAY_MINUTES.length) {
order.setCompensateStatus(COMP_NEED_MANUAL);
@@ -597,7 +597,7 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
baseMapper.updateById(order);
}
private void applyBookStatus(CanteenHotelOrderEntity order, String bookStatus, String payStatus) {
private void applyBookStatus(SmHotelOrderEntity order, String bookStatus, String payStatus) {
if (StrUtil.isNotBlank(bookStatus)) {
order.setBookStatus(bookStatus.trim().toUpperCase());
String local = ShangyouBookStatus.toLocalOrderStatus(order.getBookStatus());
@@ -617,15 +617,15 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
String orderId = str(body.get("orderId"));
String outerRefId = str(body.get("outerRefId"));
String bookStatus = str(body.get("bookStatus"));
CanteenHotelOrderEntity order = null;
SmHotelOrderEntity order = null;
if (StrUtil.isNotBlank(orderId)) {
order = baseMapper.selectOne(Wrappers.<CanteenHotelOrderEntity>lambdaQuery()
.eq(CanteenHotelOrderEntity::getPlatformNo, orderId)
order = baseMapper.selectOne(Wrappers.<SmHotelOrderEntity>lambdaQuery()
.eq(SmHotelOrderEntity::getPlatformNo, orderId)
.last("limit 1"));
}
if (order == null && StrUtil.isNotBlank(outerRefId)) {
order = baseMapper.selectOne(Wrappers.<CanteenHotelOrderEntity>lambdaQuery()
.eq(CanteenHotelOrderEntity::getChannelNo, outerRefId)
order = baseMapper.selectOne(Wrappers.<SmHotelOrderEntity>lambdaQuery()
.eq(SmHotelOrderEntity::getChannelNo, outerRefId)
.last("limit 1"));
}
if (order == null) {
@@ -648,8 +648,8 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
public R<JSONObject> cancelFromDownstream(String appKey, Map<String, Object> body) {
requireApp(appKey);
String channelNo = str(body.get("channelNo"));
CanteenHotelOrderEntity order = baseMapper.selectOne(Wrappers.<CanteenHotelOrderEntity>lambdaQuery()
.eq(CanteenHotelOrderEntity::getChannelNo, channelNo)
SmHotelOrderEntity order = baseMapper.selectOne(Wrappers.<SmHotelOrderEntity>lambdaQuery()
.eq(SmHotelOrderEntity::getChannelNo, channelNo)
.last("limit 1"));
if (order == null) {
return R.failed("订单不存在");
@@ -677,8 +677,8 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
public R<JSONObject> queryFromDownstream(String appKey, Map<String, Object> body) {
requireApp(appKey);
String channelNo = str(body.get("channelNo"));
CanteenHotelOrderEntity order = baseMapper.selectOne(Wrappers.<CanteenHotelOrderEntity>lambdaQuery()
.eq(CanteenHotelOrderEntity::getChannelNo, channelNo)
SmHotelOrderEntity order = baseMapper.selectOne(Wrappers.<SmHotelOrderEntity>lambdaQuery()
.eq(SmHotelOrderEntity::getChannelNo, channelNo)
.last("limit 1"));
if (order == null) {
return R.failed("订单不存在");
@@ -717,7 +717,7 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
@Override
@Transactional(rollbackFor = Exception.class)
public R<Boolean> cancelByAdmin(Long id, String reason) {
CanteenHotelOrderEntity order = baseMapper.selectById(id);
SmHotelOrderEntity order = baseMapper.selectById(id);
if (order == null) {
return R.failed("订单不存在");
}
@@ -743,7 +743,7 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
}
}
private JSONObject buildOut(CanteenHotelOrderEntity order) {
private JSONObject buildOut(SmHotelOrderEntity order) {
JSONObject out = new JSONObject();
out.set("channelNo", order.getChannelNo());
out.set("platformNo", order.getPlatformNo());
@@ -763,8 +763,8 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
* 字段名按官方文档:linkFirstName/linkMobile、guestInfoList、bookerPersonFirstName 等;
* dailyPriceList 必须覆盖入住夜(checkOut-checkIn),缺夜用产品底价补齐。
*/
private com.alibaba.fastjson.JSONObject buildUpstreamOrderBody(CanteenHotelOrderEntity order,
CanteenHotelProductEntity product, Map<String, Object> downstreamBody) {
private com.alibaba.fastjson.JSONObject buildUpstreamOrderBody(SmHotelOrderEntity order,
SmHotelProductEntity product, Map<String, Object> downstreamBody) {
com.alibaba.fastjson.JSONObject req = new com.alibaba.fastjson.JSONObject();
req.put("requestNo", order.getChannelNo());
req.put("outerRefId", order.getChannelNo());
@@ -897,19 +897,19 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
/**
* 按住店夜补齐 dailyPriceList;本地日历缺夜则用产品底价兜底。
*/
private List<com.alibaba.fastjson.JSONObject> buildDailyPriceList(CanteenHotelOrderEntity order,
CanteenHotelProductEntity product) {
private List<com.alibaba.fastjson.JSONObject> buildDailyPriceList(SmHotelOrderEntity order,
SmHotelProductEntity product) {
Map<LocalDate, BigDecimal> byDate = new java.util.LinkedHashMap<>();
if (order.getHotelId() != null && StrUtil.isNotBlank(order.getProductCode())
&& order.getCheckInDate() != null && order.getCheckOutDate() != null) {
List<CanteenHotelDailyEntity> dailies = dailyMapper
.selectList(Wrappers.<CanteenHotelDailyEntity>lambdaQuery()
.eq(CanteenHotelDailyEntity::getHotelId, order.getHotelId())
.eq(CanteenHotelDailyEntity::getProductCode, order.getProductCode())
.ge(CanteenHotelDailyEntity::getStayDate, order.getCheckInDate())
.lt(CanteenHotelDailyEntity::getStayDate, order.getCheckOutDate())
.orderByAsc(CanteenHotelDailyEntity::getStayDate));
for (CanteenHotelDailyEntity d : dailies) {
List<SmHotelDailyEntity> dailies = dailyMapper
.selectList(Wrappers.<SmHotelDailyEntity>lambdaQuery()
.eq(SmHotelDailyEntity::getHotelId, order.getHotelId())
.eq(SmHotelDailyEntity::getProductCode, order.getProductCode())
.ge(SmHotelDailyEntity::getStayDate, order.getCheckInDate())
.lt(SmHotelDailyEntity::getStayDate, order.getCheckOutDate())
.orderByAsc(SmHotelDailyEntity::getStayDate));
for (SmHotelDailyEntity d : dailies) {
byDate.put(d.getStayDate(), d.getCostPrice() == null ? BigDecimal.ZERO : d.getCostPrice());
}
}
@@ -927,13 +927,13 @@ public class CanteenHotelOrderServiceImpl extends ServiceImpl<CanteenHotelOrderM
return dailyPriceList;
}
private CanteenHotelDownstreamAppEntity requireApp(String appKey) {
private SmHotelDownstreamAppEntity requireApp(String appKey) {
if (StrUtil.isBlank(appKey)) {
throw new IllegalArgumentException("缺少 appKey");
}
CanteenHotelDownstreamAppEntity app = appMapper.selectOne(Wrappers.<CanteenHotelDownstreamAppEntity>lambdaQuery()
.eq(CanteenHotelDownstreamAppEntity::getAppKey, appKey)
.eq(CanteenHotelDownstreamAppEntity::getStatus, "1")
SmHotelDownstreamAppEntity app = appMapper.selectOne(Wrappers.<SmHotelDownstreamAppEntity>lambdaQuery()
.eq(SmHotelDownstreamAppEntity::getAppKey, appKey)
.eq(SmHotelDownstreamAppEntity::getStatus, "1")
.last("limit 1"));
if (app == null) {
throw new IllegalArgumentException("无效的下游 appKey");
@@ -1,10 +1,10 @@
package com.bsd.pjcloud.canteen.service.impl;
package com.bsd.pjcloud.supermarket.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.canteen.entity.CanteenHotelPriceConfigEntity;
import com.bsd.pjcloud.canteen.mapper.CanteenHotelPriceConfigMapper;
import com.bsd.pjcloud.canteen.service.CanteenHotelPriceConfigService;
import com.bsd.pjcloud.supermarket.entity.SmHotelPriceConfigEntity;
import com.bsd.pjcloud.supermarket.mapper.SmHotelPriceConfigMapper;
import com.bsd.pjcloud.supermarket.service.SmHotelPriceConfigService;
import com.bsd.pjcloud.common.core.util.R;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -15,16 +15,16 @@ import java.math.RoundingMode;
@Service
@RequiredArgsConstructor
public class CanteenHotelPriceConfigServiceImpl extends ServiceImpl<CanteenHotelPriceConfigMapper, CanteenHotelPriceConfigEntity>
implements CanteenHotelPriceConfigService {
public class SmHotelPriceConfigServiceImpl extends ServiceImpl<SmHotelPriceConfigMapper, SmHotelPriceConfigEntity>
implements SmHotelPriceConfigService {
@Override
public R<CanteenHotelPriceConfigEntity> getCurrent() {
CanteenHotelPriceConfigEntity one = baseMapper.selectOne(Wrappers.<CanteenHotelPriceConfigEntity>lambdaQuery()
.orderByDesc(CanteenHotelPriceConfigEntity::getUpdateTime)
public R<SmHotelPriceConfigEntity> getCurrent() {
SmHotelPriceConfigEntity one = baseMapper.selectOne(Wrappers.<SmHotelPriceConfigEntity>lambdaQuery()
.orderByDesc(SmHotelPriceConfigEntity::getUpdateTime)
.last("limit 1"));
if (one == null) {
one = new CanteenHotelPriceConfigEntity();
one = new SmHotelPriceConfigEntity();
one.setMarkupPercent(BigDecimal.ZERO);
}
return R.ok(one);
@@ -32,11 +32,11 @@ public class CanteenHotelPriceConfigServiceImpl extends ServiceImpl<CanteenHotel
@Override
@Transactional(rollbackFor = Exception.class)
public R<Boolean> saveOrUpdateConfig(CanteenHotelPriceConfigEntity entity) {
public R<Boolean> saveOrUpdateConfig(SmHotelPriceConfigEntity entity) {
if (entity.getMarkupPercent() == null || entity.getMarkupPercent().compareTo(BigDecimal.ZERO) < 0) {
return R.failed("加价百分比不能为空且不能为负");
}
CanteenHotelPriceConfigEntity exist = baseMapper.selectOne(Wrappers.<CanteenHotelPriceConfigEntity>lambdaQuery()
SmHotelPriceConfigEntity exist = baseMapper.selectOne(Wrappers.<SmHotelPriceConfigEntity>lambdaQuery()
.last("limit 1"));
if (exist == null) {
return R.ok(save(entity));
@@ -48,7 +48,7 @@ public class CanteenHotelPriceConfigServiceImpl extends ServiceImpl<CanteenHotel
@Override
public BigDecimal currentMarkupPercent() {
CanteenHotelPriceConfigEntity one = baseMapper.selectOne(Wrappers.<CanteenHotelPriceConfigEntity>lambdaQuery()
SmHotelPriceConfigEntity one = baseMapper.selectOne(Wrappers.<SmHotelPriceConfigEntity>lambdaQuery()
.last("limit 1"));
return one == null || one.getMarkupPercent() == null ? BigDecimal.ZERO : one.getMarkupPercent();
}
@@ -1,4 +1,4 @@
package com.bsd.pjcloud.canteen.service.impl;
package com.bsd.pjcloud.supermarket.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
@@ -14,13 +14,13 @@ import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.canteen.entity.CanteenHotelEntity;
import com.bsd.pjcloud.canteen.mapper.CanteenHotelDailyMapper;
import com.bsd.pjcloud.canteen.mapper.CanteenHotelMapper;
import com.bsd.pjcloud.canteen.mapper.CanteenHotelProductMapper;
import com.bsd.pjcloud.canteen.mapper.CanteenHotelRoomMapper;
import com.bsd.pjcloud.canteen.service.CanteenHotelService;
import com.bsd.pjcloud.canteen.vo.CanteenHotelImportResultVO;
import com.bsd.pjcloud.supermarket.entity.SmHotelEntity;
import com.bsd.pjcloud.supermarket.mapper.SmHotelDailyMapper;
import com.bsd.pjcloud.supermarket.mapper.SmHotelMapper;
import com.bsd.pjcloud.supermarket.mapper.SmHotelProductMapper;
import com.bsd.pjcloud.supermarket.mapper.SmHotelRoomMapper;
import com.bsd.pjcloud.supermarket.service.SmHotelService;
import com.bsd.pjcloud.supermarket.vo.SmHotelImportResultVO;
import com.bsd.pjcloud.common.core.constant.CommonConstants;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
@@ -48,41 +48,41 @@ import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Service
@RequiredArgsConstructor
public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, CanteenHotelEntity>
implements CanteenHotelService {
public class SmHotelServiceImpl extends ServiceImpl<SmHotelMapper, SmHotelEntity>
implements SmHotelService {
/** 多值 INSERT 一批条数(与人脸明细导入同量级) */
private static final int BATCH = 1500;
private static final int SKIP_SAMPLE_LIMIT = 50;
private static final ConcurrentHashMap<String, CanteenHotelImportResultVO> IMPORT_TASKS = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<String, SmHotelImportResultVO> IMPORT_TASKS = new ConcurrentHashMap<>();
private final CanteenHotelRoomMapper roomMapper;
private final SmHotelRoomMapper roomMapper;
private final CanteenHotelProductMapper productMapper;
private final SmHotelProductMapper productMapper;
private final CanteenHotelDailyMapper dailyMapper;
private final SmHotelDailyMapper dailyMapper;
@Override
public Page<CanteenHotelEntity> pageScope(Page<CanteenHotelEntity> page,
LambdaQueryWrapper<CanteenHotelEntity> wrapper) {
Page<CanteenHotelEntity> result = baseMapper.selectPageByScope(page, wrapper, DataScope.of());
public Page<SmHotelEntity> pageScope(Page<SmHotelEntity> page,
LambdaQueryWrapper<SmHotelEntity> wrapper) {
Page<SmHotelEntity> result = baseMapper.selectPageByScope(page, wrapper, DataScope.of());
fillDetailCounts(result.getRecords());
return result;
}
/** 为本页酒店批量补齐房型/产品/日历数量,避免 N+1 */
private void fillDetailCounts(List<CanteenHotelEntity> records) {
private void fillDetailCounts(List<SmHotelEntity> records) {
if (CollUtil.isEmpty(records)) {
return;
}
List<Long> ids = records.stream().map(CanteenHotelEntity::getId).filter(id -> id != null).toList();
List<Long> ids = records.stream().map(SmHotelEntity::getId).filter(id -> id != null).toList();
if (ids.isEmpty()) {
return;
}
Map<Long, Integer> roomMap = toCountMap(roomMapper.countGroupByHotelIds(ids));
Map<Long, Integer> productMap = toCountMap(productMapper.countGroupByHotelIds(ids));
Map<Long, Integer> dailyMap = toCountMap(dailyMapper.countGroupByHotelIds(ids));
for (CanteenHotelEntity h : records) {
for (SmHotelEntity h : records) {
Long id = h.getId();
h.setRoomCount(roomMap.getOrDefault(id, 0));
h.setProductCount(productMap.getOrDefault(id, 0));
@@ -111,7 +111,7 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean saveHotel(CanteenHotelEntity entity) {
public Boolean saveHotel(SmHotelEntity entity) {
normalize(entity);
if (StrUtil.isBlank(entity.getHotelName()) && StrUtil.isBlank(entity.getHotelCode())) {
throw new IllegalArgumentException("酒店名称与酒店编码不能同时为空");
@@ -127,11 +127,11 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateHotel(CanteenHotelEntity entity) {
public Boolean updateHotel(SmHotelEntity entity) {
if (entity.getId() == null) {
throw new IllegalArgumentException("酒店ID不能为空");
}
CanteenHotelEntity old = baseMapper.selectById(entity.getId());
SmHotelEntity old = baseMapper.selectById(entity.getId());
if (old == null) {
throw new IllegalArgumentException("酒店不存在");
}
@@ -155,12 +155,12 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
}
@Override
public R<CanteenHotelImportResultVO> startImport(MultipartFile file) {
public R<SmHotelImportResultVO> startImport(MultipartFile file) {
if (file == null || file.isEmpty()) {
return R.failed("请上传酒店 Excel");
}
String taskId = IdUtil.getSnowflakeNextIdStr();
CanteenHotelImportResultVO vo = new CanteenHotelImportResultVO();
SmHotelImportResultVO vo = new SmHotelImportResultVO();
vo.setTaskId(taskId);
vo.setStatus("RUNNING");
vo.setMessage("已提交,后台导入中…");
@@ -168,7 +168,7 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
File temp;
try {
temp = Files.createTempFile("canteen-hotel-", ".xlsx").toFile();
temp = Files.createTempFile("sm-hotel-", ".xlsx").toFile();
file.transferTo(temp);
}
catch (Exception e) {
@@ -198,18 +198,18 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
FileUtil.del(tempFile);
}
}
}, "canteen-hotel-import-" + taskId);
}, "sm-hotel-import-" + taskId);
worker.setDaemon(false);
worker.start();
return R.ok(vo, "已提交导入,请稍候查看进度");
}
@Override
public R<CanteenHotelImportResultVO> getImportStatus(String taskId) {
public R<SmHotelImportResultVO> getImportStatus(String taskId) {
if (StrUtil.isBlank(taskId)) {
return R.failed("taskId 不能为空");
}
CanteenHotelImportResultVO vo = IMPORT_TASKS.get(taskId);
SmHotelImportResultVO vo = IMPORT_TASKS.get(taskId);
if (vo == null) {
return R.failed("导入任务不存在或已过期,请重新导入");
}
@@ -219,7 +219,7 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
/**
* 一次打开 Excel 读完全部 Sheet;库内先预加载编码索引,再按批 multi-values INSERT / 批量 UPDATE。
*/
private void doImportAsync(File tempFile, CanteenHotelImportResultVO result, Long deptId, Long tenantId,
private void doImportAsync(File tempFile, SmHotelImportResultVO result, Long deptId, Long tenantId,
String operator) throws Exception {
long t0 = System.currentTimeMillis();
List<ReadSheet> sheetMetas = listSheetMetas(tempFile);
@@ -235,7 +235,7 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
Map<String, Long> sourceIdMap = new HashMap<>();
preloadIndex(codeIdMap, sourceIdMap);
List<CanteenHotelEntity> buffer = new ArrayList<>(BATCH);
List<SmHotelEntity> buffer = new ArrayList<>(BATCH);
ImportFlushContext ctx = new ImportFlushContext(result, buffer, codeIdMap, sourceIdMap, deptId, tenantId,
operator);
@@ -273,9 +273,9 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
}
private void preloadIndex(Map<String, Long> codeIdMap, Map<String, Long> sourceIdMap) {
List<CanteenHotelEntity> existing = baseMapper.selectList(Wrappers.<CanteenHotelEntity>lambdaQuery()
.select(CanteenHotelEntity::getId, CanteenHotelEntity::getHotelCode, CanteenHotelEntity::getSourceId));
for (CanteenHotelEntity e : existing) {
List<SmHotelEntity> existing = baseMapper.selectList(Wrappers.<SmHotelEntity>lambdaQuery()
.select(SmHotelEntity::getId, SmHotelEntity::getHotelCode, SmHotelEntity::getSourceId));
for (SmHotelEntity e : existing) {
if (StrUtil.isNotBlank(e.getHotelCode())) {
codeIdMap.putIfAbsent(e.getHotelCode(), e.getId());
}
@@ -298,14 +298,14 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
}
private void flushBuffer(ImportFlushContext ctx) {
List<CanteenHotelEntity> buffer = ctx.buffer;
List<SmHotelEntity> buffer = ctx.buffer;
if (buffer.isEmpty()) {
return;
}
LocalDateTime now = LocalDateTime.now();
List<CanteenHotelEntity> toInsert = new ArrayList<>();
List<CanteenHotelEntity> toUpdate = new ArrayList<>();
for (CanteenHotelEntity entity : buffer) {
List<SmHotelEntity> toInsert = new ArrayList<>();
List<SmHotelEntity> toUpdate = new ArrayList<>();
for (SmHotelEntity entity : buffer) {
Long existsId = null;
if (StrUtil.isNotBlank(entity.getHotelCode())) {
existsId = ctx.codeIdMap.get(entity.getHotelCode());
@@ -342,13 +342,13 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
if (CollUtil.isNotEmpty(toInsert)) {
// 多值 INSERT,避免 saveBatch 逐条/小批
for (int i = 0; i < toInsert.size(); i += BATCH) {
List<CanteenHotelEntity> slice = toInsert.subList(i, Math.min(i + BATCH, toInsert.size()));
List<SmHotelEntity> slice = toInsert.subList(i, Math.min(i + BATCH, toInsert.size()));
baseMapper.insertBatch(slice);
}
}
if (CollUtil.isNotEmpty(toUpdate)) {
updateBatchById(toUpdate, BATCH);
for (CanteenHotelEntity entity : toUpdate) {
for (SmHotelEntity entity : toUpdate) {
if (StrUtil.isNotBlank(entity.getHotelCode())) {
ctx.codeIdMap.put(entity.getHotelCode(), entity.getId());
}
@@ -361,15 +361,15 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
}
private boolean existsHotelCode(String hotelCode, Long excludeId) {
LambdaQueryWrapper<CanteenHotelEntity> w = Wrappers.<CanteenHotelEntity>lambdaQuery()
.eq(CanteenHotelEntity::getHotelCode, hotelCode);
LambdaQueryWrapper<SmHotelEntity> w = Wrappers.<SmHotelEntity>lambdaQuery()
.eq(SmHotelEntity::getHotelCode, hotelCode);
if (excludeId != null) {
w.ne(CanteenHotelEntity::getId, excludeId);
w.ne(SmHotelEntity::getId, excludeId);
}
return baseMapper.selectCount(w) > 0;
}
private static void normalize(CanteenHotelEntity entity) {
private static void normalize(SmHotelEntity entity) {
entity.setSourceId(trimToNull(entity.getSourceId()));
entity.setGroupCode(trimToNull(entity.getGroupCode()));
entity.setHotelCode(trimToNull(entity.getHotelCode()));
@@ -384,7 +384,7 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
return StrUtil.isBlank(v) ? null : v.trim();
}
private static void addSkipSample(CanteenHotelImportResultVO result, String sheet, int excelRow, String reason) {
private static void addSkipSample(SmHotelImportResultVO result, String sheet, int excelRow, String reason) {
if (result.getSkipSamples().size() >= SKIP_SAMPLE_LIMIT) {
return;
}
@@ -392,15 +392,15 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
}
private final class ImportFlushContext {
final CanteenHotelImportResultVO result;
final List<CanteenHotelEntity> buffer;
final SmHotelImportResultVO result;
final List<SmHotelEntity> buffer;
final Map<String, Long> codeIdMap;
final Map<String, Long> sourceIdMap;
final Long deptId;
final Long tenantId;
final String operator;
ImportFlushContext(CanteenHotelImportResultVO result, List<CanteenHotelEntity> buffer,
ImportFlushContext(SmHotelImportResultVO result, List<SmHotelEntity> buffer,
Map<String, Long> codeIdMap, Map<String, Long> sourceIdMap, Long deptId, Long tenantId,
String operator) {
this.result = result;
@@ -496,7 +496,7 @@ public class CanteenHotelServiceImpl extends ServiceImpl<CanteenHotelMapper, Can
addSkipSample(ctx.result, sheetName, excelRow, "缺少酒店名称/编码/外部id");
return;
}
CanteenHotelEntity entity = new CanteenHotelEntity();
SmHotelEntity entity = new SmHotelEntity();
entity.setSourceId(trimToNull(sourceId));
entity.setGroupCode(trimToNull(groupCode));
entity.setHotelCode(trimToNull(hotelCode));
@@ -1,18 +1,18 @@
package com.bsd.pjcloud.canteen.service.impl;
package com.bsd.pjcloud.supermarket.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.canteen.config.ShangyouHotelProperties;
import com.bsd.pjcloud.canteen.entity.CanteenHotelEntity;
import com.bsd.pjcloud.canteen.entity.CanteenHotelSyncLogEntity;
import com.bsd.pjcloud.canteen.integration.shangyou.ShangyouHotelApi;
import com.bsd.pjcloud.canteen.integration.shangyou.ShangyouHotelClient;
import com.bsd.pjcloud.canteen.mapper.CanteenHotelMapper;
import com.bsd.pjcloud.canteen.mapper.CanteenHotelSyncLogMapper;
import com.bsd.pjcloud.canteen.service.CanteenHotelMidService;
import com.bsd.pjcloud.canteen.service.CanteenHotelSyncService;
import com.bsd.pjcloud.supermarket.config.ShangyouHotelProperties;
import com.bsd.pjcloud.supermarket.entity.SmHotelEntity;
import com.bsd.pjcloud.supermarket.entity.SmHotelSyncLogEntity;
import com.bsd.pjcloud.supermarket.integration.shangyou.ShangyouHotelApi;
import com.bsd.pjcloud.supermarket.integration.shangyou.ShangyouHotelClient;
import com.bsd.pjcloud.supermarket.mapper.SmHotelMapper;
import com.bsd.pjcloud.supermarket.mapper.SmHotelSyncLogMapper;
import com.bsd.pjcloud.supermarket.service.SmHotelMidService;
import com.bsd.pjcloud.supermarket.service.SmHotelSyncService;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.tenant.TenantBroker;
import com.bsd.pjcloud.common.data.tenant.TenantContextHolder;
@@ -41,7 +41,7 @@ import java.util.concurrent.TimeUnit;
@Slf4j
@Service
@RequiredArgsConstructor
public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
public class SmHotelSyncServiceImpl implements SmHotelSyncService {
private static final String TYPE_LIST = "LIST_DIFF";
@@ -56,7 +56,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
private static final String STATUS_FAILED = "FAILED";
private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(2, r -> {
Thread t = new Thread(r, "canteen-hotel-sync");
Thread t = new Thread(r, "sm-hotel-sync");
t.setDaemon(true);
return t;
});
@@ -65,23 +65,23 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
private final ShangyouHotelClient upstreamClient;
private final CanteenHotelMidService midService;
private final SmHotelMidService midService;
private final CanteenHotelMapper hotelMapper;
private final SmHotelMapper hotelMapper;
private final CanteenHotelSyncLogMapper syncLogMapper;
private final SmHotelSyncLogMapper syncLogMapper;
private final StringRedisTemplate redisTemplate;
@Override
public R<CanteenHotelSyncLogEntity> startListSyncAsync(boolean autoImport, String triggerType) {
Long running = syncLogMapper.selectCount(Wrappers.<CanteenHotelSyncLogEntity>lambdaQuery()
.eq(CanteenHotelSyncLogEntity::getSyncType, TYPE_LIST)
.eq(CanteenHotelSyncLogEntity::getStatus, STATUS_RUNNING));
public R<SmHotelSyncLogEntity> startListSyncAsync(boolean autoImport, String triggerType) {
Long running = syncLogMapper.selectCount(Wrappers.<SmHotelSyncLogEntity>lambdaQuery()
.eq(SmHotelSyncLogEntity::getSyncType, TYPE_LIST)
.eq(SmHotelSyncLogEntity::getStatus, STATUS_RUNNING));
if (running != null && running > 0) {
return R.failed("已有列表同步任务进行中,请稍候查看进度");
}
CanteenHotelSyncLogEntity logEntity = newLog(TYPE_LIST, triggerType);
SmHotelSyncLogEntity logEntity = newLog(TYPE_LIST, triggerType);
logEntity.setStage("QUEUED");
logEntity.setStageMsg("已提交,等待执行…");
logEntity.setProgressPct(1);
@@ -99,17 +99,17 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
@Override
public R<CanteenHotelSyncLogEntity> startPriceRollAsync(String triggerType) {
public R<SmHotelSyncLogEntity> startPriceRollAsync(String triggerType) {
if (!properties.isPriceRollDailyEnabled() && !"MANUAL".equalsIgnoreCase(triggerType)) {
return R.failed("滚价未启用");
}
Long running = syncLogMapper.selectCount(Wrappers.<CanteenHotelSyncLogEntity>lambdaQuery()
.eq(CanteenHotelSyncLogEntity::getSyncType, TYPE_ROLL)
.eq(CanteenHotelSyncLogEntity::getStatus, STATUS_RUNNING));
Long running = syncLogMapper.selectCount(Wrappers.<SmHotelSyncLogEntity>lambdaQuery()
.eq(SmHotelSyncLogEntity::getSyncType, TYPE_ROLL)
.eq(SmHotelSyncLogEntity::getStatus, STATUS_RUNNING));
if (running != null && running > 0) {
return R.failed("已有滚价任务进行中");
}
CanteenHotelSyncLogEntity logEntity = newLog(TYPE_ROLL, triggerType);
SmHotelSyncLogEntity logEntity = newLog(TYPE_ROLL, triggerType);
logEntity.setStage("QUEUED");
logEntity.setStageMsg("已提交滚价任务…");
logEntity.setProgressPct(1);
@@ -125,10 +125,10 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
@Override
public R<CanteenHotelSyncLogEntity> startDetailPullAsync(Integer limit, String triggerType) {
Long running = syncLogMapper.selectCount(Wrappers.<CanteenHotelSyncLogEntity>lambdaQuery()
.eq(CanteenHotelSyncLogEntity::getSyncType, TYPE_DETAIL)
.eq(CanteenHotelSyncLogEntity::getStatus, STATUS_RUNNING));
public R<SmHotelSyncLogEntity> startDetailPullAsync(Integer limit, String triggerType) {
Long running = syncLogMapper.selectCount(Wrappers.<SmHotelSyncLogEntity>lambdaQuery()
.eq(SmHotelSyncLogEntity::getSyncType, TYPE_DETAIL)
.eq(SmHotelSyncLogEntity::getStatus, STATUS_RUNNING));
if (running != null && running > 0) {
return R.failed("已有全量详情拉取任务进行中,请打开「同步日志」查看进度");
}
@@ -138,7 +138,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
int maxHotels = limit != null && limit > 0 ? limit : properties.getDetailPullMaxHotels();
CanteenHotelSyncLogEntity logEntity = newLog(TYPE_DETAIL, triggerType);
SmHotelSyncLogEntity logEntity = newLog(TYPE_DETAIL, triggerType);
logEntity.setStage("QUEUED");
logEntity.setStageMsg(maxHotels > 0 ? "已提交,最多处理 " + maxHotels + " 家启用酒店…"
: "已提交,将拉取全部启用酒店详情(耗时长,请看进度)…");
@@ -158,11 +158,11 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
@Override
public R<CanteenHotelSyncLogEntity> startRetryFailedAsync(Long sourceLogId) {
public R<SmHotelSyncLogEntity> startRetryFailedAsync(Long sourceLogId) {
if (sourceLogId == null) {
return R.failed("请指定失败来源日志 logId");
}
CanteenHotelSyncLogEntity src = syncLogMapper.selectById(sourceLogId);
SmHotelSyncLogEntity src = syncLogMapper.selectById(sourceLogId);
if (src == null) {
return R.failed("同步记录不存在");
}
@@ -177,14 +177,14 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
if (CollUtil.isEmpty(codes)) {
return R.failed("该日志无失败明细可重试(请确认 failDetail 有 hotelCode|名称|原因)");
}
Long running = syncLogMapper.selectCount(Wrappers.<CanteenHotelSyncLogEntity>lambdaQuery()
.eq(CanteenHotelSyncLogEntity::getSyncType, syncType)
.eq(CanteenHotelSyncLogEntity::getStatus, STATUS_RUNNING));
Long running = syncLogMapper.selectCount(Wrappers.<SmHotelSyncLogEntity>lambdaQuery()
.eq(SmHotelSyncLogEntity::getSyncType, syncType)
.eq(SmHotelSyncLogEntity::getStatus, STATUS_RUNNING));
if (running != null && running > 0) {
return R.failed("已有同类型任务进行中,请稍后再试");
}
CanteenHotelSyncLogEntity logEntity = newLog(syncType, "RETRY");
SmHotelSyncLogEntity logEntity = newLog(syncType, "RETRY");
logEntity.setStage("QUEUED");
logEntity.setStageMsg("重试失败酒店:来源日志 " + sourceLogId + ",共 " + codes.size() + " 家"
+ (TYPE_ROLL.equals(syncType) ? "(滚价日=" + resolveRollDay(src) + ")" : ""));
@@ -205,8 +205,8 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
@Override
public R<CanteenHotelSyncLogEntity> getSyncLog(Long id) {
CanteenHotelSyncLogEntity e = syncLogMapper.selectById(id);
public R<SmHotelSyncLogEntity> getSyncLog(Long id) {
SmHotelSyncLogEntity e = syncLogMapper.selectById(id);
if (e == null) {
return R.failed("同步记录不存在");
}
@@ -214,17 +214,17 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
@Override
public Page<CanteenHotelSyncLogEntity> pageSyncLogs(Page<CanteenHotelSyncLogEntity> page,
CanteenHotelSyncLogEntity query) {
return syncLogMapper.selectPage(page, Wrappers.<CanteenHotelSyncLogEntity>lambdaQuery()
.eq(StrUtil.isNotBlank(query.getSyncType()), CanteenHotelSyncLogEntity::getSyncType, query.getSyncType())
.eq(StrUtil.isNotBlank(query.getStatus()), CanteenHotelSyncLogEntity::getStatus, query.getStatus())
.orderByDesc(CanteenHotelSyncLogEntity::getCreateTime));
public Page<SmHotelSyncLogEntity> pageSyncLogs(Page<SmHotelSyncLogEntity> page,
SmHotelSyncLogEntity query) {
return syncLogMapper.selectPage(page, Wrappers.<SmHotelSyncLogEntity>lambdaQuery()
.eq(StrUtil.isNotBlank(query.getSyncType()), SmHotelSyncLogEntity::getSyncType, query.getSyncType())
.eq(StrUtil.isNotBlank(query.getStatus()), SmHotelSyncLogEntity::getStatus, query.getStatus())
.orderByDesc(SmHotelSyncLogEntity::getCreateTime));
}
@Override
public R<Map<String, Object>> syncHotelListAndDiff(boolean autoImport) {
R<CanteenHotelSyncLogEntity> started = startListSyncAsync(autoImport, "MANUAL");
R<SmHotelSyncLogEntity> started = startListSyncAsync(autoImport, "MANUAL");
if (started.getCode() != 0) {
return R.failed(started.getMsg());
}
@@ -276,7 +276,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
reactivated = reactivateBackOnlineHotels();
}
CanteenHotelSyncLogEntity done = syncLogMapper.selectById(logId);
SmHotelSyncLogEntity done = syncLogMapper.selectById(logId);
if (done == null) {
return;
}
@@ -318,26 +318,26 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
int skip = 0;
int processed = 0;
List<String> failLines = new ArrayList<>();
Long totalHint = hotelMapper.selectCount(Wrappers.<CanteenHotelEntity>lambdaQuery()
.and(w -> w.isNull(CanteenHotelEntity::getUpstreamStatus)
Long totalHint = hotelMapper.selectCount(Wrappers.<SmHotelEntity>lambdaQuery()
.and(w -> w.isNull(SmHotelEntity::getUpstreamStatus)
.or()
.ne(CanteenHotelEntity::getUpstreamStatus, "OFFLINE")));
.ne(SmHotelEntity::getUpstreamStatus, "OFFLINE")));
long total = totalHint == null ? 0L : totalHint;
while (true) {
List<CanteenHotelEntity> rows = hotelMapper.selectList(Wrappers.<CanteenHotelEntity>lambdaQuery()
.select(CanteenHotelEntity::getId, CanteenHotelEntity::getHotelCode,
CanteenHotelEntity::getHotelName)
.gt(CanteenHotelEntity::getId, lastId)
.and(w -> w.isNull(CanteenHotelEntity::getUpstreamStatus)
List<SmHotelEntity> rows = hotelMapper.selectList(Wrappers.<SmHotelEntity>lambdaQuery()
.select(SmHotelEntity::getId, SmHotelEntity::getHotelCode,
SmHotelEntity::getHotelName)
.gt(SmHotelEntity::getId, lastId)
.and(w -> w.isNull(SmHotelEntity::getUpstreamStatus)
.or()
.ne(CanteenHotelEntity::getUpstreamStatus, "OFFLINE"))
.orderByAsc(CanteenHotelEntity::getId)
.ne(SmHotelEntity::getUpstreamStatus, "OFFLINE"))
.orderByAsc(SmHotelEntity::getId)
.last("limit " + batchSize));
if (CollUtil.isEmpty(rows)) {
break;
}
for (CanteenHotelEntity h : rows) {
for (SmHotelEntity h : rows) {
lastId = h.getId();
processed++;
if (StrUtil.isBlank(h.getHotelCode())) {
@@ -377,7 +377,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
}
CanteenHotelSyncLogEntity done = syncLogMapper.selectById(logId);
SmHotelSyncLogEntity done = syncLogMapper.selectById(logId);
if (done == null) {
return;
}
@@ -408,10 +408,10 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
long t0 = System.currentTimeMillis();
try {
progress(logId, 3, "SCAN", "正在统计启用酒店…");
Long totalHint = hotelMapper.selectCount(Wrappers.<CanteenHotelEntity>lambdaQuery()
.and(w -> w.isNull(CanteenHotelEntity::getUpstreamStatus)
Long totalHint = hotelMapper.selectCount(Wrappers.<SmHotelEntity>lambdaQuery()
.and(w -> w.isNull(SmHotelEntity::getUpstreamStatus)
.or()
.ne(CanteenHotelEntity::getUpstreamStatus, "OFFLINE")));
.ne(SmHotelEntity::getUpstreamStatus, "OFFLINE")));
long totalAll = totalHint == null ? 0L : totalHint;
long target = maxHotels > 0 ? Math.min(totalAll, maxHotels) : totalAll;
int batchSize = Math.max(20, properties.getPriceRollBatchSize());
@@ -428,19 +428,19 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
outer:
while (true) {
List<CanteenHotelEntity> rows = hotelMapper.selectList(Wrappers.<CanteenHotelEntity>lambdaQuery()
.select(CanteenHotelEntity::getId, CanteenHotelEntity::getHotelCode,
CanteenHotelEntity::getHotelName)
.gt(CanteenHotelEntity::getId, lastId)
.and(w -> w.isNull(CanteenHotelEntity::getUpstreamStatus)
List<SmHotelEntity> rows = hotelMapper.selectList(Wrappers.<SmHotelEntity>lambdaQuery()
.select(SmHotelEntity::getId, SmHotelEntity::getHotelCode,
SmHotelEntity::getHotelName)
.gt(SmHotelEntity::getId, lastId)
.and(w -> w.isNull(SmHotelEntity::getUpstreamStatus)
.or()
.ne(CanteenHotelEntity::getUpstreamStatus, "OFFLINE"))
.orderByAsc(CanteenHotelEntity::getId)
.ne(SmHotelEntity::getUpstreamStatus, "OFFLINE"))
.orderByAsc(SmHotelEntity::getId)
.last("limit " + batchSize));
if (CollUtil.isEmpty(rows)) {
break;
}
for (CanteenHotelEntity h : rows) {
for (SmHotelEntity h : rows) {
lastId = h.getId();
if (maxHotels > 0 && processed >= maxHotels) {
break outer;
@@ -484,7 +484,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
}
CanteenHotelSyncLogEntity done = syncLogMapper.selectById(logId);
SmHotelSyncLogEntity done = syncLogMapper.selectById(logId);
if (done == null) {
return;
}
@@ -516,14 +516,14 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
long t0 = System.currentTimeMillis();
try {
progress(logId, 5, "SCAN", "正在按失败明细匹配本地酒店…");
List<CanteenHotelEntity> hotels = new ArrayList<>();
List<SmHotelEntity> hotels = new ArrayList<>();
int batch = 200;
for (int i = 0; i < hotelCodes.size(); i += batch) {
List<String> slice = hotelCodes.subList(i, Math.min(i + batch, hotelCodes.size()));
List<CanteenHotelEntity> part = hotelMapper.selectList(Wrappers.<CanteenHotelEntity>lambdaQuery()
.select(CanteenHotelEntity::getId, CanteenHotelEntity::getHotelCode,
CanteenHotelEntity::getHotelName)
.in(CanteenHotelEntity::getHotelCode, slice));
List<SmHotelEntity> part = hotelMapper.selectList(Wrappers.<SmHotelEntity>lambdaQuery()
.select(SmHotelEntity::getId, SmHotelEntity::getHotelCode,
SmHotelEntity::getHotelName)
.in(SmHotelEntity::getHotelCode, slice));
if (CollUtil.isNotEmpty(part)) {
hotels.addAll(part);
}
@@ -545,7 +545,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
+ (missing > 0 ? "(明细中有 " + missing + " 家本地未匹配)" : "")
+ (TYPE_ROLL.equals(syncType) ? " day=" + day : "") + "…");
for (CanteenHotelEntity h : hotels) {
for (SmHotelEntity h : hotels) {
processed++;
if (StrUtil.isBlank(h.getHotelCode())) {
skip++;
@@ -586,7 +586,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
}
CanteenHotelSyncLogEntity done = syncLogMapper.selectById(logId);
SmHotelSyncLogEntity done = syncLogMapper.selectById(logId);
if (done == null) {
return;
}
@@ -632,7 +632,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
/** 从滚价日志文案解析日期;解析不到则用配置偏移 */
private LocalDate resolveRollDay(CanteenHotelSyncLogEntity src) {
private LocalDate resolveRollDay(SmHotelSyncLogEntity src) {
String msg = StrUtil.blankToDefault(src.getStageMsg(), "") + " " + StrUtil.blankToDefault(src.getErrorMsg(), "");
java.util.regex.Matcher m = java.util.regex.Pattern.compile("day=(\\d{4}-\\d{2}-\\d{2})").matcher(msg);
if (m.find()) {
@@ -646,7 +646,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
return LocalDate.now().plusDays(Math.max(1, properties.getPriceRollDayOffset()));
}
private static void appendFail(List<String> failLines, CanteenHotelEntity h, String reason) {
private static void appendFail(List<String> failLines, SmHotelEntity h, String reason) {
if (failLines == null) {
return;
}
@@ -659,7 +659,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
failLines.add(code + "|" + name + "|" + StrUtil.maxLength(StrUtil.blankToDefault(reason, "未知错误"), 300));
}
private static void applyFailDetail(CanteenHotelSyncLogEntity done, List<String> failLines, int fail) {
private static void applyFailDetail(SmHotelSyncLogEntity done, List<String> failLines, int fail) {
if (fail <= 0 || CollUtil.isEmpty(failLines)) {
return;
}
@@ -715,8 +715,8 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
}
private CanteenHotelSyncLogEntity newLog(String syncType, String triggerType) {
CanteenHotelSyncLogEntity e = new CanteenHotelSyncLogEntity();
private SmHotelSyncLogEntity newLog(String syncType, String triggerType) {
SmHotelSyncLogEntity e = new SmHotelSyncLogEntity();
e.setSyncType(syncType);
e.setTriggerType(StrUtil.blankToDefault(triggerType, "MANUAL"));
e.setStatus(STATUS_RUNNING);
@@ -739,7 +739,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
private void progress(Long logId, int pct, String stage, String msg) {
CanteenHotelSyncLogEntity e = syncLogMapper.selectById(logId);
SmHotelSyncLogEntity e = syncLogMapper.selectById(logId);
if (e == null) {
return;
}
@@ -751,7 +751,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
}
private void failLog(Long logId, String err, long costMs) {
CanteenHotelSyncLogEntity e = syncLogMapper.selectById(logId);
SmHotelSyncLogEntity e = syncLogMapper.selectById(logId);
if (e == null) {
return;
}
@@ -793,17 +793,17 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
long lastId = 0L;
int batch = Math.max(50, properties.getDiffScanBatchSize());
while (true) {
List<CanteenHotelEntity> rows = hotelMapper.selectList(Wrappers.<CanteenHotelEntity>lambdaQuery()
.select(CanteenHotelEntity::getId, CanteenHotelEntity::getHotelCode)
.eq(CanteenHotelEntity::getUpstreamStatus, "OFFLINE")
.gt(CanteenHotelEntity::getId, lastId)
.orderByAsc(CanteenHotelEntity::getId)
List<SmHotelEntity> rows = hotelMapper.selectList(Wrappers.<SmHotelEntity>lambdaQuery()
.select(SmHotelEntity::getId, SmHotelEntity::getHotelCode)
.eq(SmHotelEntity::getUpstreamStatus, "OFFLINE")
.gt(SmHotelEntity::getId, lastId)
.orderByAsc(SmHotelEntity::getId)
.last("limit " + batch));
if (CollUtil.isEmpty(rows)) {
break;
}
List<String> back = new ArrayList<>();
for (CanteenHotelEntity h : rows) {
for (SmHotelEntity h : rows) {
lastId = h.getId();
if (StrUtil.isBlank(h.getHotelCode())) {
continue;
@@ -826,9 +826,9 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
if (CollUtil.isEmpty(codes)) {
return 0;
}
return hotelMapper.update(null, Wrappers.<CanteenHotelEntity>lambdaUpdate()
.set(CanteenHotelEntity::getUpstreamStatus, status)
.in(CanteenHotelEntity::getHotelCode, codes));
return hotelMapper.update(null, Wrappers.<SmHotelEntity>lambdaUpdate()
.set(SmHotelEntity::getUpstreamStatus, status)
.in(SmHotelEntity::getHotelCode, codes));
}
@Override
@@ -943,7 +943,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
if (!properties.isHotelListDailySyncEnabled()) {
return Map.of("skipped", true, "reason", "hotel-list-daily-sync-enabled=false");
}
R<CanteenHotelSyncLogEntity> r = startListSyncAsync(properties.isAutoImportNewHotels(),
R<SmHotelSyncLogEntity> r = startListSyncAsync(properties.isAutoImportNewHotels(),
StrUtil.blankToDefault(triggerType, "XXL"));
if (r.getCode() != 0) {
return Map.of("ok", false, "msg", r.getMsg());
@@ -964,7 +964,7 @@ public class CanteenHotelSyncServiceImpl implements CanteenHotelSyncService {
if (!properties.isPriceRollDailyEnabled()) {
return Map.of("skipped", true, "reason", "price-roll-daily-enabled=false");
}
R<CanteenHotelSyncLogEntity> r = startPriceRollAsync(StrUtil.blankToDefault(triggerType, "XXL"));
R<SmHotelSyncLogEntity> r = startPriceRollAsync(StrUtil.blankToDefault(triggerType, "XXL"));
if (r.getCode() != 0) {
return Map.of("ok", false, "msg", r.getMsg());
}
@@ -1,15 +1,15 @@
package com.bsd.pjcloud.canteen.service.impl;
package com.bsd.pjcloud.supermarket.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.bsd.pjcloud.canteen.entity.CanteenHotelEntity;
import com.bsd.pjcloud.canteen.integration.shangyou.ShangyouHotelClient;
import com.bsd.pjcloud.canteen.mapper.CanteenHotelMapper;
import com.bsd.pjcloud.canteen.service.CanteenHotelCallbackTaskService;
import com.bsd.pjcloud.canteen.service.CanteenHotelUpstreamService;
import com.bsd.pjcloud.supermarket.entity.SmHotelEntity;
import com.bsd.pjcloud.supermarket.integration.shangyou.ShangyouHotelClient;
import com.bsd.pjcloud.supermarket.mapper.SmHotelMapper;
import com.bsd.pjcloud.supermarket.service.SmHotelCallbackTaskService;
import com.bsd.pjcloud.supermarket.service.SmHotelUpstreamService;
import com.bsd.pjcloud.common.core.util.R;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -28,13 +28,13 @@ import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class CanteenHotelUpstreamServiceImpl implements CanteenHotelUpstreamService {
public class SmHotelUpstreamServiceImpl implements SmHotelUpstreamService {
private final ShangyouHotelClient client;
private final CanteenHotelMapper hotelMapper;
private final SmHotelMapper hotelMapper;
private final CanteenHotelCallbackTaskService callbackTaskService;
private final SmHotelCallbackTaskService callbackTaskService;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -42,7 +42,7 @@ public class CanteenHotelUpstreamServiceImpl implements CanteenHotelUpstreamServ
if (hotelId == null) {
return R.failed("酒店ID不能为空");
}
CanteenHotelEntity hotel = hotelMapper.selectById(hotelId);
SmHotelEntity hotel = hotelMapper.selectById(hotelId);
if (hotel == null) {
return R.failed("酒店不存在");
}
@@ -164,7 +164,7 @@ public class CanteenHotelUpstreamServiceImpl implements CanteenHotelUpstreamServ
return callbackTaskService.enqueueFromNotify(notifyType, body, time, sign);
}
private void applyHotelComplex(CanteenHotelEntity hotel, com.alibaba.fastjson.JSONObject data) {
private void applyHotelComplex(SmHotelEntity hotel, com.alibaba.fastjson.JSONObject data) {
if (data == null || data.isEmpty()) {
return;
}
@@ -23,3 +23,105 @@ spring:
# username: root
# password: root
# url: jdbc:mysql://pjcloud-mysql:3306/pjcloudx_supermarket?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true
## ========== 玉编电云 / TMC CRS 酒店上游(docs/shangyou)==========
## 生产对方通常只给一个根地址:https://onlink.yubdianyun.cn/link/provider
## 此时只配 base-url 即可:鉴权 POST {base-url}/oauth/token ,业务 POST {base-url}/hotel/...
## 测试若鉴权与业务拆成两个地址,再单独配 auth-base-url / biz-base-url
#shangyou-hotel:
# # 是否启用上游调用(false 时拉酒店/房价/下单都会直接报「未启用」)
# enabled: true
# # 上游根地址(生产常用这一项即可,同时用于鉴权+业务)
# base-url: https://onlink.yubdianyun.cn/link/provider
# # 鉴权根地址;一般留空,自动用 base-url。仅当测试环境鉴权与业务分离时才填,例 https://xxx/link
# # auth-base-url: ""
# # 业务根地址;一般留空,自动用 base-url。仅当业务地址与 base-url 不同时才填
# # biz-base-url: ""
# # OAuth clientId(对方开通账号时下发,用于换 access_token)
# client-id: F210AE02B74C48A3901B
# # OAuth clientSecret(与 client-id 配对,Basic 鉴权换 token)
# client-secret: 99165116A43F413CB799C91714861408
# # 业务卡号 cardId(账号),请求体 content 里会带
# card-id: 9082727358de43be96fe
# # 业务秘钥 cardPassWord,请求体 content 里会带;也可兼作回调验签 Secret
# card-password: 5bffd3c42e5a42219872bace3092983d
# # 房价/房量回调验签 Secret:sign=MD5(Secret+time);留空则用上面的 card-password
# callback-secret: 99165116A43F413CB799C91714861408
# # 下单预订人 bookerId;留空则用 card-id;以对方开通为准
# booker-id: ""
# # 是否总对总下单(企业中转一般 true;现付调试可 false)
# order-is-group: true
# # 担保模式:NONE / FIRST_NIGHT / FULL_AMOUNT,以对方开卡为准
# order-guarantee-mode: NONE
# # 房价接口路径。生产必须用 /hotel/getRoomPrice(/hotel/getTMCRoomPrice 会 404)
# room-price-path: /hotel/getRoomPrice
# # 会员等级,逗号分隔;对方要求传时再填,空则不传该字段
# member-levels: ""
# # 调上游 HTTP 超时(毫秒),含拉酒店列表/房价等
# timeout-ms: 60000
# # token 提前作废秒数(对方 token 默认约 21600 秒);避免边界时刻用到已失效 token
# token-skew-seconds: 120
# # 「拉取上游」时拉未来多少天房价;建议 1~90;接口单次约 31 天,代码会自动按段切片
# price-days: 90
# # 授权酒店列表 Redis 缓存分钟数(HASH+ZSET,不落 JVM 全量,支持十几万级)
# hotel-list-cache-minutes: 30
# # 授权酒店数量告警阈值(仅打日志告警,不截断);十几万级强制刷新建议低峰做
# hotel-list-warn-size: 100000
# # 回调无 TENANT-ID:写入任务/匹配本地酒店用的默认租户(酒店中转一般单租户)
# callback-tenant-id: 1
# # 是否启用回调异步队列 Worker(Redis BRPOP 消费后 pullFromUpstream)
# callback-queue-enabled: true
# # 单条回调任务最大尝试次数(含首次;失败会自动重入队)
# callback-max-attempts: 3
# # 回调队列处理完一家后的间隔毫秒(房价另有 QPS 限流,这里可较小)
# callback-task-interval-ms: 50
# # 房价 getRoomPrice 限流(对方约定约 20 QPS)。多实例请均分,如 2 实例各配 10;≤0 关闭
# price-api-qps: 20
# # ----- 日更 / 差集 -----
# # 酒店列表日同步开关(false 则定时/XXL 都跳过)
# hotel-list-daily-sync-enabled: true
# # 是否启用本服务 Spring Cron(改下面 cron 即可生效;已用 XXL 请设 false,避免一天跑两次)
# spring-schedule-enabled: true
# # 列表日更时间:默认每天 02:00(Spring Cron 6 段:秒 分 时 日 月 周)
# hotel-list-daily-cron: "0 0 2 * * ?"
# # 滚价日更时间:默认每天 03:00
# price-roll-daily-cron: "0 0 3 * * ?"
# # 列表同步后是否自动把「上游有本地无」写入本地主数据
# auto-import-new-hotels: true
# # 自动导入单次上限(剩余留在差集,可再点导入)
# auto-import-batch-size: 5000
# # 每日滚第 N 天房价开关
# price-roll-daily-enabled: true
# # 滚价偏移:today + N(文档第 91 天 → 90)
# price-roll-day-offset: 90
# # 滚价按本地酒店 id 游标每批数量(防 OOM)
# price-roll-batch-size: 100
# # 全量房价房量:每天最多次数 / 最小间隔小时(「拉取全部启用详情」受此限制)
# full-price-sync-max-per-day: 3
# full-price-sync-min-interval-hours: 6
# # 全量拉详情:每家间隔毫秒(落库已批量,默认 0;上游压力大时可调大)
# detail-pull-interval-ms: 0
# # 全量拉详情单次最多家数;0=不限制(酒店很多时建议先设 100 试跑)
# detail-pull-max-hotels: 0
# # 差集扫描 / 重建本地 code SET 批大小
# diff-scan-batch-size: 500
# # 同步后:本地有上游无 → 自动标 OFFLINE 停用
# auto-mark-offline-hotels: true
# # 同步后:已停用但上游又出现 → 自动恢复 ACTIVE
# auto-reactivate-online-hotels: true
#
## ========== 下游销售方推送(《第三方数据同步接口文档》)==========
## 本系统作为中转 A,主动把加价后的酒店/房价推到下游 B(与上面「上游」无关,可单独开关)
#hotel-downstream:
# # 是否启用向下游推送
# enabled: false
# # 下游 B 系统根地址(不含尾斜杠),实际请求 = base-url + /third/party/api/...
# base-url: https://b.example.com
# # B 系统分配给我们的 appKey(请求头/签名用)
# app-key: TP_xxx
# # B 系统分配的 appSecret(仅本地算签名,不落报文)
# app-secret: your-secret
# # 推下游 HTTP 超时(毫秒)
# timeout-ms: 30000
# # 兼容字段;实际上游拉取天数以 shangyou-hotel.price-days 为准
# daily-days: 90
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bsd.pjcloud.canteen.mapper.CanteenHotelDailyMapper">
<mapper namespace="com.bsd.pjcloud.supermarket.mapper.SmHotelDailyMapper">
<insert id="insertBatch">
INSERT INTO canteen_hotel_daily (
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bsd.pjcloud.canteen.mapper.CanteenHotelMapper">
<mapper namespace="com.bsd.pjcloud.supermarket.mapper.SmHotelMapper">
<insert id="insertBatch">
INSERT INTO canteen_hotel (
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bsd.pjcloud.canteen.mapper.CanteenHotelProductMapper">
<mapper namespace="com.bsd.pjcloud.supermarket.mapper.SmHotelProductMapper">
<insert id="insertBatch">
INSERT INTO canteen_hotel_product (
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bsd.pjcloud.canteen.mapper.CanteenHotelRoomMapper">
<mapper namespace="com.bsd.pjcloud.supermarket.mapper.SmHotelRoomMapper">
<insert id="insertBatch">
INSERT INTO canteen_hotel_room (