feat(oa): 添加项目台账报表功能
- 新增项目台账报表Service接口及实现类 - 创建项目台账报表Controller提供列表查询和导出功能 - 实现项目台账报表Mapper及XML映射文件 - 定义项目台账报表VO对象支持Excel导出 - 集成权限验证和日志记录功能 - 实现分页查询和全量导出功能dev
parent
e1a87a8f71
commit
bda947983b
@ -0,0 +1,66 @@
|
||||
package org.dromara.oa.erp.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.idev.excel.FastExcel;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.oa.erp.domain.vo.ProjectLedgerReportVo;
|
||||
import org.dromara.oa.erp.service.IProjectLedgerReportService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 项目台账报表
|
||||
*
|
||||
* @author Yangk
|
||||
* @date 2026-03-11
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/erp/projectLedgerReport")
|
||||
public class ProjectLedgerReportController {
|
||||
|
||||
private final IProjectLedgerReportService reportService;
|
||||
|
||||
/**
|
||||
* 获取项目台账报表列表
|
||||
*/
|
||||
@SaCheckPermission("oa:erp:projectLedgerReport:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<ProjectLedgerReportVo> list(ProjectLedgerReportVo bo) {
|
||||
return reportService.queryProjectLedgerList(bo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出项目台账报表
|
||||
*/
|
||||
@SaCheckPermission("oa:erp:projectLedgerReport:export")
|
||||
@Log(title = "项目台账报表", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(ProjectLedgerReportVo bo, HttpServletResponse response) {
|
||||
try {
|
||||
List<ProjectLedgerReportVo> list = reportService.queryProjectLedgerAll(bo);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
String fileName = URLEncoder.encode("项目台账报表", "UTF-8").replaceAll("\\+", "%20");
|
||||
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
|
||||
|
||||
FastExcel.write(response.getOutputStream(), ProjectLedgerReportVo.class)
|
||||
.sheet("项目台账报表")
|
||||
.doWrite(list);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("导出失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package org.dromara.oa.erp.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.dromara.oa.erp.domain.vo.ProjectLedgerReportVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 项目台账报表 Mapper
|
||||
*
|
||||
* @author Yangk
|
||||
* @date 2026-03-11
|
||||
*/
|
||||
@Mapper
|
||||
public interface ProjectLedgerReportMapper {
|
||||
|
||||
/**
|
||||
* 查询项目台账报表列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 列表
|
||||
*/
|
||||
List<ProjectLedgerReportVo> selectProjectLedgerList(@Param("bo") ProjectLedgerReportVo bo);
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package org.dromara.oa.erp.service.impl;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.oa.erp.domain.vo.ProjectLedgerReportVo;
|
||||
import org.dromara.oa.erp.mapper.ProjectLedgerReportMapper;
|
||||
import org.dromara.oa.erp.service.IProjectLedgerReportService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 项目台账报表 Service 实现
|
||||
*
|
||||
* @author Yangk
|
||||
* @date 2026-03-11
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class ProjectLedgerReportServiceImpl implements IProjectLedgerReportService {
|
||||
|
||||
private final ProjectLedgerReportMapper reportMapper;
|
||||
|
||||
@Override
|
||||
public TableDataInfo<ProjectLedgerReportVo> queryProjectLedgerList(ProjectLedgerReportVo bo) {
|
||||
List<ProjectLedgerReportVo> list = reportMapper.selectProjectLedgerList(bo);
|
||||
return TableDataInfo.build(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProjectLedgerReportVo> queryProjectLedgerAll(ProjectLedgerReportVo bo) {
|
||||
return reportMapper.selectProjectLedgerList(bo);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.oa.erp.mapper.ProjectLedgerReportMapper">
|
||||
|
||||
<select id="selectProjectLedgerList" resultType="org.dromara.oa.erp.domain.vo.ProjectLedgerReportVo">
|
||||
SELECT
|
||||
p.project_id,
|
||||
p.project_code,
|
||||
p.project_name,
|
||||
p.project_category,
|
||||
p.project_status,
|
||||
p.payment_method,
|
||||
p.contract_id,
|
||||
u1.nick_name AS manager_name,
|
||||
d.dept_name,
|
||||
CONCAT(t2.type_name, '/', t1.type_name) AS type_name,
|
||||
<!-- 合同信息 -->
|
||||
c.contract_date,
|
||||
c.total_price AS contract_amount,
|
||||
cust.customer_name,
|
||||
u2.nick_name AS contract_manager_name,
|
||||
<!-- 预算信息 -->
|
||||
b.budget_cost,
|
||||
b.budget_rate,
|
||||
b.reduce_budget_cost,
|
||||
b.reduce_budget_rate,
|
||||
CASE WHEN b.contract_amount IS NOT NULL THEN ROUND(b.contract_amount / 1.13, 2) ELSE NULL END AS revenue,
|
||||
<!-- 验收信息 -->
|
||||
acc.acceptance_date,
|
||||
<!-- 累计工时 -->
|
||||
hours_sub.total_hours,
|
||||
<!-- 产品数量 -->
|
||||
mat_sub.product_amount
|
||||
FROM
|
||||
erp_project_info p
|
||||
LEFT JOIN erp_project_type t1 ON t1.project_type_id = p.project_type_id
|
||||
LEFT JOIN erp_project_type t2 ON t1.parent_id = t2.project_type_id
|
||||
LEFT JOIN sys_dept d ON d.dept_id = p.dept_id
|
||||
LEFT JOIN sys_user u1 ON u1.user_id = p.manager_id
|
||||
<!-- 合同 + 客户 + 客户经理 -->
|
||||
LEFT JOIN erp_contract_info c ON p.contract_id = c.contract_id AND c.del_flag = '0'
|
||||
LEFT JOIN crm_customer_info cust ON c.one_customer_id = cust.customer_id AND cust.del_flag = '0'
|
||||
LEFT JOIN sys_user u2 ON c.contract_manager_id = u2.user_id
|
||||
<!-- 预算(取已审批的) -->
|
||||
LEFT JOIN erp_budget_info b ON p.project_id = b.project_id AND b.budget_status = '3' AND b.del_flag = '0'
|
||||
<!-- 验收(取已完成审批的) -->
|
||||
LEFT JOIN (
|
||||
SELECT project_id, MAX(acceptance_date) AS acceptance_date
|
||||
FROM erp_project_acceptance
|
||||
WHERE del_flag = '0' AND flow_status = 'finish'
|
||||
GROUP BY project_id
|
||||
) acc ON p.project_id = acc.project_id
|
||||
<!-- 累计工时 -->
|
||||
LEFT JOIN (
|
||||
SELECT tp.project_id, COALESCE(SUM(tp.hours), 0) AS total_hours
|
||||
FROM erp_timesheet_project tp
|
||||
JOIN erp_timesheet_info ti ON tp.timesheet_id = ti.timesheet_id AND ti.del_flag = '0'
|
||||
WHERE tp.del_flag = '0' AND ti.timesheet_status = '3'
|
||||
GROUP BY tp.project_id
|
||||
) hours_sub ON p.project_id = hours_sub.project_id
|
||||
<!-- 产品数量(按合同聚合) -->
|
||||
LEFT JOIN (
|
||||
SELECT contract_id, SUM(amount) AS product_amount
|
||||
FROM erp_contract_material
|
||||
WHERE del_flag = '0'
|
||||
GROUP BY contract_id
|
||||
) mat_sub ON p.contract_id = mat_sub.contract_id
|
||||
<where>
|
||||
p.del_flag = '0'
|
||||
AND p.project_category <> '9'
|
||||
<if test="bo.params != null and bo.params.projectIds != null and bo.params.projectIds != ''">
|
||||
AND p.project_id IN
|
||||
<foreach collection="bo.params.projectIds.split(',')" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="bo.projectName != null and bo.projectName != ''">
|
||||
AND p.project_name LIKE concat('%', #{bo.projectName}, '%')
|
||||
</if>
|
||||
<if test="bo.projectCode != null and bo.projectCode != ''">
|
||||
AND p.project_code LIKE concat('%', #{bo.projectCode}, '%')
|
||||
</if>
|
||||
<if test="bo.businessDirection != null and bo.businessDirection != ''">
|
||||
AND p.business_direction = #{bo.businessDirection}
|
||||
</if>
|
||||
<if test="bo.projectStatus != null and bo.projectStatus != ''">
|
||||
AND p.project_status = #{bo.projectStatus}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY p.create_time DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue