shinnosuke
2026-09-10 65b57875700bf42ebd17eafa01a265e5690ce271
talent-card-server/src/main/java/com/talentcard/server/business/admin/AdminBusinessService.java
@@ -328,8 +328,8 @@
                   s.external_mini_program_path as car_wash_external_mini_program_path,
                   s.external_web_url as car_wash_external_web_url,
                   (select o.account from merchant_operator o
                    where o.merchant_id = merchant.id and o.deleted = 0
                    order by case when o.role_code = 'owner' then 0 else 1 end, o.id asc limit 1) as login_account
                    where o.merchant_id = merchant.id
                    order by o.deleted asc, case when o.role_code = 'owner' then 0 else 1 end, o.id asc limit 1) as login_account
            from merchant
            left join transport_car_wash_service s on s.merchant_id = merchant.id and s.deleted = 0
            where merchant.deleted = 0 and merchant.id = ?
@@ -353,12 +353,24 @@
   @Transactional(readOnly = true)
   public Map<String, Object> merchantLoginAccountAvailable(String account) {
      return merchantLoginAccountAvailable(account, null);
   }
   @Transactional(readOnly = true)
   public Map<String, Object> merchantLoginAccountAvailable(String account, Long merchantId) {
      String normalizedAccount = account == null ? "" : account.trim();
      if (!normalizedAccount.matches("^[A-Za-z0-9]{1,32}$")) {
         return Map.of("available", false);
      }
      Long count = jdbcTemplate.queryForObject(
            "select count(*) from merchant_operator where account = ?", Long.class, normalizedAccount);
      Long count;
      if (merchantId == null) {
         count = jdbcTemplate.queryForObject(
               "select count(*) from merchant_operator where account = ?", Long.class, normalizedAccount);
      } else {
         count = jdbcTemplate.queryForObject(
               "select count(*) from merchant_operator where account = ? and merchant_id <> ?",
               Long.class, normalizedAccount, merchantId);
      }
      return Map.of("available", count == null || count == 0);
   }
@@ -551,8 +563,8 @@
         }
         int passwordUpdated = jdbcTemplate.update("""
               update merchant_operator
               set password_hash = ?
               where merchant_id = ? and role_code = 'owner' and deleted = 0
               set password_hash = ?, deleted = 0, status = 1
               where merchant_id = ? and role_code = 'owner'
               """, MerchantPasswordHasher.encode(request.loginPassword()), id);
         if (passwordUpdated == 0) {
            createMerchantOperator(id, request);
@@ -561,7 +573,7 @@
      if ((request.loginPassword() == null || request.loginPassword().isBlank()) && supportsMerchantAppLogin(request.merchantType())
            && (request.canLoginMerchantApp() == null || request.canLoginMerchantApp() == 1)
            && (request.loginAccount() != null && !request.loginAccount().isBlank())) {
         createMerchantOperator(id, request);
         ensureMerchantOperator(id, request);
      }
      return merchant(id);
   }
@@ -573,12 +585,28 @@
      if (request.loginPassword() == null || request.loginPassword().length() < 6 || request.loginPassword().length() > 64) {
         throw new BusinessException(ErrorCode.BAD_REQUEST, "商户登录密码长度须为6至64位");
      }
      Integer occupied = jdbcTemplate.queryForObject("select count(*) from merchant_operator where account = ? and deleted = 0", Integer.class, request.loginAccount().trim());
      Integer occupied = jdbcTemplate.queryForObject("select count(*) from merchant_operator where account = ?", Integer.class, request.loginAccount().trim());
      if (occupied != null && occupied > 0) throw new BusinessException(ErrorCode.CONFLICT, "登录账号已存在");
      jdbcTemplate.update("insert into merchant_operator(merchant_id, account, password_hash, display_name, role_code, status) values (?, ?, ?, ?, 'owner', 1)",
            merchantId, request.loginAccount().trim(), MerchantPasswordHasher.encode(request.loginPassword()), request.merchantName().trim());
   }
   private void ensureMerchantOperator(Long merchantId, MerchantUpdateRequest request) {
      String account = request.loginAccount().trim();
      Integer sameMerchant = jdbcTemplate.queryForObject(
            "select count(*) from merchant_operator where merchant_id = ? and account = ?",
            Integer.class, merchantId, account);
      if (sameMerchant != null && sameMerchant > 0) {
         jdbcTemplate.update("""
               update merchant_operator
               set deleted = 0, status = 1, display_name = ?
               where merchant_id = ? and account = ?
               """, request.merchantName().trim(), merchantId, account);
         return;
      }
      createMerchantOperator(merchantId, request);
   }
   private void ensureParkingBenefit(Long merchantId, String merchantType) {
      if (!"parking".equals(merchantType)) return;
      jdbcTemplate.update("""