gaoluyang
昨天 90b3ad820eea45d021835197eac5bc3ad55b12ed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
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;
    }
 
}