diff --git a/sql/mysql/member/member_airline_data.sql b/sql/mysql/member/member_airline_data.sql new file mode 100644 index 0000000..1023339 --- /dev/null +++ b/sql/mysql/member/member_airline_data.sql @@ -0,0 +1,51 @@ +-- ---------------------------------------------------------------------------- +-- 航空 App 数据云同步:新增航线 / 我的(积点钱包) +-- 数据归属:member_airline_account.id(登录账号),一账号一套数据 +-- ---------------------------------------------------------------------------- + +-- 用户自建的飞行任务(航线) +CREATE TABLE IF NOT EXISTS `member_airline_flight` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `account_id` bigint NOT NULL COMMENT '航空账号编号 member_airline_account.id', + `flight_no` varchar(32) NULL DEFAULT '' COMMENT '航班号', + `title` varchar(64) NULL DEFAULT '' COMMENT '任务/航班名称', + `begin_city` varchar(64) NULL DEFAULT '' COMMENT '出发城市', + `begin_airport` varchar(128) NULL DEFAULT '' COMMENT '出发机场', + `end_city` varchar(64) NULL DEFAULT '' COMMENT '到达城市', + `end_airport` varchar(128) NULL DEFAULT '' COMMENT '到达机场', + `classes` varchar(128) NULL DEFAULT '' COMMENT '舱位/班次', + `status` varchar(32) NULL DEFAULT '' COMMENT '状态', + `fly_begin_date0` varchar(32) NULL DEFAULT '' COMMENT '计划起飞时间', + `fly_end_date0` varchar(32) NULL DEFAULT '' COMMENT '计划到达时间', + `fly_begin_date1` varchar(32) NULL DEFAULT '' COMMENT '实际起飞时间', + `fly_end_date1` varchar(32) NULL DEFAULT '' COMMENT '实际到达时间', + `sign_in_time` varchar(32) NULL DEFAULT '' COMMENT '签到时间', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + `creator` varchar(64) NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_account_id` (`account_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='航空App用户自建航线'; + +-- 我的页面:积点/钱包(每账号一行) +CREATE TABLE IF NOT EXISTS `member_airline_point` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `account_id` bigint NOT NULL COMMENT '航空账号编号 member_airline_account.id', + `current_month` varchar(16) NULL DEFAULT '00' COMMENT '当月飞行', + `current_year` varchar(16) NULL DEFAULT '00' COMMENT '年度飞行', + `jixiao` varchar(16) NULL DEFAULT '00' COMMENT '绩效积点', + `yanwu` varchar(16) NULL DEFAULT '00' COMMENT '延误积点', + `current_point` varchar(16) NULL DEFAULT '00' COMMENT '当前积点', + `wallet` varchar(16) NULL DEFAULT '00' COMMENT '钱包余额', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + `creator` varchar(64) NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `uk_account_id` (`account_id`, `deleted`, `tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='航空App我的积点钱包'; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/airline/AppAirlineDataController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/airline/AppAirlineDataController.java new file mode 100644 index 0000000..fe7c0e8 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/airline/AppAirlineDataController.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.member.controller.app.airline; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.member.controller.app.airline.vo.AirlineFlightVO; +import cn.iocoder.yudao.module.member.controller.app.airline.vo.AirlinePointVO; +import cn.iocoder.yudao.module.member.service.airline.MemberAirlineDataService; +import io.swagger.v3.oas.annotations.Operation; +import javax.annotation.security.PermitAll; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +/** + * 免登录接口(@PermitAll):身份由 mobile + channel + deviceId 三要素定位, + * 与 airline-check 相同的账号状态/有效期/设备绑定校验,防冒用。 + */ +@Tag(name = "用户 APP - 航空 App 数据云同步(自建航线/我的积点钱包)") +@RestController +@RequestMapping("/member/airline-data") +@Validated +public class AppAirlineDataController { + + @Resource + private MemberAirlineDataService airlineDataService; + + // ─── 航线 ──────────────────────────────────────────────── + + @GetMapping("/flight/list") + @Operation(summary = "航线列表") + @PermitAll + public CommonResult> flightList(@RequestParam("mobile") String mobile, + @RequestParam("deviceId") String deviceId, + @RequestParam("channel") String channel) { + return success(airlineDataService.getFlightList(mobile, deviceId, channel)); + } + + @PostMapping("/flight/create") + @Operation(summary = "新增航线") + @PermitAll + public CommonResult flightCreate(@RequestParam("mobile") String mobile, + @RequestParam("deviceId") String deviceId, + @RequestParam("channel") String channel, + @RequestBody AirlineFlightVO vo) { + return success(airlineDataService.createFlight(mobile, deviceId, channel, vo)); + } + + @PutMapping("/flight/update") + @Operation(summary = "更新航线") + @PermitAll + public CommonResult flightUpdate(@RequestParam("mobile") String mobile, + @RequestParam("deviceId") String deviceId, + @RequestParam("channel") String channel, + @RequestBody AirlineFlightVO vo) { + airlineDataService.updateFlight(mobile, deviceId, channel, vo); + return success(true); + } + + @DeleteMapping("/flight/delete") + @Operation(summary = "删除航线") + @PermitAll + public CommonResult flightDelete(@RequestParam("mobile") String mobile, + @RequestParam("deviceId") String deviceId, + @RequestParam("channel") String channel, + @RequestParam("id") Long id) { + airlineDataService.deleteFlight(mobile, deviceId, channel, id); + return success(true); + } + + // ─── 我的:积点/钱包 ───────────────────────────────────── + + @GetMapping("/point/get") + @Operation(summary = "我的积点/钱包") + @PermitAll + public CommonResult pointGet(@RequestParam("mobile") String mobile, + @RequestParam("deviceId") String deviceId, + @RequestParam("channel") String channel) { + return success(airlineDataService.getPoint(mobile, deviceId, channel)); + } + + @PutMapping("/point/update") + @Operation(summary = "保存我的积点/钱包") + @PermitAll + public CommonResult pointUpdate(@RequestParam("mobile") String mobile, + @RequestParam("deviceId") String deviceId, + @RequestParam("channel") String channel, + @RequestBody AirlinePointVO vo) { + airlineDataService.updatePoint(mobile, deviceId, channel, vo); + return success(true); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/airline/vo/AirlineFlightVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/airline/vo/AirlineFlightVO.java new file mode 100644 index 0000000..9b00c61 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/airline/vo/AirlineFlightVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.member.controller.app.airline.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 APP - 航空 App 自建航线 VO") +@Data +public class AirlineFlightVO { + + @Schema(description = "编号(新增时不传,更新时必传)", example = "1") + private Long id; + + @Schema(description = "航班号", example = "CZ3101") + private String flightNo; + + @Schema(description = "任务/航班名称") + private String title; + + @Schema(description = "出发城市") + private String beginCity; + + @Schema(description = "出发机场") + private String beginAirport; + + @Schema(description = "到达城市") + private String endCity; + + @Schema(description = "到达机场") + private String endAirport; + + @Schema(description = "舱位/班次") + private String classes; + + @Schema(description = "状态") + private String status; + + @Schema(description = "计划起飞时间") + private String flyBeginDate0; + + @Schema(description = "计划到达时间") + private String flyEndDate0; + + @Schema(description = "实际起飞时间") + private String flyBeginDate1; + + @Schema(description = "实际到达时间") + private String flyEndDate1; + + @Schema(description = "签到时间") + private String signInTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/airline/vo/AirlinePointVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/airline/vo/AirlinePointVO.java new file mode 100644 index 0000000..92e458c --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/airline/vo/AirlinePointVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.member.controller.app.airline.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 APP - 航空 App 我的积点/钱包 VO") +@Data +public class AirlinePointVO { + + @Schema(description = "当月飞行", example = "12") + private String currentMonth; + + @Schema(description = "年度飞行", example = "130") + private String currentYear; + + @Schema(description = "绩效积点", example = "08") + private String jixiao; + + @Schema(description = "延误积点", example = "00") + private String yanwu; + + @Schema(description = "当前积点", example = "260") + private String currentPoint; + + @Schema(description = "钱包余额", example = "1280.00") + private String wallet; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/airline/MemberAirlineFlightDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/airline/MemberAirlineFlightDO.java new file mode 100644 index 0000000..64c6c2e --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/airline/MemberAirlineFlightDO.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.airline; + +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 航空 App 用户自建航线 DO + */ +@TableName("member_airline_flight") +@KeySequence("member_airline_flight_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberAirlineFlightDO extends TenantBaseDO { + + @TableId + private Long id; + /** 航空账号编号 member_airline_account.id */ + private Long accountId; + /** 航班号 */ + private String flightNo; + /** 任务/航班名称 */ + private String title; + /** 出发城市 */ + private String beginCity; + /** 出发机场 */ + private String beginAirport; + /** 到达城市 */ + private String endCity; + /** 到达机场 */ + private String endAirport; + /** 舱位/班次 */ + private String classes; + /** 状态 */ + private String status; + /** 计划起飞时间 */ + private String flyBeginDate0; + /** 计划到达时间 */ + private String flyEndDate0; + /** 实际起飞时间 */ + private String flyBeginDate1; + /** 实际到达时间 */ + private String flyEndDate1; + /** 签到时间 */ + private String signInTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/airline/MemberAirlinePointDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/airline/MemberAirlinePointDO.java new file mode 100644 index 0000000..f418d73 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/airline/MemberAirlinePointDO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.airline; + +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 航空 App 我的积点/钱包 DO(每账号一行) + */ +@TableName("member_airline_point") +@KeySequence("member_airline_point_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberAirlinePointDO extends TenantBaseDO { + + @TableId + private Long id; + /** 航空账号编号 member_airline_account.id */ + private Long accountId; + /** 当月飞行 */ + private String currentMonth; + /** 年度飞行 */ + private String currentYear; + /** 绩效积点 */ + private String jixiao; + /** 延误积点 */ + private String yanwu; + /** 当前积点 */ + private String currentPoint; + /** 钱包余额 */ + private String wallet; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/airline/MemberAirlineFlightMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/airline/MemberAirlineFlightMapper.java new file mode 100644 index 0000000..4baceef --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/airline/MemberAirlineFlightMapper.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.member.dal.mysql.airline; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.member.dal.dataobject.airline.MemberAirlineFlightDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface MemberAirlineFlightMapper extends BaseMapperX { + + default List selectListByAccountId(Long accountId) { + return selectList(new LambdaQueryWrapperX() + .eq(MemberAirlineFlightDO::getAccountId, accountId) + .orderByDesc(MemberAirlineFlightDO::getId)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/airline/MemberAirlinePointMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/airline/MemberAirlinePointMapper.java new file mode 100644 index 0000000..89d0313 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/airline/MemberAirlinePointMapper.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.member.dal.mysql.airline; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.member.dal.dataobject.airline.MemberAirlinePointDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface MemberAirlinePointMapper extends BaseMapperX { + + default MemberAirlinePointDO selectByAccountId(Long accountId) { + return selectOne(new LambdaQueryWrapperX() + .eq(MemberAirlinePointDO::getAccountId, accountId)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineAccountService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineAccountService.java index cbf41b2..d705ec6 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineAccountService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineAccountService.java @@ -40,6 +40,6 @@ public interface MemberAirlineAccountService { * ③ 都没有 → 仅按设备识别号兜底(设备绑定的任一有效账号即放行)。 * 校验内容:账号存在、未禁用、在有效期内、设备绑定匹配。 */ - void validateAirlineSession(Long loginUserId, String mobile, String deviceId, String channel); + MemberAirlineAccountDO validateAirlineSession(Long loginUserId, String mobile, String deviceId, String channel); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineAccountServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineAccountServiceImpl.java index f7fe46d..29d9e10 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineAccountServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineAccountServiceImpl.java @@ -126,7 +126,7 @@ public class MemberAirlineAccountServiceImpl implements MemberAirlineAccountServ } @Override - public void validateAirlineSession(Long loginUserId, String mobile, String deviceId, String channel) { + public MemberAirlineAccountDO validateAirlineSession(Long loginUserId, String mobile, String deviceId, String channel) { // ① 手机号+渠道:精确匹配,直接认定是本人账号 if (StrUtil.isNotBlank(mobile) && StrUtil.isNotBlank(channel)) { MemberAirlineAccountDO account = airlineAccountMapper.selectByMobileAndChannel(mobile, channel); @@ -134,7 +134,7 @@ public class MemberAirlineAccountServiceImpl implements MemberAirlineAccountServ throw exception(AIRLINE_ACCOUNT_NOT_EXISTS); } validateAccount(account, deviceId); - return; + return account; } // 收集候选账号:② Token 定位 + ③ 设备识别号定位(两者合并,逐个核实) @@ -164,7 +164,7 @@ public class MemberAirlineAccountServiceImpl implements MemberAirlineAccountServ continue; } validateAccount(account, deviceId); - return; + return account; } // 所有候选的绑定设备都与本机不符 throw exception(AIRLINE_ACCOUNT_DEVICE_BOUND); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineDataService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineDataService.java new file mode 100644 index 0000000..31f23fa --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineDataService.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.member.service.airline; + +import cn.iocoder.yudao.module.member.controller.app.airline.vo.AirlineFlightVO; +import cn.iocoder.yudao.module.member.controller.app.airline.vo.AirlinePointVO; + +import java.util.List; + +/** + * 航空 App 数据云同步(自建航线 / 我的积点钱包) + */ +public interface MemberAirlineDataService { + + /** 航线列表(按账号) */ + List getFlightList(String mobile, String deviceId, String channel); + + /** 新增航线,返回编号 */ + Long createFlight(String mobile, String deviceId, String channel, AirlineFlightVO vo); + + /** 更新航线(校验归属) */ + void updateFlight(String mobile, String deviceId, String channel, AirlineFlightVO vo); + + /** 删除航线(校验归属) */ + void deleteFlight(String mobile, String deviceId, String channel, Long id); + + /** 我的积点/钱包(不存在则创建默认行) */ + AirlinePointVO getPoint(String mobile, String deviceId, String channel); + + /** 保存我的积点/钱包 */ + void updatePoint(String mobile, String deviceId, String channel, AirlinePointVO vo); + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineDataServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineDataServiceImpl.java new file mode 100644 index 0000000..b1f57ba --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/airline/MemberAirlineDataServiceImpl.java @@ -0,0 +1,164 @@ +package cn.iocoder.yudao.module.member.service.airline; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.member.controller.app.airline.vo.AirlineFlightVO; +import cn.iocoder.yudao.module.member.controller.app.airline.vo.AirlinePointVO; +import cn.iocoder.yudao.module.member.dal.dataobject.airline.MemberAirlineAccountDO; +import cn.iocoder.yudao.module.member.dal.dataobject.airline.MemberAirlineFlightDO; +import cn.iocoder.yudao.module.member.dal.dataobject.airline.MemberAirlinePointDO; +import cn.iocoder.yudao.module.member.dal.mysql.airline.MemberAirlineFlightMapper; +import cn.iocoder.yudao.module.member.dal.mysql.airline.MemberAirlinePointMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.member.enums.MemberErrorCode.AIRLINE_ACCOUNT_NOT_EXISTS; + +/** + * 航空 App 数据云同步实现。 + * 身份定位:复用 validateAirlineSession(免 Token,手机号+渠道+设备识别号),并顺带校验账号状态与设备绑定。 + */ +@Service +@Validated +public class MemberAirlineDataServiceImpl implements MemberAirlineDataService { + + @Resource + private MemberAirlineAccountService airlineAccountService; + @Resource + private MemberAirlineFlightMapper flightMapper; + @Resource + private MemberAirlinePointMapper pointMapper; + + @Override + public List getFlightList(String mobile, String deviceId, String channel) { + MemberAirlineAccountDO account = resolveAccount(mobile, deviceId, channel); + return flightMapper.selectListByAccountId(account.getId()).stream() + .map(this::convertFlight).collect(java.util.stream.Collectors.toList()); + } + + @Override + public Long createFlight(String mobile, String deviceId, String channel, AirlineFlightVO vo) { + MemberAirlineAccountDO account = resolveAccount(mobile, deviceId, channel); + MemberAirlineFlightDO flight = convertFlight(vo); + flight.setId(null); + flight.setAccountId(account.getId()); + flightMapper.insert(flight); + return flight.getId(); + } + + @Override + public void updateFlight(String mobile, String deviceId, String channel, AirlineFlightVO vo) { + MemberAirlineAccountDO account = resolveAccount(mobile, deviceId, channel); + MemberAirlineFlightDO exist = flightMapper.selectById(vo.getId()); + // 不存在或不属于当前账号,一律按不存在处理(防越权) + if (exist == null || !Objects.equals(exist.getAccountId(), account.getId())) { + throw exception(AIRLINE_ACCOUNT_NOT_EXISTS); + } + MemberAirlineFlightDO update = convertFlight(vo); + update.setId(exist.getId()); + update.setAccountId(account.getId()); + flightMapper.updateById(update); + } + + @Override + public void deleteFlight(String mobile, String deviceId, String channel, Long id) { + MemberAirlineAccountDO account = resolveAccount(mobile, deviceId, channel); + MemberAirlineFlightDO exist = flightMapper.selectById(id); + if (exist == null || !Objects.equals(exist.getAccountId(), account.getId())) { + throw exception(AIRLINE_ACCOUNT_NOT_EXISTS); + } + flightMapper.deleteById(id); + } + + @Override + public AirlinePointVO getPoint(String mobile, String deviceId, String channel) { + MemberAirlineAccountDO account = resolveAccount(mobile, deviceId, channel); + MemberAirlinePointDO point = pointMapper.selectByAccountId(account.getId()); + if (point == null) { + // 首次查询创建默认行 + point = MemberAirlinePointDO.builder().accountId(account.getId()) + .currentMonth("00").currentYear("00").jixiao("00") + .yanwu("00").currentPoint("00").wallet("00").build(); + pointMapper.insert(point); + } + return convertPoint(point); + } + + @Override + public void updatePoint(String mobile, String deviceId, String channel, AirlinePointVO vo) { + MemberAirlineAccountDO account = resolveAccount(mobile, deviceId, channel); + MemberAirlinePointDO point = pointMapper.selectByAccountId(account.getId()); + if (point == null) { + point = MemberAirlinePointDO.builder().accountId(account.getId()).build(); + } + point.setCurrentMonth(StrUtil.nullToEmpty(vo.getCurrentMonth())); + point.setCurrentYear(StrUtil.nullToEmpty(vo.getCurrentYear())); + point.setJixiao(StrUtil.nullToEmpty(vo.getJixiao())); + point.setYanwu(StrUtil.nullToEmpty(vo.getYanwu())); + point.setCurrentPoint(StrUtil.nullToEmpty(vo.getCurrentPoint())); + point.setWallet(StrUtil.nullToEmpty(vo.getWallet())); + if (point.getId() == null) { + pointMapper.insert(point); + } else { + pointMapper.updateById(point); + } + } + + private MemberAirlineAccountDO resolveAccount(String mobile, String deviceId, String channel) { + // 传 null 跳过 Token 定位路径,走 手机号+渠道(客户端固定会传) + return airlineAccountService.validateAirlineSession(null, mobile, deviceId, channel); + } + + private AirlineFlightVO convertFlight(MemberAirlineFlightDO d) { + AirlineFlightVO vo = new AirlineFlightVO(); + vo.setId(d.getId()); + vo.setFlightNo(d.getFlightNo()); + vo.setTitle(d.getTitle()); + vo.setBeginCity(d.getBeginCity()); + vo.setBeginAirport(d.getBeginAirport()); + vo.setEndCity(d.getEndCity()); + vo.setEndAirport(d.getEndAirport()); + vo.setClasses(d.getClasses()); + vo.setStatus(d.getStatus()); + vo.setFlyBeginDate0(d.getFlyBeginDate0()); + vo.setFlyEndDate0(d.getFlyEndDate0()); + vo.setFlyBeginDate1(d.getFlyBeginDate1()); + vo.setFlyEndDate1(d.getFlyEndDate1()); + vo.setSignInTime(d.getSignInTime()); + return vo; + } + + private MemberAirlineFlightDO convertFlight(AirlineFlightVO vo) { + MemberAirlineFlightDO d = new MemberAirlineFlightDO(); + d.setFlightNo(StrUtil.nullToEmpty(vo.getFlightNo())); + d.setTitle(StrUtil.nullToEmpty(vo.getTitle())); + d.setBeginCity(StrUtil.nullToEmpty(vo.getBeginCity())); + d.setBeginAirport(StrUtil.nullToEmpty(vo.getBeginAirport())); + d.setEndCity(StrUtil.nullToEmpty(vo.getEndCity())); + d.setEndAirport(StrUtil.nullToEmpty(vo.getEndAirport())); + d.setClasses(StrUtil.nullToEmpty(vo.getClasses())); + d.setStatus(StrUtil.nullToEmpty(vo.getStatus())); + d.setFlyBeginDate0(StrUtil.nullToEmpty(vo.getFlyBeginDate0())); + d.setFlyEndDate0(StrUtil.nullToEmpty(vo.getFlyEndDate0())); + d.setFlyBeginDate1(StrUtil.nullToEmpty(vo.getFlyBeginDate1())); + d.setFlyEndDate1(StrUtil.nullToEmpty(vo.getFlyEndDate1())); + d.setSignInTime(StrUtil.nullToEmpty(vo.getSignInTime())); + return d; + } + + private AirlinePointVO convertPoint(MemberAirlinePointDO d) { + AirlinePointVO vo = new AirlinePointVO(); + vo.setCurrentMonth(d.getCurrentMonth()); + vo.setCurrentYear(d.getCurrentYear()); + vo.setJixiao(d.getJixiao()); + vo.setYanwu(d.getYanwu()); + vo.setCurrentPoint(d.getCurrentPoint()); + vo.setWallet(d.getWallet()); + return vo; + } + +}