yeg
2026-09-28 85bfb9351803d97a33329d507f30a2f78bf1fc75
talent-card-server/src/main/java/com/talentcard/server/business/admin/AdminBusinessService.java
@@ -1056,16 +1056,17 @@
      ensureMerchantExists(request.merchantId());
      validateProductConfiguration(request.merchantId(), request.salePrice(), request.productImages());
      validateProductRights(request.merchantId(), request.rightsConfig());
      Long productId = resolveProductId(id);
      BigDecimal subsidyAmount = valueOrZero(request.subsidyAmount());
      int updated = jdbcTemplate.update("""
            update merchant_product
            set merchant_id = ?, product_type = ?, product_name = ?, subtitle = ?, cover_url = ?,
                original_price = ?, sale_price = ?, subsidy_amount = ?, is_government_subsidy = ?,
                stock = ?, detail_text = ?, benefit_desc = ?, purchase_notice = ?, valid_start_time = ?,
                valid_end_time = ?, product_images = ?, rights_config = ?, status = 0, sort_no = ?,
                audit_status = 1, audit_remark = null, audit_time = null, submit_time = now()
            where deleted = 0 and id = ?
            """,
         int updated = jdbcTemplate.update("""
               update merchant_product
               set merchant_id = ?, product_type = ?, product_name = ?, subtitle = ?, cover_url = ?,
                   original_price = ?, sale_price = ?, subsidy_amount = ?, is_government_subsidy = ?,
                   stock = ?, detail_text = ?, benefit_desc = ?, purchase_notice = ?, valid_start_time = ?,
                   valid_end_time = ?, product_images = ?, rights_config = ?, status = 0, sort_no = ?,
                   audit_status = 1, audit_remark = null, audit_time = null, submit_time = now()
               where deleted = 0 and id = ?
               """,
            request.merchantId(),
            request.productType(),
            request.productName(),
@@ -1084,45 +1085,48 @@
            toJson(request.productImages()),
            toJson(request.rightsConfig()),
            request.sortNo() == null ? 0 : request.sortNo(),
            id);
            productId);
      ensureUpdated(updated);
      appendProductAuditRecord(id);
      return product(id);
      appendProductAuditRecord(productId);
      return product(productId);
   }
   @Transactional
   public Map<String, Object> updateProductStatus(Long id, Byte status) {
      Number auditStatus = (Number) product(id).get("auditStatus");
      Long productId = resolveProductId(id);
      Number auditStatus = (Number) product(productId).get("auditStatus");
      if (auditStatus == null || auditStatus.intValue() != 2) {
         throw new BusinessException(ErrorCode.BAD_REQUEST, "Only approved products can be listed or unlisted");
         throw new BusinessException(ErrorCode.BAD_REQUEST, "只有审核通过的团单才能上架或下架");
      }
      int updated = jdbcTemplate.update("update merchant_product set status = ? where deleted = 0 and id = ?", status, id);
      int updated = jdbcTemplate.update("update merchant_product set status = ? where deleted = 0 and id = ?", status, productId);
      ensureUpdated(updated);
      return product(id);
      return product(productId);
   }
   @Transactional
   public Map<String, Object> deleteProduct(Long id) {
      Map<String, Object> existing = product(id);
      int updated = jdbcTemplate.update("update merchant_product set deleted = 1 where deleted = 0 and id = ?", id);
      Long productId = resolveProductId(id);
      Map<String, Object> existing = product(productId);
      int updated = jdbcTemplate.update("update merchant_product set deleted = 1 where deleted = 0 and id = ?", productId);
      ensureUpdated(updated);
      return existing;
   }
   @Transactional
   public Map<String, Object> auditProduct(Long id, ProductAuditRequest request) {
      Long productId = resolveProductId(id);
      List<Map<String, Object>> pendingRecords = DatabaseRows.normalize(jdbcTemplate.queryForList("""
            select id from merchant_product_audit_record
            where product_id = ? and deleted = 0 and audit_status = 1
            order by id desc limit 1
            """, id));
            """, productId));
      if (!pendingRecords.isEmpty()) {
         return auditProductAuditRecord(Long.valueOf(String.valueOf(pendingRecords.get(0).get("id"))), request);
      }
      if (request.auditStatus() != 2 && request.auditStatus() != 3) {
         throw new BusinessException(ErrorCode.BAD_REQUEST, "Invalid audit status");
      }
      Number currentAuditStatus = (Number) product(id).get("auditStatus");
      Number currentAuditStatus = (Number) product(productId).get("auditStatus");
      if (currentAuditStatus == null || currentAuditStatus.intValue() != 1) {
         throw new BusinessException(ErrorCode.BAD_REQUEST, "Product is not pending audit");
      }
@@ -1130,9 +1134,9 @@
            update merchant_product
            set audit_status = ?, audit_remark = ?, audit_time = now(), status = ?
            where deleted = 0 and id = ?
            """, request.auditStatus(), request.auditRemark(), request.auditStatus() == 2 ? 1 : 0, id);
            """, request.auditStatus(), request.auditRemark(), request.auditStatus() == 2 ? 1 : 0, productId);
      ensureUpdated(updated);
      return product(id);
      return product(productId);
   }
   @Transactional
@@ -1406,6 +1410,35 @@
      }
   }
   /**
    * 团单在后台有两个 id 口径:商家编辑页的团单列表给的是商品 id,团单审核列表给的是审核记录 id。
    * 两个都认——否则拿另一口径的 id 去改团单,就只会在 update 影响 0 行之后抛出英文的
    * {@code Data not found},现场完全看不出是"id 口径不一致"。
    */
   private Long resolveProductId(Long id) {
      if (id == null) {
         throw new BusinessException(ErrorCode.BAD_REQUEST, "团单参数不能为空");
      }
      List<Long> direct = jdbcTemplate.queryForList(
            "select id from merchant_product where deleted = 0 and id = ?",
            Long.class,
            id);
      if (!direct.isEmpty()) {
         return direct.get(0);
      }
      List<Long> byAuditRecord = jdbcTemplate.queryForList("""
            select p.id
            from merchant_product_audit_record r
            join merchant_product p on p.id = r.product_id and p.deleted = 0
            where r.deleted = 0 and r.id = ?
            limit 1
            """, Long.class, id);
      if (!byAuditRecord.isEmpty()) {
         return byAuditRecord.get(0);
      }
      throw new BusinessException(ErrorCode.NOT_FOUND, "团单不存在或已被删除,请刷新列表后重试");
   }
   private void ensureMerchantExists(Long merchantId) {
      Long count = jdbcTemplate.queryForObject(
            "select count(*) from merchant where deleted = 0 and id = ?",