CompanyController.java 13.5 KB
package com.aigeo.company.controller;

import com.aigeo.company.entity.Company;
import com.aigeo.company.service.CompanyService;
import com.aigeo.common.result.Result;
import com.aigeo.common.result.ResultCode;
import com.aigeo.common.exception.BusinessException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

/**
 * 公司管理控制器
 *
 * @author AIGEO Team
 * @since 1.0.0
 */
@Tag(name = "公司管理", description = "公司信息管理接口,支持公司的创建、查询、更新和删除操作")
@RestController
@RequestMapping("/api/companies")
@RequiredArgsConstructor
@Slf4j
public class CompanyController {

    private final CompanyService companyService;

    @Operation(
        summary = "分页查询公司列表",
        description = "支持按公司名称、状态等条件分页查询公司列表,默认按创建时间倒序排列"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "查询成功"),
        @ApiResponse(responseCode = "400", description = "请求参数错误"),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/list")
    public Result<Page<Company>> listCompanies(
        @Parameter(description = "页码,从0开始", example = "0")
        @RequestParam(defaultValue = "0") @Min(0) int page,

        @Parameter(description = "页大小,默认10条", example = "10")
        @RequestParam(defaultValue = "10") @Min(1) @Max(100) int size,

        @Parameter(description = "公司名称(模糊查询)", example = "AIGEO")
        @RequestParam(required = false) String name,

        @Parameter(description = "公司状态(ACTIVE/INACTIVE/SUSPENDED)")
        @RequestParam(required = false) String status,

        @Parameter(description = "套餐类型(TRIAL/BASIC/PREMIUM/ENTERPRISE)")
        @RequestParam(required = false) String planType
    ) {
        try {
            Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt"));
            Page<Company> companies = companyService.searchCompanies(name, status, planType, pageable);
            return Result.success("查询成功", companies);
        } catch (Exception e) {
            log.error("分页查询公司列表失败", e);
            return Result.error("查询失败");
        }
    }

    @Operation(
        summary = "获取所有公司(简化版)",
        description = "获取所有公司的基本信息,用于下拉选择等场景"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "查询成功"),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping
    public Result<List<Company>> getAllCompanies() {
        try {
            List<Company> companies = companyService.getAllCompanies();
            return Result.success("查询成功", companies);
        } catch (Exception e) {
            log.error("获取所有公司失败", e);
            return Result.error("查询失败");
        }
    }

    @Operation(
        summary = "根据ID查询公司详情",
        description = "通过公司ID获取公司的详细信息"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "查询成功"),
        @ApiResponse(responseCode = "404", description = "公司不存在"),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/{id}")
    public Result<Company> getCompanyById(
        @Parameter(description = "公司ID", required = true, example = "1")
        @PathVariable @NotNull Integer id
    ) {
        try {
            Company company = companyService.getCompanyById(id);
            return Result.success("查询成功", company);
        } catch (BusinessException e) {
            log.warn("根据ID查询公司失败, id: {}, error: {}", id, e.getMessage());
            return Result.error(e.getResultCode(), e.getMessage());
        } catch (Exception e) {
            log.error("根据ID查询公司详情失败, id: {}", id, e);
            return Result.error("查询失败");
        }
    }

    @Operation(
        summary = "根据子域名查询公司",
        description = "通过公司子域名获取公司信息,用于多租户识别"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "查询成功"),
        @ApiResponse(responseCode = "404", description = "公司不存在"),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/subdomain/{subdomain}")
    public Result<Company> getCompanyBySubdomain(
        @Parameter(description = "公司子域名", required = true, example = "aigeo")
        @PathVariable @NotNull String subdomain
    ) {
        try {
            Optional<Company> companyOpt = companyService.getCompanyBySubdomain(subdomain);
            if (companyOpt.isPresent()) {
                return Result.success("查询成功", companyOpt.get());
            } else {
                return Result.error(ResultCode.COMPANY_NOT_FOUND);
            }
        } catch (Exception e) {
            log.error("根据子域名查询公司失败, subdomain: {}", subdomain, e);
            return Result.error("查询失败");
        }
    }

    @Operation(
        summary = "查询活跃公司列表",
        description = "获取所有状态为活跃的公司列表"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "查询成功"),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/active")
    public Result<List<Company>> getActiveCompanies() {
        try {
            List<Company> companies = companyService.getActiveCompanies();
            return Result.success("查询成功", companies);
        } catch (Exception e) {
            log.error("查询活跃公司列表失败", e);
            return Result.error("查询失败");
        }
    }

    @Operation(
        summary = "创建新公司",
        description = "创建一个新的公司记录,包含基本信息和配置"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "创建成功"),
        @ApiResponse(responseCode = "400", description = "请求参数错误"),
        @ApiResponse(responseCode = "409", description = "公司子域名已存在"),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PostMapping
    public Result<Company> createCompany(
        @Parameter(description = "公司信息", required = true)
        @Valid @RequestBody Company company
    ) {
        try {
            // 检查子域名是否已存在
            if (companyService.existsBySubdomain(company.getSubdomain())) {
                return Result.error(ResultCode.DATA_DUPLICATE, "子域名已存在");
            }

            Company savedCompany = companyService.saveCompany(company);
            log.info("成功创建公司: id={}, name={}", savedCompany.getId(), savedCompany.getName());
            return Result.success("创建成功", savedCompany);
        } catch (Exception e) {
            log.error("创建公司失败", e);
            return Result.error("创建失败");
        }
    }

    @Operation(
        summary = "更新公司信息",
        description = "根据ID更新公司的详细信息"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "更新成功"),
        @ApiResponse(responseCode = "400", description = "请求参数错误"),
        @ApiResponse(responseCode = "404", description = "公司不存在"),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PutMapping("/{id}")
    public Result<Company> updateCompany(
        @Parameter(description = "公司ID", required = true, example = "1")
        @PathVariable @NotNull Integer id,

        @Parameter(description = "更新的公司信息", required = true)
        @Valid @RequestBody Company companyDetails
    ) {
        try {
            Company existingCompany = companyService.getCompanyById(id);

            // 更新字段
            existingCompany.setName(companyDetails.getName());
            existingCompany.setSubdomain(companyDetails.getSubdomain());
            existingCompany.setPlanType(companyDetails.getPlanType());
            existingCompany.setMaxUsers(companyDetails.getMaxUsers());
            existingCompany.setMaxArticlesPerMonth(companyDetails.getMaxArticlesPerMonth());
            existingCompany.setStatus(companyDetails.getStatus());
            existingCompany.setTrialExpiryDate(companyDetails.getTrialExpiryDate());
            existingCompany.setDefaultSettings(companyDetails.getDefaultSettings());

            Company savedCompany = companyService.saveCompany(existingCompany);
            log.info("成功更新公司: id={}, name={}", savedCompany.getId(), savedCompany.getName());
            return Result.success("更新成功", savedCompany);
        } catch (BusinessException e) {
            log.warn("更新公司失败, id: {}, error: {}", id, e.getMessage());
            return Result.error(e.getResultCode(), e.getMessage());
        } catch (Exception e) {
            log.error("更新公司失败, id: {}", id, e);
            return Result.error("更新失败");
        }
    }

    @Operation(
        summary = "批量更新公司状态",
        description = "批量更新多个公司的状态"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "更新成功"),
        @ApiResponse(responseCode = "400", description = "请求参数错误"),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PutMapping("/batch-status")
    public Result<String> batchUpdateStatus(
        @Parameter(description = "公司ID列表", required = true)
        @RequestParam @NotNull List<Integer> ids,

        @Parameter(description = "新状态", required = true)
        @RequestParam @NotNull String status
    ) {
        try {
            int updatedCount = companyService.batchUpdateStatus(ids, status);
            log.info("批量更新公司状态成功,更新数量: {}", updatedCount);
            return Result.success(String.format("成功更新 %d 个公司状态", updatedCount));
        } catch (Exception e) {
            log.error("批量更新公司状态失败", e);
            return Result.error("批量更新失败");
        }
    }

    @Operation(
        summary = "删除公司",
        description = "根据ID删除公司记录(软删除)"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "删除成功"),
        @ApiResponse(responseCode = "404", description = "公司不存在"),
        @ApiResponse(responseCode = "409", description = "公司有关联用户,无法删除"),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @DeleteMapping("/{id}")
    public Result<String> deleteCompany(
        @Parameter(description = "公司ID", required = true, example = "1")
        @PathVariable @NotNull Integer id
    ) {
        try {
            if (!companyService.existsById(id)) {
                return Result.error(ResultCode.COMPANY_NOT_FOUND);
            }

            // 检查是否有关联用户
            if (companyService.hasAssociatedUsers(id)) {
                return Result.error(ResultCode.CONFLICT, "公司有关联用户,无法删除");
            }

            companyService.deleteCompany(id);
            log.info("成功删除公司, id: {}", id);
            return Result.success("删除成功");
        } catch (Exception e) {
            log.error("删除公司失败, id: {}", id, e);
            return Result.error("删除失败");
        }
    }

    @Operation(
        summary = "搜索公司",
        description = "根据关键词搜索公司名称或子域名"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "搜索成功"),
        @ApiResponse(responseCode = "400", description = "请求参数错误"),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/search")
    public Result<List<Company>> searchCompanies(
        @Parameter(description = "搜索关键词", required = true, example = "AIGEO")
        @RequestParam @NotNull String keyword,

        @Parameter(description = "最大返回数量", example = "20")
        @RequestParam(defaultValue = "20") @Min(1) @Max(100) int limit
    ) {
        try {
            List<Company> companies = companyService.searchByKeyword(keyword, limit);
            return Result.success("搜索成功", companies);
        } catch (Exception e) {
            log.error("搜索公司失败, keyword: {}", keyword, e);
            return Result.error("搜索失败");
        }
    }
}