shinnosuke
2026-08-31 dfdaa3e75a5d2e8779c8463673484eeea1f1e813
talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantWorkService.java
@@ -39,6 +39,9 @@
   @Transactional(readOnly = true)
   public PageResult<Map<String, Object>> orders(Long merchantId, Long storeId, int page, int size, MerchantOrderQuery query) {
      if (query != null && "stay".equals(normalize(query.category()))) {
         return freeStayOrders(merchantId, storeId, page, size, query);
      }
      int safePage = Math.max(page, 1);
      int safeSize = Math.min(Math.max(size, 1), 100);
      OrderFilters filters = filters(query);
@@ -92,11 +95,67 @@
            where o.deleted = 0 and o.order_no = ? and o.merchant_id = ? and (o.store_id is null or o.store_id = ?)
            """, orderNo, merchantId, storeId);
      if (rows.isEmpty()) {
         throw new BusinessException(ErrorCode.NOT_FOUND, "订单不存在");
         List<Map<String, Object>> freeStayRows = query("""
               select r.id, r.verify_no as order_no, r.talent_id, tu.name as talent_name, tu.mobile as talent_mobile, tu.gender,
                      r.card_id, tc.card_no, tc.card_level, r.merchant_id, m.merchant_name, m.merchant_rights_config,
                      '免费入住' as benefit_name, '1天免费入住' as product_name_snapshot,
                      'FREE_STAY' as order_type, 0 as order_amount, 0 as base_pay_amount, 0 as coupon_amount,
                      r.subsidy_amount, 0 as pay_amount, 1 as order_status, 1 as verify_status,
                      r.verify_time as created_at, r.verify_time, r.status as verify_record_status
               from verify_record r
               left join talent_user tu on tu.id = r.talent_id
               left join talent_card tc on tc.id = r.card_id
               left join merchant m on m.id = r.merchant_id
               where r.verify_no = ? and r.verify_type = 'HOTEL_FREE' and r.status = 1
                 and r.merchant_id = ? and (r.store_id is null or r.store_id = ?)
               limit 1
               """, orderNo, merchantId, storeId);
         if (freeStayRows.isEmpty()) throw new BusinessException(ErrorCode.NOT_FOUND, "订单不存在");
         return enrichOrder(freeStayRows.get(0));
      }
      return enrichOrder(rows.get(0));
   }
   private PageResult<Map<String, Object>> freeStayOrders(Long merchantId, Long storeId, int page, int size, MerchantOrderQuery query) {
      int safePage = Math.max(page, 1);
      int safeSize = Math.min(Math.max(size, 1), 100);
      StringBuilder condition = new StringBuilder(" where r.verify_type = 'HOTEL_FREE' and r.status = 1 and r.merchant_id = ? and (r.store_id is null or r.store_id = ?)");
      List<Object> arguments = new ArrayList<>();
      arguments.add(merchantId);
      arguments.add(storeId);
      LocalDate startDate = date(query.startDate(), "开始日期");
      LocalDate endDate = date(query.endDate(), "结束日期");
      if (startDate != null && endDate != null && startDate.isAfter(endDate)) {
         throw new BusinessException(ErrorCode.BAD_REQUEST, "开始日期不能晚于结束日期");
      }
      if (startDate != null) {
         condition.append(" and r.verify_time >= ?");
         arguments.add(Timestamp.valueOf(startDate.atStartOfDay()));
      }
      if (endDate != null) {
         condition.append(" and r.verify_time < ?");
         arguments.add(Timestamp.valueOf(endDate.plusDays(1).atStartOfDay()));
      }
      String select = """
            select r.id, r.verify_no as order_no, r.talent_id, tu.name as talent_name, tu.mobile as talent_mobile, tu.gender,
                   r.card_id, tc.card_level, r.merchant_id, m.merchant_name,
                   '免费入住' as benefit_name, '1天免费入住' as product_name_snapshot,
                   'FREE_STAY' as order_type, 0 as order_amount, 0 as base_pay_amount, 0 as coupon_amount,
                   r.subsidy_amount, 0 as pay_amount, 1 as order_status, 1 as verify_status,
                   r.verify_time as created_at, r.verify_time
            from verify_record r
            left join talent_user tu on tu.id = r.talent_id
            left join talent_card tc on tc.id = r.card_id
            left join merchant m on m.id = r.merchant_id
            """ + condition + " order by r.verify_time desc, r.id desc limit ? offset ?";
      List<Object> recordArguments = new ArrayList<>(arguments);
      recordArguments.add(safeSize);
      recordArguments.add((safePage - 1) * safeSize);
      List<Map<String, Object>> records = query(select, recordArguments.toArray()).stream().map(this::toListItem).toList();
      Long total = jdbcTemplate.queryForObject("select count(*) from verify_record r" + condition, Long.class, arguments.toArray());
      return new PageResult<>(records, safePage, safeSize, total == null ? 0 : total);
   }
   @Transactional
   public Map<String, Object> verify(String orderNo, MerchantPrincipal principal, VerifyRequest request, String idempotencyKey) {
      if (idempotencyKey == null || idempotencyKey.isBlank()) {