package com.talentcard.server.business.admin; import java.util.Map; import com.talentcard.server.business.PageResult; import com.talentcard.server.common.ApiResponse; import com.talentcard.server.request.TicketPackageCodeImportRequest; import com.talentcard.server.request.TicketPackageCodeStatusRequest; import com.talentcard.server.request.TicketPackageSaveRequest; import com.talentcard.server.request.TicketPackageStatusRequest; import com.talentcard.server.service.TicketPackageAdminService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; @Tag(name = "后台-票包码池", description = "后台维护票包、兑换码码池、库存、发放记录和兑换码状态") @RestController @RequestMapping("/api/admin/ticket-packages") public class TicketPackageAdminController { private final TicketPackageAdminService service; public TicketPackageAdminController(TicketPackageAdminService service) { this.service = service; } @Operation(summary = "查询票包列表", description = "分页查询票包配置和兑换码库存汇总") @GetMapping public ApiResponse>> packages( @Parameter(description = "指定兑换商家ID") @RequestParam(required = false) Long merchantId, @Parameter(description = "状态:1启用,0停用") @RequestParam(required = false) Integer status, @Parameter(description = "票包名称或编号关键词") @RequestParam(required = false) String keyword, @Parameter(description = "页码") @RequestParam(defaultValue = "1") int page, @Parameter(description = "每页条数") @RequestParam(defaultValue = "10") int size ) { return ApiResponse.success(service.packages(merchantId, status, keyword, page, size)); } @Operation(summary = "查询票包详情", description = "查看票包基础配置和码池库存汇总") @GetMapping("/{packageId}") public ApiResponse> packageDetail(@PathVariable Long packageId) { return ApiResponse.success(service.packageDetail(packageId)); } @Operation(summary = "查询票包库存", description = "查看指定票包兑换码总量、可发放、锁定、已发放、已使用和作废数量") @GetMapping("/{packageId}/stock") public ApiResponse> stock(@Parameter(description = "票包ID") @PathVariable Long packageId) { return ApiResponse.success(service.stock(packageId)); } @Operation(summary = "新增票包", description = "后台录入票包,不涉及具体电影票场次") @PostMapping public ApiResponse> createPackage(@Valid @RequestBody TicketPackageSaveRequest request) { return ApiResponse.success(service.createPackage(request)); } @Operation(summary = "修改票包", description = "修改票包名称、适用卡等级、有效期、商家APP信息等") @PutMapping("/{packageId}") public ApiResponse> updatePackage( @PathVariable Long packageId, @Valid @RequestBody TicketPackageSaveRequest request ) { return ApiResponse.success(service.updatePackage(packageId, request)); } @Operation(summary = "修改票包状态", description = "启用或停用票包") @PatchMapping("/{packageId}/status") public ApiResponse> updatePackageStatus( @PathVariable Long packageId, @Valid @RequestBody TicketPackageStatusRequest request ) { return ApiResponse.success(service.updatePackageStatus(packageId, request.status())); } @Operation(summary = "导入票包兑换码", description = "批量导入兑换码到指定票包码池,重复兑换码自动跳过") @PostMapping("/{packageId}/codes/import") public ApiResponse> importCodes( @PathVariable Long packageId, @Valid @RequestBody TicketPackageCodeImportRequest request ) { return ApiResponse.success(service.importCodes(packageId, request)); } @Operation(summary = "导入票包兑换码Excel", description = "上传Excel文件导入兑换码,读取第一个Sheet第一列,首行可为兑换码标题,重复兑换码自动跳过") @PostMapping(value = "/{packageId}/codes/import-file", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ApiResponse> importCodeFile( @Parameter(description = "票包ID") @PathVariable Long packageId, @Parameter(description = "兑换码Excel文件") @RequestParam("file") MultipartFile file, @Parameter(description = "导入批次号;不传后端自动生成") @RequestParam(required = false) String batchNo, @Parameter(description = "备注") @RequestParam(required = false) String remark ) { return ApiResponse.success(service.importCodeFile(packageId, file, batchNo, remark)); } @Operation(summary = "查询票包兑换码列表", description = "分页查询码池兑换码,支持状态、批次号和关键词筛选") @GetMapping("/codes") public ApiResponse>> codes( @Parameter(description = "票包ID") @RequestParam(required = false) Long packageId, @Parameter(description = "兑换码状态") @RequestParam(required = false) String status, @Parameter(description = "导入批次号") @RequestParam(required = false) String batchNo, @Parameter(description = "兑换码或票包名称关键词") @RequestParam(required = false) String keyword, @Parameter(description = "页码") @RequestParam(defaultValue = "1") int page, @Parameter(description = "每页条数") @RequestParam(defaultValue = "10") int size ) { return ApiResponse.success(service.codes(packageId, status, batchNo, keyword, page, size)); } @Operation(summary = "修改兑换码状态", description = "后台作废兑换码,或将已发放兑换码标记为已使用") @PatchMapping("/codes/{codeId}/status") public ApiResponse> updateCodeStatus( @PathVariable Long codeId, @Valid @RequestBody TicketPackageCodeStatusRequest request ) { return ApiResponse.success(service.updateCodeStatus(codeId, request)); } @Operation(summary = "查询票包发放记录", description = "分页查询用户领取兑换码记录") @GetMapping("/claims") public ApiResponse>> claims( @Parameter(description = "票包ID") @RequestParam(required = false) Long packageId, @Parameter(description = "持卡人ID") @RequestParam(required = false) Long talentId, @Parameter(description = "发放状态") @RequestParam(required = false) String status, @Parameter(description = "领取编号、兑换码、姓名或手机号关键词") @RequestParam(required = false) String keyword, @Parameter(description = "页码") @RequestParam(defaultValue = "1") int page, @Parameter(description = "每页条数") @RequestParam(defaultValue = "10") int size ) { return ApiResponse.success(service.claims(packageId, talentId, status, keyword, page, size)); } }