package cn.iocoder.yudao.module.finance.controller.admin.subject;
|
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
import cn.iocoder.yudao.module.finance.controller.admin.subject.vo.FinAccountSubjectPageReqVO;
|
import cn.iocoder.yudao.module.finance.controller.admin.subject.vo.FinAccountSubjectRespVO;
|
import cn.iocoder.yudao.module.finance.controller.admin.subject.vo.FinAccountSubjectSaveReqVO;
|
import cn.iocoder.yudao.module.finance.dal.dataobject.subject.FinAccountSubjectDO;
|
import cn.iocoder.yudao.module.finance.service.subject.FinAccountSubjectService;
|
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
import jakarta.annotation.Resource;
|
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.validation.Valid;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.validation.annotation.Validated;
|
import org.springframework.web.bind.annotation.*;
|
|
import java.io.IOException;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.Map;
|
|
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
|
@Tag(name = "管理后台 - 财务会计科目")
|
@RestController
|
@RequestMapping("/finance/account-subject")
|
@Validated
|
public class FinAccountSubjectController {
|
|
@Resource
|
private FinAccountSubjectService accountSubjectService;
|
|
@PostMapping("/create")
|
@Operation(summary = "创建会计科目")
|
@PreAuthorize("@ss.hasPermission('finance:account-subject:create')")
|
public CommonResult<Long> createAccountSubject(@Valid @RequestBody FinAccountSubjectSaveReqVO createReqVO) {
|
return success(accountSubjectService.createAccountSubject(createReqVO));
|
}
|
|
@PutMapping("/update")
|
@Operation(summary = "更新会计科目")
|
@PreAuthorize("@ss.hasPermission('finance:account-subject:update')")
|
public CommonResult<Boolean> updateAccountSubject(@Valid @RequestBody FinAccountSubjectSaveReqVO updateReqVO) {
|
accountSubjectService.updateAccountSubject(updateReqVO);
|
return success(true);
|
}
|
|
@DeleteMapping("/delete")
|
@Operation(summary = "删除会计科目", description = "存在下级科目或被凭证分录引用时不允许删除")
|
@Parameter(name = "ids", description = "科目编号数组", required = true, example = "1,2,3")
|
@PreAuthorize("@ss.hasPermission('finance:account-subject:delete')")
|
public CommonResult<Boolean> deleteAccountSubject(@RequestParam("ids") List<Long> ids) {
|
accountSubjectService.deleteAccountSubjectList(ids);
|
return success(true);
|
}
|
|
@GetMapping("/get")
|
@Operation(summary = "获得会计科目")
|
@Parameter(name = "id", description = "科目编号", required = true, example = "1024")
|
@PreAuthorize("@ss.hasPermission('finance:account-subject:query')")
|
public CommonResult<FinAccountSubjectRespVO> getAccountSubject(@RequestParam("id") Long id) {
|
FinAccountSubjectDO subject = accountSubjectService.getAccountSubject(id);
|
return success(BeanUtils.toBean(subject, FinAccountSubjectRespVO.class));
|
}
|
|
/**
|
* 会计科目树形列表页的取数方式:一次拉全量命中的科目,再在前端内存里组树,分页对树没有意义,
|
* 所以前端传 pageSize = -1(即框架的 PageParam.PAGE_SIZE_NONE,语义是「查询全部」)。
|
*
|
* 但 PageParam 上挂着 @Min(1) @Max(200),请求里的 -1 会被参数校验直接拦成
|
* 400「每页条数最小值为 1」。PAGE_SIZE_NONE 在框架里一直是服务端导出方法内部 set 的
|
* (见下方 export-excel),从没走 HTTP 参数校验,所以这里必须去掉 @Valid,
|
* 改为在方法内把 pageSize < 1 显式归一为 PAGE_SIZE_NONE,让「查询全部」这条路走得通。
|
*/
|
@GetMapping("/page")
|
@Operation(summary = "获得会计科目分页", description = "pageSize 传 -1 表示查询全部(树形列表页组树用)")
|
@PreAuthorize("@ss.hasPermission('finance:account-subject:query')")
|
public CommonResult<PageResult<FinAccountSubjectRespVO>> getAccountSubjectPage(FinAccountSubjectPageReqVO pageReqVO) {
|
if (pageReqVO.getPageSize() == null || pageReqVO.getPageSize() < 1) {
|
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
}
|
PageResult<FinAccountSubjectDO> pageResult = accountSubjectService.getAccountSubjectPage(pageReqVO);
|
return success(BeanUtils.toBean(pageResult, FinAccountSubjectRespVO.class));
|
}
|
|
@GetMapping("/list")
|
@Operation(summary = "获得会计科目树列表", description = "返回全量科目,按父子层级组装 children")
|
@PreAuthorize("@ss.hasPermission('finance:account-subject:query')")
|
public CommonResult<List<FinAccountSubjectRespVO>> getAccountSubjectList() {
|
return success(buildTree(accountSubjectService.getAccountSubjectList()));
|
}
|
|
@GetMapping("/simple-list")
|
@Operation(summary = "获得会计科目精简列表", description = "用于凭证分录的科目下拉/树选择")
|
public CommonResult<List<FinAccountSubjectRespVO>> getAccountSubjectSimpleList() {
|
List<FinAccountSubjectDO> list = accountSubjectService.getAccountSubjectList();
|
return success(convertList(list, subject -> new FinAccountSubjectRespVO()
|
.setId(subject.getId()).setParentId(subject.getParentId())
|
.setSubjectCode(subject.getSubjectCode()).setSubjectName(subject.getSubjectName())
|
.setSubjectType(subject.getSubjectType()).setBalanceDirection(subject.getBalanceDirection())
|
.setStatus(subject.getStatus())));
|
}
|
|
@GetMapping("/export-excel")
|
@Operation(summary = "导出会计科目 Excel")
|
@PreAuthorize("@ss.hasPermission('finance:account-subject:export')")
|
@ApiAccessLog(operateType = EXPORT)
|
public void exportAccountSubjectExcel(@Valid FinAccountSubjectPageReqVO pageReqVO,
|
HttpServletResponse response) throws IOException {
|
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
List<FinAccountSubjectDO> list = accountSubjectService.getAccountSubjectPage(pageReqVO).getList();
|
// 导出 Excel
|
ExcelUtils.write(response, "会计科目.xls", "数据", FinAccountSubjectRespVO.class,
|
BeanUtils.toBean(list, FinAccountSubjectRespVO.class));
|
}
|
|
/**
|
* 将扁平科目列表组装为树:上级科目不存在(已被删除)时,按根节点处理,避免节点丢失
|
*/
|
private List<FinAccountSubjectRespVO> buildTree(List<FinAccountSubjectDO> list) {
|
List<FinAccountSubjectRespVO> voList = BeanUtils.toBean(list, FinAccountSubjectRespVO.class);
|
Map<Long, FinAccountSubjectRespVO> idMap = convertMap(voList, FinAccountSubjectRespVO::getId);
|
List<FinAccountSubjectRespVO> roots = new ArrayList<>();
|
voList.forEach(vo -> {
|
FinAccountSubjectRespVO parent = vo.getParentId() == null ? null : idMap.get(vo.getParentId());
|
if (parent == null) {
|
roots.add(vo);
|
} else {
|
if (parent.getChildren() == null) {
|
parent.setChildren(new ArrayList<>());
|
}
|
parent.getChildren().add(vo);
|
}
|
});
|
return roots;
|
}
|
|
}
|