|
|
@@ -0,0 +1,104 @@
|
|
|
+package com.etotem.cfc.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.etotem.cfc.entity.RecommendationRule;
|
|
|
+import com.etotem.cfc.mapper.RecommendationRuleMapper;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import com.etotem.cfc.entity.ProductOrder;
|
|
|
+import com.etotem.cfc.mapper.ProductOrderMapper;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class RecommendationRuleService extends ServiceImpl<RecommendationRuleMapper, RecommendationRule> {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private RecommendationRuleMapper recommendationRuleMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ProductOrderMapper productOrderMapper;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据场景码加载启用的规则,按 priority 降序
|
|
|
+ */
|
|
|
+ public List<RecommendationRule> loadRulesByScene(String sceneCode) {
|
|
|
+ List<RecommendationRule> allEnabled = this.list(new LambdaQueryWrapper<RecommendationRule>()
|
|
|
+ .eq(RecommendationRule::getEnabled, 1));
|
|
|
+ return allEnabled.stream()
|
|
|
+ .filter(rule -> rule.getSceneCodes() != null && rule.getSceneCodes().contains(sceneCode))
|
|
|
+ .sorted(Comparator.comparing(RecommendationRule::getPriority).reversed())
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询已购商品ID(回溯窗口内)
|
|
|
+ */
|
|
|
+ public Set<Long> getPurchasedProductIds(Long familyId, Long memberId, int daysAgo) {
|
|
|
+ Set<Long> ids = new HashSet<>();
|
|
|
+ if (familyId == null) return ids;
|
|
|
+
|
|
|
+ Calendar cal = Calendar.getInstance();
|
|
|
+ cal.add(Calendar.DAY_OF_YEAR, -daysAgo);
|
|
|
+ Date cutoff = cal.getTime();
|
|
|
+
|
|
|
+ // 查 family 成员订单
|
|
|
+ List<ProductOrder> orders = productOrderMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<ProductOrder>()
|
|
|
+ .eq(ProductOrder::getFamilyId, familyId)
|
|
|
+ .eq(ProductOrder::getStatus, "已支付")
|
|
|
+ .gt(ProductOrder::getPaidAt, cutoff)
|
|
|
+ );
|
|
|
+ for (ProductOrder order : orders) {
|
|
|
+ if (order.getProductId() != null) {
|
|
|
+ ids.add(order.getProductId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 若未查到家庭订单,且 memberId 不为空,查个人订单
|
|
|
+ if (ids.isEmpty() && memberId != null) {
|
|
|
+ List<ProductOrder> orders2 = productOrderMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<ProductOrder>()
|
|
|
+ .eq(ProductOrder::getBuyerId, memberId)
|
|
|
+ .eq(ProductOrder::getStatus, "已支付")
|
|
|
+ .gt(ProductOrder::getPaidAt, cutoff)
|
|
|
+ );
|
|
|
+ for (ProductOrder order : orders2) {
|
|
|
+ if (order.getProductId() != null) {
|
|
|
+ ids.add(order.getProductId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ids;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询当前用户已购商品(用于 individual scope)
|
|
|
+ */
|
|
|
+ public Set<Long> getMyPurchasedProductIds(Long userId, int daysAgo) {
|
|
|
+ Set<Long> ids = new HashSet<>();
|
|
|
+ if (userId == null) return ids;
|
|
|
+
|
|
|
+ Calendar cal = Calendar.getInstance();
|
|
|
+ cal.add(Calendar.DAY_OF_YEAR, -daysAgo);
|
|
|
+ Date cutoff = cal.getTime();
|
|
|
+
|
|
|
+ List<ProductOrder> orders = productOrderMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<ProductOrder>()
|
|
|
+ .eq(ProductOrder::getBuyerId, userId)
|
|
|
+ .eq(ProductOrder::getStatus, "已支付")
|
|
|
+ .gt(ProductOrder::getPaidAt, cutoff)
|
|
|
+ );
|
|
|
+ for (ProductOrder order : orders) {
|
|
|
+ if (order.getProductId() != null) {
|
|
|
+ ids.add(order.getProductId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ids;
|
|
|
+ }
|
|
|
+}
|