Przeglądaj źródła

设置库存预警通知;预备账号 预备账号计算可用车位数

zoujiajian 2 lat temu
rodzic
commit
68e778a3cd

+ 7 - 2
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -204,12 +204,17 @@ public interface Constant {
 
 	String DOUBLE_VERIFY_CODE_TIMES_KEY = "double_verify_code_times_key";
 
-	String AI_RENEW_MSG = "有人续费了 %s %s,请及时处理";
+	String AI_RENEW_MSG = "有人续费了 %s %s,请及时处理【银河录像局】";
 
-	String PAY_MSG = "有人购买了 %s %s,请及时处理";
+	String PAY_MSG = "有人购买了 %s %s,请及时处理【银河录像局】";
 
 	/**
 	 * 通知手机号
 	 */
 	String SERVICE_PHONE = "18658194165";
+
+	/**
+	 * AI 车票额外座位数
+	 */
+	Integer AI_EXTRACT_NUM = 5;
 }

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GroupsRelationAlertMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GroupsRelationAlert;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GroupsRelationAlertMapper
+ * 创建者: JavaZou
+ * 创建时间:2023/10/26 15:14
+ */
+public interface GroupsRelationAlertMapper extends BaseMapper<GroupsRelationAlert> {
+}

+ 4 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GroupsRelationMapper.java

@@ -53,4 +53,8 @@ public interface GroupsRelationMapper extends BaseMapper<GroupsRelation> {
 	Page<UserRecommendGoodsFrontView> getRecommendGoodsViews(@Param("page") Page<UserRecommendGoodsFrontView> page, @Param("list") List<Long> filter_goods_id, @Param("isPayNf") Boolean isPayNf);
 
 	Long getOutSideGroupsTripsRelationByGoodsId(@Param("skuId") Long skuId, @Param("beginOfDay") DateTime beginOfDay, @Param("extraNum") Integer extraNum, @Param("userId") Long userId);
+
+	Integer selectAvailableRelation(@Param("skuId") Long skuId);
+
+	Integer selectSpecialGroupsRelationAvailable(@Param("skuId") Long skuId, @Param("maxNum") Integer maxNum, @Param("extractNum") Integer extractNum, @Param("tenExpiry") DateTime tenExpiry);
 }

+ 10 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/Account.java

@@ -85,4 +85,14 @@ public class Account extends BaseEntity {
      * gpt accesToken
      */
     private String gptRefreshToken;
+
+    /**
+     * 备用账号类型sku_id
+     */
+    private Integer preSkuId;
+
+    /**
+     * 类型 1通用 2备用
+     */
+    private Integer type;
 }

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java

@@ -198,7 +198,7 @@ public class GoodsDon extends BaseEntity {
     public enum SpecialType {
         recharge("代充"),
         courseware("课程"),
-            giftCard("礼品卡")
+        giftCard("礼品卡")
         ;
 
         private String desc;

+ 47 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GroupsRelationAlert.java

@@ -0,0 +1,47 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GroupsRelationAlert
+ * 创建者: JavaZou
+ * 创建时间:2023/10/26 15:13
+ */
+@Getter
+@Setter
+public class GroupsRelationAlert extends BaseEntity{
+
+	/**
+	 * 针对库存
+	 */
+	@NotNull
+	private Long skuId;
+
+	/**
+	 * 预警数量
+	 */
+	@NotNull(message = "预警数量不为空")
+	@Min(value = 1, message = "请输入正确的库存预警数量")
+	private Integer num;
+
+	/**
+	 * 手机号
+	 */
+	@NotNull(message = "手机号不为空")
+	private String phoneStr;
+
+	/**
+	 * 预警开发
+	 */
+	private Boolean isOpen;
+
+	/**
+	 * 是否重置 根据新增对应规格账号 重置该预警记录
+	 */
+	private Boolean isReset;
+}

+ 7 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelManageAccountData.java

@@ -89,4 +89,11 @@ public class ExcelManageAccountData {
 	@DbIgnore
 	@ExcelIgnore
 	private Boolean expiredAll;
+
+	/**
+	 * 账号类型 2 备用
+	 */
+	@DbField("a.type")
+	@ExcelIgnore
+	private Integer accountType;
 }

+ 7 - 1
netflix-dao/src/main/java/com/cyksj/model/manage/views/AccountView.java

@@ -106,7 +106,7 @@ public class AccountView {
     @DbField("a.email")
     private String email;
 
-    @DbField("gdk.id")
+    @DbField("ifnull(gdk.id,a.pre_sku_id)")
     private Long skuId;
 
     @DbField("a.gpt_refresh_token")
@@ -137,4 +137,10 @@ public class AccountView {
 
     @DbIgnore
     private Date lastUpdatePwdDate;
+
+    @DbField("a.pre_sku_id")
+    private Long preSkuId;
+
+    @DbField("a.type")
+    private Integer accountType;
 }

+ 32 - 0
netflix-dao/src/main/resources/mapper/GroupRelationMapper.xml

@@ -237,4 +237,36 @@
             = #{userId}) = 0
         order by RAND() limit 1
     </select>
+
+    <select id="selectAvailableRelation" resultType="java.lang.Integer">
+        select count(gr.id)
+        from account a
+                 inner join `groups_trips` gt on gt.account_id = a.id
+            and gt.`status` = 'validity'
+            and gt.sku_id = #{skuId}
+                 inner join groups_relation gr on gr.groups_id = gt.id
+            and gr.user_id = 0
+            and gr.status = 'none'
+    </select>
+
+    <select id="selectSpecialGroupsRelationAvailable" resultType="java.lang.Integer">
+        select sum(a1+(#{extractNum}-t1)) from
+                                         (select gt.id,
+        (select count(*)
+        from groups_relation gr2
+        where gr2.groups_id = gt.id
+        and status = 'outside'
+        and num &lt;= #{maxNum}) t1,
+        (select count(*)
+        from groups_relation gr2
+        where gr2.groups_id = gt.id
+        and user_id = 0
+        and status = 'outside'
+        and num &lt;= #{maxNum}) a1
+        from account a
+        inner join `groups_trips` gt on gt.account_id = a.id
+        and gt.`status` = 'validity'
+        and gt.sku_id = #{skuId}
+        and a.expiry_time >= #{tenExpiry}) s where (t1=5 and a1=0) = 0
+    </select>
 </mapper>

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/mange/CmsGroupService.java

@@ -17,4 +17,6 @@ public interface CmsGroupService extends IService<GroupsTrips> {
     void setAccount(GroupsTrips groupsTrips) throws Exception;
 
     void replaceTripsAccount(ReplaceTripsAccountReq req);
+
+	Integer getAvailableRelation(Long goodsId, Long skuId);
 }

+ 72 - 4
netflix-service/src/main/java/com/cyksj/service/mange/group/CmsGroupServiceImpl.java

@@ -12,10 +12,10 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
 import com.cyksj.dto.RedisKey;
 import com.cyksj.mapper.*;
-import com.cyksj.mapper.manage.DelGroupsTripsRecordMapper;
 import com.cyksj.mapper.manage.GroupsTripsAccountReplaceRecordMapper;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.model.entity.*;
+import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.model.request.ReplaceTripsAccountReq;
 import com.cyksj.model.views.GroupsAccountView;
 import com.cyksj.redis.RedisService;
@@ -24,6 +24,7 @@ import com.cyksj.service.mange.CmsGroupService;
 import com.cyksj.service.sms.SmsService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -67,13 +68,11 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
 
     private final RedisService redisService;
 
-    private final DelGroupsTripsRecordMapper delGroupsTripsRecordMapper;
-
     private final GroupsMapper groupsMapper;
 
     private final AccountCommonService accountCommonService;
 
-    private final OrderDiscountPlusPurchaseSkuRelationMapper discountPlusPurchaseSkuRelationMapper;
+    private final GroupsRelationAlertMapper alertMapper;
 
     private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
 
@@ -108,6 +107,15 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
             }
             relationMapper.insert(relation);
         }
+        Integer alertCount = alertMapper.selectCount(Wrappers.lambdaQuery(GroupsRelationAlert.class)
+                .eq(GroupsRelationAlert::getSkuId, sku.getId())
+                .last("limit 1"));
+        if (alertCount > 0) {
+            alertMapper.update(null, Wrappers.lambdaUpdate(GroupsRelationAlert.class)
+                    .set(GroupsRelationAlert::getIsReset, true)
+                    .eq(GroupsRelationAlert::getSkuId, sku.getId())
+                    .eq(GroupsRelationAlert::getIsReset, false));
+        }
         return groups;
     }
 
@@ -166,6 +174,17 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
         if (count > 0) {
             throw new BusinessRuntimeException("该账号已发车.请选择未发车账户");
         }
+        Account account = accountMapper.selectById(groupsTrips.getAccountId());
+        //将预备账号 类型替换掉
+        if (account.getType() == 2) {
+            int update = accountMapper.update(null, Wrappers.lambdaUpdate(Account.class)
+                    .set(Account::getType, 1)
+                    .eq(Account::getId, account.getId())
+                    .eq(Account::getType, 2));
+            if (update == 0) {
+                throw BusinessRuntimeException.getInstance("该账号已配置车队");
+            }
+        }
         List<GroupsRelation> groupsRelations = relationMapper.selectList(Wrappers.lambdaQuery(GroupsRelation.class).eq(GroupsRelation::getGroupsId, groupsTrips.getId()).eq(GroupsRelation::getStatus, GroupsRelation.Status.validity));
         GroupsTrips trips = beanSearcher.searchFirst(GroupsTrips.class, MapUtils.builder().field(GroupsTrips::getId, groupsTrips.getId()).onlySelect(GroupsTrips::getTitle).build());
         String title = "车票";
@@ -254,6 +273,15 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
         }
        updateById(groupsTrips);
 
+        Integer alertCount = alertMapper.selectCount(Wrappers.lambdaQuery(GroupsRelationAlert.class)
+                .eq(GroupsRelationAlert::getSkuId, sku.getId())
+                .last("limit 1"));
+        if (alertCount > 0) {
+            alertMapper.update(null, Wrappers.lambdaUpdate(GroupsRelationAlert.class)
+                    .set(GroupsRelationAlert::getIsReset, true)
+                    .eq(GroupsRelationAlert::getSkuId, sku.getId())
+                    .eq(GroupsRelationAlert::getIsReset, false));
+        }
     }
 
     @Override
@@ -339,6 +367,29 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
         TASK_EXECUTOR.execute(() -> sendChangeAccountMsg(groupsId, goodsId));;
     }
 
+    @Override
+    public Integer getAvailableRelation(Long goodsId, Long skuId) {
+        //chatGPT
+        GoodsDonSku sku = skuMapper.selectById(skuId);
+        goodsId = sku.getGoodsId();
+        Integer skuNum = sku.getNum();
+        if (Constant.AI_goodsIds.contains(sku.getGoodsId()) && sku.getNum() > 1) {
+            Integer extraNum = Constant.AI_EXTRACT_NUM;
+            Integer maxNum = skuNum + extraNum;
+            DateTime tenExpiry = DateUtil.offsetDay(DateTime.now(), 10);
+            Integer available = relationMapper.selectAvailableRelation(skuId);
+            //额外硬塞
+            Integer special_available = relationMapper.selectSpecialGroupsRelationAvailable(skuId, maxNum, extraNum, tenExpiry);
+            available += special_available;
+            available = getAvailableAfterPreAccount(available, skuId, maxNum, goodsId);
+            return available;
+        }
+
+        Integer available = relationMapper.selectAvailableRelation(skuId);
+        available = getAvailableAfterPreAccount(available, skuId, skuNum, goodsId);
+        return available;
+    }
+
     private void sendChangeAccountMsg(Long groupsId, Long goodsId) {
         GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
         String title = goodsDon != null ? goodsDon.getTitle() : "车票";
@@ -365,4 +416,21 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
             }
         });
     }
+
+    public Integer getAvailableAfterPreAccount(Integer available, Long skuId, Integer maxNum, Long goodsId) {
+        MapBuilder builder = MapUtils.builder();
+        if (goodsId == 26) {
+            builder.field(AccountView::getPreSkuId, skuId);
+        }
+        Number preAccount = beanSearcher.searchCount(AccountView.class, builder
+                .field(AccountView::getGoodsId, goodsId)
+                .field(AccountView::getAccountType, 2)
+                .field(AccountView::getGroupsId).op(Operator.IsNull)
+                .build());
+        //计算上预发布账号车位数
+        if (preAccount.intValue() > 0) {
+            available += preAccount.intValue() * maxNum;
+        }
+        return available;
+    }
 }

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -201,7 +201,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 			}
 		}
 		//用户是否买了奈飞车票
-			Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder()
+		Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder()
 				.field(RenewalView::getUserId, userId)
 				.field(RenewalView::getGoodsId, 1)
 				.field(RenewalView::getStatus, List.of("validity", "overdue")).op(Operator.InList)

+ 21 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java

@@ -950,4 +950,25 @@ public class CmsAccountController {
 		}).sheet().doRead();
 		return GatewayResponse.SUCCESS.newBuilder().toResult(repeat);
 	}
+
+	/**
+	 * 新增预备账号
+	 */
+	@PostMapping("/post/prepare")
+	public Result<String> postPrepare(@RequestBody Account account) {
+		account.setAccount(account.getAccount().trim());
+		account.setPassword(account.getPassword().trim());
+		//账号是否已经添加过
+		if (!account.getAccount().contains("客服")) {
+			if (accountCommonService.checkIsDupAccount(account.getGoodsId(), account.getAccount())) {
+				throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
+			}
+		}
+		account.setType(2);
+		if (account.getGoodsId() == 26 && account.getPreSkuId() == null) {
+			throw BusinessRuntimeException.getInstance("请选择对应规格id");
+		}
+		accountService.save(account);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
 }

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonController.java

@@ -197,7 +197,7 @@ public class CmsGoodsDonController {
         List<GoodsDon> goodsDons = beanSearcher.searchAll(GoodsDon.class, MapUtils.flatBuilder(request.getParameterMap())
                 .field(GoodsDon::getDeleted, true)
                 .put("condition", "(special_type is null or special_type != 'giftCard')")
-                .onlySelect(GoodsDon::getId, GoodsDon::getCategory, GoodsDon::getType, GoodsDon::getTitle).build());
+                .onlySelect(GoodsDon::getId, GoodsDon::getCategory, GoodsDon::getType, GoodsDon::getTitle, GoodsDon::getSecondType).build());
         return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDons);
     }
 

+ 59 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupController.java

@@ -4,21 +4,26 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.date.DateTime;
+import cn.hutool.core.lang.Validator;
 import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONObject;
 import com.alibaba.excel.support.ExcelTypeEnum;
+import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.annotation.Log;
 import com.cyksj.common.annotation.NoSubmit;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.GoogleGenerator;
+import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GroupsRelationAlertMapper;
 import com.cyksj.mapper.GroupsRelationMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.model.entity.Account;
+import com.cyksj.model.entity.GroupsRelationAlert;
 import com.cyksj.model.entity.GroupsTrips;
 import com.cyksj.model.entity.GroupsTripsAccountReplaceRecord;
 import com.cyksj.model.excel.ExcelGroupRelationData;
@@ -39,6 +44,7 @@ import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
@@ -69,6 +75,8 @@ public class CmsGroupController {
 
     private final AccountCommonService accountCommonService;
 
+    private final GroupsRelationAlertMapper alertMapper;
+
     private final UserMapper userMapper;
 
     @GetMapping("/get")
@@ -331,4 +339,55 @@ public class CmsGroupController {
         re.putOpt("time", time);
         return GatewayResponse.SUCCESS.newBuilder().toResult(re.toString());
     }
+
+    /**
+     * 获取该规格下可用车位数
+     */
+    @GetMapping("/get/available/relation")
+    public Result<Integer> getAvailableRelation(Long goodsId, Long skuId) {
+        Integer available = groupService.getAvailableRelation(goodsId, skuId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(available);
+    }
+
+    /**
+     * 设置库存预警通知
+     */
+    @PutMapping("/set/relation/alert")
+    public Result<String> setGroupsRelationAlert(@RequestBody @Validated GroupsRelationAlert groupsRelationAlert) throws Exception {
+        if (groupsRelationAlert.getId() == null) {
+            try {
+                alertMapper.insert(groupsRelationAlert);
+            } catch (DuplicateKeyException e) {
+            }
+            return GatewayResponse.SUCCESS.newBuilder().toResult();
+        }
+        Long id = groupsRelationAlert.getId();
+        Assert.notNull(id, "预警id不存在");
+        GroupsRelationAlert dbAlert = alertMapper.selectById(id);
+        Assert.notNull(dbAlert, "预警不存在");
+        String phoneStr = groupsRelationAlert.getPhoneStr();
+        List<String> phoneList = Jsons.parseList(phoneStr, String.class);
+        phoneList.forEach(phone -> {
+            if (!Validator.isMobile(phone)) {
+                throw BusinessRuntimeException.getInstance("请输入正确的手机格式");
+            }
+        });
+        Integer dbNum = dbAlert.getNum();
+        Integer num = groupsRelationAlert.getNum();
+        if (dbNum != num) {
+            groupsRelationAlert.setIsReset(true);
+        }
+        alertMapper.updateById(groupsRelationAlert);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 库存预警通知
+     */
+    @GetMapping("/get/relation/alert")
+    public Result<GroupsRelationAlert> getGroupsRelationAlert(@RequestParam(required = true) Long skuId) {
+        GroupsRelationAlert groupsRelationAlert = alertMapper.selectOne(Wrappers.lambdaQuery(GroupsRelationAlert.class)
+                .eq(GroupsRelationAlert::getSkuId, skuId).last("limit 1"));
+        return GatewayResponse.SUCCESS.newBuilder().toResult(groupsRelationAlert);
+    }
 }