package com.talentcard.server.business.application; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; import com.talentcard.server.business.DatabaseRows; import com.talentcard.server.business.PageResult; import com.talentcard.server.common.BusinessException; import com.talentcard.server.common.ErrorCode; import com.talentcard.server.request.ParkingPlateStatusUpdateRequest; import com.talentcard.server.service.ParkingPlateSubmissionAdminService; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class ServiceApplicationService { private final JdbcTemplate jdbcTemplate; private final ParkingPlateSubmissionAdminService parkingPlateSubmissionAdminService; public ServiceApplicationService( JdbcTemplate jdbcTemplate, ParkingPlateSubmissionAdminService parkingPlateSubmissionAdminService ) { this.jdbcTemplate = jdbcTemplate; this.parkingPlateSubmissionAdminService = parkingPlateSubmissionAdminService; } @Transactional(readOnly = true) public PageResult> page( String applicationType, String talentKeyword, String merchantName, String hospitalName, String parkingLot, String cardLevel, String status, String submissionType, String subsidy, String submittedStart, String submittedEnd, int page, int size ) { int safePage = Math.max(page, 1); int safeSize = Math.min(Math.max(size, 1), 100); if (isParkingPlateApplication(applicationType)) { return parkingPlateSubmissionAdminService.page( null, null, talentKeyword, firstNonBlank(merchantName, parkingLot, hospitalName), cardLevel, status, submissionType, submittedStart, submittedEnd, safePage, safeSize ); } StringBuilder where = new StringBuilder(" where deleted = 0"); List args = new ArrayList<>(); if (applicationType != null && !applicationType.isBlank()) { where.append(" and application_type = ?"); args.add(applicationType); } if (talentKeyword != null && !talentKeyword.isBlank()) { where.append(""" and (talent_name like ? or talent_mobile like ? or card_no like ? or application_no like ? or applicant_name like ? or applicant_mobile like ? or plate_no like ? or spouse_name like ? or spouse_mobile like ? or alipay_mobile like ?) """); String like = "%" + talentKeyword.trim() + "%"; for (int i = 0; i < 10; i++) { args.add(like); } } if (merchantName != null && !merchantName.isBlank()) { where.append(" and merchant_name like ?"); args.add("%" + merchantName.trim() + "%"); } if (hospitalName != null && !hospitalName.isBlank()) { where.append(" and hospital_name like ?"); args.add("%" + hospitalName.trim() + "%"); } if (parkingLot != null && !parkingLot.isBlank()) { where.append(" and parking_lot like ?"); args.add("%" + parkingLot.trim() + "%"); } if (cardLevel != null && !cardLevel.isBlank()) { where.append(" and talent_level = ?"); args.add(cardLevel); } if (status != null && !status.isBlank()) { where.append(" and status = ?"); args.add(status); } if (submissionType != null && !submissionType.isBlank()) { where.append(" and submission_type = ?"); args.add(submissionType); } if (subsidy != null && !subsidy.isBlank()) { where.append(" and subsidy = ?"); args.add(subsidy); } if (submittedStart != null && !submittedStart.isBlank()) { where.append(" and date(submitted_at) >= ?"); args.add(submittedStart); } if (submittedEnd != null && !submittedEnd.isBlank()) { where.append(" and date(submitted_at) <= ?"); args.add(submittedEnd); } List pageArgs = new ArrayList<>(args); pageArgs.add(safeSize); pageArgs.add((safePage - 1) * safeSize); List> records = query(""" select * from service_application """ + where + " order by submitted_at desc, id desc limit ? offset ?", pageArgs.toArray()); Long total = jdbcTemplate.queryForObject(""" select count(*) from service_application """ + where, Long.class, args.toArray()); return new PageResult<>(records, safePage, safeSize, total == null ? 0 : total); } @Transactional(readOnly = true) public Map detail(Long id) { return detail(id, null); } @Transactional(readOnly = true) public Map detail(Long id, String applicationType) { if (isParkingPlateApplication(applicationType)) { return parkingPlateSubmissionAdminService.detail(id); } List> rows = query(""" select * from service_application where deleted = 0 and id = ? """, id); if (rows.isEmpty()) { throw new BusinessException(ErrorCode.NOT_FOUND, "申请单不存在"); } return rows.get(0); } @Transactional public Map updateStatus(Long id, ServiceApplicationStatusRequest request) { return updateStatus(id, request, null); } @Transactional public Map updateStatus(Long id, ServiceApplicationStatusRequest request, String applicationType) { if (isParkingPlateApplication(applicationType)) { return parkingPlateSubmissionAdminService.updateStatus( id, new ParkingPlateStatusUpdateRequest(request.status(), request.rejectReason()), null ); } Map current = detail(id); String status = request.status(); if (!List.of("待处理", "已处理", "已驳回", "已取消").contains(status)) { throw new BusinessException(ErrorCode.BAD_REQUEST, "申请单状态不正确"); } String handlerName = request.handlerName() == null || request.handlerName().isBlank() ? "管理员" : request.handlerName(); Object handledAt = "待处理".equals(status) ? null : java.time.LocalDateTime.now(); int updated = jdbcTemplate.update(""" update service_application set status = ?, handled_at = ?, handler_name = ?, reject_reason = ? where deleted = 0 and id = ? """, status, handledAt, "待处理".equals(status) ? null : handlerName, request.rejectReason(), current.get("id")); if (updated == 0) { throw new BusinessException(ErrorCode.NOT_FOUND, "申请单不存在"); } return detail(id); } private boolean isParkingPlateApplication(String applicationType) { String value = applicationType == null ? "" : applicationType.trim().toUpperCase(Locale.ROOT).replace("-", "_"); return switch (value) { case "PARKING_PLATE", "PARKING_PLATE_REGISTRATION", "PARKING_PLATE_SUBMISSION", "停车车牌", "停车车牌登记" -> true; default -> false; }; } private String firstNonBlank(String... values) { for (String value : values) { if (value != null && !value.isBlank()) { return value.trim(); } } return null; } private List> query(String sql, Object... args) { return DatabaseRows.normalize(jdbcTemplate.queryForList(sql, args)); } }