新增车间计算记录与数据看板
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
package com.ruoyi.oa.controller;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import com.ruoyi.common.annotation.RepeatSubmit;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.validate.AddGroup;
|
||||
import com.ruoyi.common.core.validate.EditGroup;
|
||||
import com.ruoyi.common.core.validate.QueryGroup;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.oa.domain.vo.OaAttendanceRecordVo;
|
||||
import com.ruoyi.oa.domain.bo.OaAttendanceRecordBo;
|
||||
import com.ruoyi.oa.service.IOaAttendanceRecordService;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 计算记录
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-05-15
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/oa/attendanceRecord")
|
||||
public class OaAttendanceRecordController extends BaseController {
|
||||
|
||||
private final IOaAttendanceRecordService iOaAttendanceRecordService;
|
||||
|
||||
/**
|
||||
* 查询计算记录列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<OaAttendanceRecordVo> list(OaAttendanceRecordBo bo, PageQuery pageQuery) {
|
||||
return iOaAttendanceRecordService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
@GetMapping("/gen-list/{date}")
|
||||
public R<List<String>> list(@PathVariable String date) {
|
||||
return R.ok(iOaAttendanceRecordService.listGenDate(date));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出计算记录列表
|
||||
*/
|
||||
@PostMapping("/export")
|
||||
public void export(OaAttendanceRecordBo bo, HttpServletResponse response) {
|
||||
List<OaAttendanceRecordVo> list = iOaAttendanceRecordService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "计算记录", OaAttendanceRecordVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取计算记录详细信息
|
||||
*
|
||||
* @param recordId 主键
|
||||
*/
|
||||
@GetMapping("/{recordId}")
|
||||
public R<OaAttendanceRecordVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long recordId) {
|
||||
return R.ok(iOaAttendanceRecordService.queryById(recordId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增计算记录
|
||||
*/
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody OaAttendanceRecordBo bo) {
|
||||
return toAjax(iOaAttendanceRecordService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改计算记录
|
||||
*/
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody OaAttendanceRecordBo bo) {
|
||||
return toAjax(iOaAttendanceRecordService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除计算记录
|
||||
*
|
||||
* @param recordIds 主键串
|
||||
*/
|
||||
@DeleteMapping("/{recordIds}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] recordIds) {
|
||||
return toAjax(iOaAttendanceRecordService.deleteWithValidByIds(Arrays.asList(recordIds), true));
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,6 @@ public class OaReportDetailController extends BaseController {
|
||||
/**
|
||||
* 查询设计项目汇报详情列表
|
||||
*/
|
||||
@SaCheckPermission("system:reportDetail:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<OaReportDetailVo> list(OaReportDetailBo bo, PageQuery pageQuery) {
|
||||
return iOaReportDetailService.queryPageList(bo, pageQuery);
|
||||
@@ -51,7 +50,6 @@ public class OaReportDetailController extends BaseController {
|
||||
/**
|
||||
* 导出设计项目汇报详情列表
|
||||
*/
|
||||
@SaCheckPermission("system:reportDetail:export")
|
||||
@Log(title = "设计项目汇报详情", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(OaReportDetailBo bo, HttpServletResponse response) {
|
||||
@@ -64,7 +62,6 @@ public class OaReportDetailController extends BaseController {
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("system:reportDetail:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<OaReportDetailVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
@@ -74,7 +71,6 @@ public class OaReportDetailController extends BaseController {
|
||||
/**
|
||||
* 新增设计项目汇报详情
|
||||
*/
|
||||
@SaCheckPermission("system:reportDetail:add")
|
||||
@Log(title = "设计项目汇报详情", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
@@ -85,7 +81,6 @@ public class OaReportDetailController extends BaseController {
|
||||
/**
|
||||
* 修改设计项目汇报详情
|
||||
*/
|
||||
@SaCheckPermission("system:reportDetail:edit")
|
||||
@Log(title = "设计项目汇报详情", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
@@ -98,8 +93,6 @@ public class OaReportDetailController extends BaseController {
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("system:reportDetail:remove")
|
||||
@Log(title = "设计项目汇报详情", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
|
||||
@@ -42,7 +42,6 @@ public class OaReportSummaryController extends BaseController {
|
||||
/**
|
||||
* 查询设计项目汇报概述列表
|
||||
*/
|
||||
@SaCheckPermission("system:reportSummary:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<OaReportSummaryVo> list(OaReportSummaryBo bo, PageQuery pageQuery) {
|
||||
return iOaReportSummaryService.queryPageList(bo, pageQuery);
|
||||
@@ -51,7 +50,6 @@ public class OaReportSummaryController extends BaseController {
|
||||
/**
|
||||
* 导出设计项目汇报概述列表
|
||||
*/
|
||||
@SaCheckPermission("system:reportSummary:export")
|
||||
@Log(title = "设计项目汇报概述", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(OaReportSummaryBo bo, HttpServletResponse response) {
|
||||
@@ -64,7 +62,6 @@ public class OaReportSummaryController extends BaseController {
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("system:reportSummary:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<OaReportSummaryVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
@@ -74,7 +71,6 @@ public class OaReportSummaryController extends BaseController {
|
||||
/**
|
||||
* 新增设计项目汇报概述
|
||||
*/
|
||||
@SaCheckPermission("system:reportSummary:add")
|
||||
@Log(title = "设计项目汇报概述", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
@@ -85,7 +81,6 @@ public class OaReportSummaryController extends BaseController {
|
||||
/**
|
||||
* 修改设计项目汇报概述
|
||||
*/
|
||||
@SaCheckPermission("system:reportSummary:edit")
|
||||
@Log(title = "设计项目汇报概述", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
@@ -98,7 +93,6 @@ public class OaReportSummaryController extends BaseController {
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("system:reportSummary:remove")
|
||||
@Log(title = "设计项目汇报概述", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.util.Arrays;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.oa.domain.LaborCostData;
|
||||
import com.ruoyi.oa.domain.vo.AttendanceMonthlyCount;
|
||||
import com.ruoyi.oa.domain.vo.SysUserVo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -163,4 +164,21 @@ public class SysOaAttendanceController extends BaseController {
|
||||
public R<Void> insertBatch(@Validated(AddGroup.class) @RequestBody SysOaAttendanceBo bo) {
|
||||
return toAjax( iSysOaAttendanceService.insertBatch(bo));
|
||||
}
|
||||
|
||||
@GetMapping("/data/{refDate}")
|
||||
public R<List<AttendanceMonthlyCount>> selectLastSixMonthsByMonth(@PathVariable String refDate) {
|
||||
return R.ok(iSysOaAttendanceService.selectLastSixMonthsByMonth(refDate));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/data/pie/{refDate}")
|
||||
public R<AttendanceMonthlyCount> selectAttendanceMonthlyCountByMonth(@PathVariable String refDate) {
|
||||
return R.ok(iSysOaAttendanceService.selectAttendanceMonthlyCountByMonth(refDate));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/data/card/{refDate}")
|
||||
public R<List<AttendanceMonthlyCount>> selectMonthlyCounts(@PathVariable String refDate) {
|
||||
return R.ok(iSysOaAttendanceService.selectMonthlyCounts(refDate));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,12 @@ public class LaborCostData extends BaseEntity {
|
||||
// 加班时间
|
||||
private Double overtime;
|
||||
|
||||
// 出差次数
|
||||
private Double tripTimes;
|
||||
|
||||
// 请假次数
|
||||
private Double absenceDays;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.ruoyi.oa.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 计算记录对象 oa_attendance_record
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-05-15
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("oa_attendance_record")
|
||||
public class OaAttendanceRecord extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID=1L;
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId(value = "record_id")
|
||||
private Long recordId;
|
||||
/**
|
||||
* 涉及月份
|
||||
*/
|
||||
private Date relationMonth;
|
||||
/**
|
||||
* 生成时间
|
||||
*/
|
||||
private Date calcTime;
|
||||
/**
|
||||
* 统计者姓名
|
||||
*/
|
||||
private String nickName;
|
||||
/**
|
||||
* 出差天数
|
||||
*/
|
||||
private BigDecimal trips;
|
||||
/**
|
||||
* 请假次数
|
||||
*/
|
||||
private BigDecimal notNum;
|
||||
/**
|
||||
* 出勤天数
|
||||
*/
|
||||
private BigDecimal works;
|
||||
/**
|
||||
* 涉及项目
|
||||
*/
|
||||
private String projectIds;
|
||||
/**
|
||||
* 加班时长
|
||||
*/
|
||||
private BigDecimal overNum;
|
||||
/**
|
||||
* 删除标志
|
||||
*/
|
||||
@TableLogic
|
||||
private Long delFlag;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
private Long userId;
|
||||
|
||||
}
|
||||
@@ -25,8 +25,8 @@ public class OaReportDetail extends BaseEntity {
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
@TableId(value = "detail_id")
|
||||
private Long detailId;
|
||||
/**
|
||||
* 关联汇报概述ID(oa_report_summary.id)
|
||||
*/
|
||||
|
||||
@@ -27,8 +27,8 @@ public class OaReportSummary extends BaseEntity {
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
@TableId(value = "summary_id")
|
||||
private Long summaryId;
|
||||
/**
|
||||
* 汇报标题
|
||||
*/
|
||||
@@ -55,4 +55,6 @@ public class OaReportSummary extends BaseEntity {
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
private Long type;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.ruoyi.oa.domain.bo;
|
||||
|
||||
import com.ruoyi.common.core.validate.AddGroup;
|
||||
import com.ruoyi.common.core.validate.EditGroup;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
/**
|
||||
* 计算记录业务对象 oa_attendance_record
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-05-15
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class OaAttendanceRecordBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
private Long recordId;
|
||||
|
||||
/**
|
||||
* 涉及月份
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date relationMonth;
|
||||
|
||||
/**
|
||||
* 生成时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date calcTime;
|
||||
|
||||
/**
|
||||
* 统计者姓名
|
||||
*/
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 出差天数
|
||||
*/
|
||||
private BigDecimal trips;
|
||||
|
||||
/**
|
||||
* 请假次数
|
||||
*/
|
||||
private BigDecimal notNum;
|
||||
|
||||
/**
|
||||
* 出勤天数
|
||||
*/
|
||||
private BigDecimal works;
|
||||
|
||||
/**
|
||||
* 涉及项目
|
||||
*/
|
||||
private String projectIds;
|
||||
|
||||
/**
|
||||
* 加班时长
|
||||
*/
|
||||
private BigDecimal overNum;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
private Long userId;
|
||||
|
||||
|
||||
}
|
||||
@@ -25,48 +25,41 @@ public class OaReportDetailBo extends BaseEntity {
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
private Long detailId;
|
||||
|
||||
/**
|
||||
* 关联汇报概述ID(oa_report_summary.id)
|
||||
*/
|
||||
@NotNull(message = "关联汇报概述ID(oa_report_summary.id)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long summaryId;
|
||||
|
||||
/**
|
||||
* 设备唯一编号
|
||||
*/
|
||||
@NotBlank(message = "设备唯一编号不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String deviceCode;
|
||||
|
||||
/**
|
||||
* 设备类别
|
||||
*/
|
||||
@NotBlank(message = "设备类别不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 设备生产说明
|
||||
*/
|
||||
@NotBlank(message = "设备生产说明不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String deviceDescription;
|
||||
|
||||
/**
|
||||
* 汇报详情内容(含文字、图像说明等)
|
||||
*/
|
||||
@NotBlank(message = "汇报详情内容(含文字、图像说明等)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String reportDetail;
|
||||
|
||||
/**
|
||||
* 关联图像 OSS ID 列表(逗号分隔)
|
||||
*/
|
||||
@NotBlank(message = "关联图像 OSS ID 列表(逗号分隔)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String ossIds;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String remark;
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public class OaReportSummaryBo extends BaseEntity {
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
private Long summaryId;
|
||||
|
||||
/**
|
||||
* 汇报标题
|
||||
@@ -59,4 +59,6 @@ public class OaReportSummaryBo extends BaseEntity {
|
||||
private String remark;
|
||||
|
||||
|
||||
private Long type;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.oa.domain.vo;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AttendanceMonthlyCount {
|
||||
/** 格式:"2025-05" */
|
||||
private String month;
|
||||
/** 出勤次数(含出差) */
|
||||
private Integer attendanceCount;
|
||||
/** 请假次数 */
|
||||
private Integer leaveCount;
|
||||
// + getters/setters
|
||||
|
||||
private Long workHours;
|
||||
|
||||
private Long leaveHours;
|
||||
|
||||
private Long overtimeHours;
|
||||
|
||||
private Long tripHours;
|
||||
|
||||
|
||||
private Double attendanceRate; // 出勤率(0‑1 之间)
|
||||
|
||||
private Integer tripCount; // 出差次数
|
||||
|
||||
private Integer leavePeople; // 请假人数
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.ruoyi.oa.domain.vo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.ruoyi.common.annotation.ExcelDictFormat;
|
||||
import com.ruoyi.common.convert.ExcelDictConvert;
|
||||
import com.ruoyi.oa.domain.LaborCostData;
|
||||
import lombok.Data;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 计算记录视图对象 oa_attendance_record
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-05-15
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class OaAttendanceRecordVo {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@ExcelProperty(value = "主键id")
|
||||
private Long recordId;
|
||||
|
||||
/**
|
||||
* 涉及月份
|
||||
*/
|
||||
@ExcelProperty(value = "涉及月份")
|
||||
private Date relationMonth;
|
||||
|
||||
/**
|
||||
* 生成时间
|
||||
*/
|
||||
@ExcelProperty(value = "生成时间")
|
||||
private Date calcTime;
|
||||
|
||||
/**
|
||||
* 统计者姓名
|
||||
*/
|
||||
@ExcelProperty(value = "统计者姓名")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 出差天数
|
||||
*/
|
||||
@ExcelProperty(value = "出差天数")
|
||||
private BigDecimal trips;
|
||||
|
||||
/**
|
||||
* 请假次数
|
||||
*/
|
||||
@ExcelProperty(value = "请假次数")
|
||||
private BigDecimal notNum;
|
||||
|
||||
/**
|
||||
* 出勤天数
|
||||
*/
|
||||
@ExcelProperty(value = "出勤天数")
|
||||
private BigDecimal works;
|
||||
|
||||
/**
|
||||
* 涉及项目
|
||||
*/
|
||||
@ExcelProperty(value = "涉及项目")
|
||||
private String projectIds;
|
||||
|
||||
/**
|
||||
* 加班时长
|
||||
*/
|
||||
@ExcelProperty(value = "加班时长")
|
||||
private BigDecimal overNum;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
private List<SysOaAttendanceVo> attendanceList;
|
||||
|
||||
private Long userId;
|
||||
|
||||
|
||||
/** ▶︎ 按项目汇总 */
|
||||
private List<ProjectAttendanceSummaryVo> projectList;
|
||||
|
||||
private Long laborCost;
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public class OaReportDetailVo {
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
private Long detailId;
|
||||
|
||||
/**
|
||||
* 关联汇报概述ID(oa_report_summary.id)
|
||||
|
||||
@@ -27,7 +27,7 @@ public class OaReportSummaryVo {
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
private Long summaryId;
|
||||
|
||||
/**
|
||||
* 汇报标题
|
||||
@@ -65,5 +65,7 @@ public class OaReportSummaryVo {
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
private Long type;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ruoyi.oa.domain.vo;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/** 项目维度汇总行 */
|
||||
@Data
|
||||
public class ProjectAttendanceSummaryVo {
|
||||
private Long projectId;
|
||||
private String projectName;
|
||||
private String color;
|
||||
|
||||
private Integer workTimes; // 出勤天数
|
||||
private Integer hourWorkTimes; // 工作时长(h)
|
||||
private Integer overTime; // 加班时长(h)
|
||||
private Integer tripDays; // 出差天数
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.ruoyi.oa.mapper;
|
||||
|
||||
import com.ruoyi.oa.domain.OaAttendanceRecord;
|
||||
import com.ruoyi.oa.domain.vo.OaAttendanceRecordVo;
|
||||
import com.ruoyi.common.core.mapper.BaseMapperPlus;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 计算记录Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-05-15
|
||||
*/
|
||||
public interface OaAttendanceRecordMapper extends BaseMapperPlus<OaAttendanceRecordMapper, OaAttendanceRecord, OaAttendanceRecordVo> {
|
||||
|
||||
/**
|
||||
* 获取全部的生成日期
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
List<String> listGenDate(String date);
|
||||
|
||||
/**
|
||||
* 获取全部相同日期数据
|
||||
*
|
||||
* @param date
|
||||
* @param firstDay
|
||||
* @return
|
||||
*/
|
||||
List<Long> listCommonDateRecord(@Param("date") String date, @Param("firstDay") Date firstDay);
|
||||
|
||||
/**
|
||||
* 查询详情
|
||||
* @param recordId
|
||||
* @return
|
||||
*/
|
||||
OaAttendanceRecordVo selectVoByIdPlus(Long recordId);
|
||||
}
|
||||
@@ -14,4 +14,7 @@ import org.apache.ibatis.annotations.Select;
|
||||
public interface OaReportDetailMapper extends BaseMapperPlus<OaReportDetailMapper, OaReportDetail, OaReportDetailVo> {
|
||||
@Select("SELECT url FROM sys_oss WHERE oss_id = #{ossId}")
|
||||
String selectImageUrlByOssId(String ossId);
|
||||
|
||||
|
||||
OaReportDetailVo selectVoByIdPlus(Long id);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package com.ruoyi.oa.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import com.ruoyi.oa.domain.SysOaAttendance;
|
||||
import com.ruoyi.oa.domain.bo.SysOaAttendanceBo;
|
||||
import com.ruoyi.oa.domain.vo.AttendanceMonthlyCount;
|
||||
import com.ruoyi.oa.domain.vo.SysOaAttendanceVo;
|
||||
import com.ruoyi.common.core.mapper.BaseMapperPlus;
|
||||
import com.ruoyi.oa.domain.vo.SysUserVo;
|
||||
@@ -38,4 +37,11 @@ public interface SysOaAttendanceMapper extends BaseMapperPlus<SysOaAttendanceMap
|
||||
Double getAttendanceDay(@Param("userId") Long userId,
|
||||
@Param("projectId") Long projectId );
|
||||
|
||||
List<Long> selectNowMonthUserId(Date firstDay);
|
||||
|
||||
List<AttendanceMonthlyCount> selectLastSixMonthsByMonth(String refDate);
|
||||
|
||||
AttendanceMonthlyCount selectAttendanceMonthlyCountByMonth(String refDate);
|
||||
|
||||
List<AttendanceMonthlyCount> selectMonthlyCounts(String refDate);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.ruoyi.oa.service;
|
||||
|
||||
import com.ruoyi.oa.domain.vo.OaAttendanceRecordVo;
|
||||
import com.ruoyi.oa.domain.bo.OaAttendanceRecordBo;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 计算记录Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-05-15
|
||||
*/
|
||||
public interface IOaAttendanceRecordService {
|
||||
|
||||
/**
|
||||
* 查询计算记录
|
||||
*/
|
||||
OaAttendanceRecordVo queryById(Long recordId);
|
||||
|
||||
/**
|
||||
* 查询计算记录列表
|
||||
*/
|
||||
TableDataInfo<OaAttendanceRecordVo> queryPageList(OaAttendanceRecordBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询计算记录列表
|
||||
*/
|
||||
List<OaAttendanceRecordVo> queryList(OaAttendanceRecordBo bo);
|
||||
|
||||
/**
|
||||
* 新增计算记录
|
||||
*/
|
||||
Boolean insertByBo(OaAttendanceRecordBo bo);
|
||||
|
||||
/**
|
||||
* 修改计算记录
|
||||
*/
|
||||
Boolean updateByBo(OaAttendanceRecordBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除计算记录信息
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 获取某月的所有数据报告的生成日期
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
List<String> listGenDate(String date);
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ruoyi.oa.service;
|
||||
|
||||
import com.ruoyi.oa.domain.LaborCostData;
|
||||
import com.ruoyi.oa.domain.vo.AttendanceMonthlyCount;
|
||||
import com.ruoyi.oa.domain.vo.SysOaAttendanceVo;
|
||||
import com.ruoyi.oa.domain.bo.SysOaAttendanceBo;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
@@ -77,4 +78,15 @@ public interface ISysOaAttendanceService {
|
||||
* @return
|
||||
*/
|
||||
int delOaAttendanceAll(Long day);
|
||||
|
||||
/**
|
||||
* @param refDate
|
||||
* @return
|
||||
*/
|
||||
List<AttendanceMonthlyCount> selectLastSixMonthsByMonth(String refDate);
|
||||
|
||||
AttendanceMonthlyCount selectAttendanceMonthlyCountByMonth(String refDate);
|
||||
|
||||
List<AttendanceMonthlyCount> selectMonthlyCounts(String refDate);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
package com.ruoyi.oa.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.oa.domain.bo.OaAttendanceRecordBo;
|
||||
import com.ruoyi.oa.domain.vo.OaAttendanceRecordVo;
|
||||
import com.ruoyi.oa.domain.OaAttendanceRecord;
|
||||
import com.ruoyi.oa.mapper.OaAttendanceRecordMapper;
|
||||
import com.ruoyi.oa.service.IOaAttendanceRecordService;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 计算记录Service业务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-05-15
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class OaAttendanceRecordServiceImpl implements IOaAttendanceRecordService {
|
||||
|
||||
private final OaAttendanceRecordMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询计算记录
|
||||
*/
|
||||
@Override
|
||||
public OaAttendanceRecordVo queryById(Long recordId){
|
||||
return baseMapper.selectVoByIdPlus(recordId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询计算记录列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<OaAttendanceRecordVo> queryPageList(OaAttendanceRecordBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<OaAttendanceRecord> lqw = buildQueryWrapper(bo);
|
||||
Page<OaAttendanceRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<OaAttendanceRecord> buildQueryWrapper(OaAttendanceRecordBo bo) {
|
||||
LambdaQueryWrapper<OaAttendanceRecord> lqw = Wrappers.lambdaQuery();
|
||||
if (bo.getRelationMonth() != null) {
|
||||
lqw.apply(
|
||||
|
||||
"YEAR(relation_month) = YEAR({0}) AND MONTH(relation_month) = MONTH({1})",
|
||||
bo.getRelationMonth(), bo.getRelationMonth());
|
||||
if (bo.getCalcTime() != null) {
|
||||
// 2a) 如果前端传了 genTime,就按那天精准过滤
|
||||
lqw.apply("DATE(calc_time) = {0}", bo.getCalcTime());
|
||||
} else {
|
||||
// 2b) 如果没传 genTime,就只拿该月最新一次的记录
|
||||
lqw.apply(
|
||||
"calc_time = (" +
|
||||
"SELECT MAX(calc_time) FROM oa_attendance_record " +
|
||||
"WHERE YEAR(relation_month)=YEAR({0}) AND MONTH(relation_month)=MONTH({1})" +
|
||||
")",
|
||||
bo.getRelationMonth(), bo.getRelationMonth()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询计算记录列表
|
||||
*/
|
||||
@Override
|
||||
public List<OaAttendanceRecordVo> queryList(OaAttendanceRecordBo bo) {
|
||||
LambdaQueryWrapper<OaAttendanceRecord> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 新增计算记录
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(OaAttendanceRecordBo bo) {
|
||||
OaAttendanceRecord add = BeanUtil.toBean(bo, OaAttendanceRecord.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setRecordId(add.getRecordId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改计算记录
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(OaAttendanceRecordBo bo) {
|
||||
OaAttendanceRecord update = BeanUtil.toBean(bo, OaAttendanceRecord.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(OaAttendanceRecord entity){
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除计算记录
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if(isValid){
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listGenDate(String date) {
|
||||
|
||||
return baseMapper.listGenDate(date);
|
||||
}
|
||||
}
|
||||
@@ -88,11 +88,13 @@ public class OaProgressServiceImpl implements IOaProgressService {
|
||||
OaProgress add = BeanUtil.toBean(bo, OaProgress.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
List<OaProgressDetailBo> detailList = bo.getDetailList();
|
||||
for (OaProgressDetailBo detailBo : detailList) {
|
||||
detailBo.setProgressId(add.getProgressId());
|
||||
detailService.insertByBo(detailBo);
|
||||
if(bo.getDetailList() != null && !bo.getDetailList().isEmpty()) {
|
||||
for (OaProgressDetailBo detailBo : bo.getDetailList()) {
|
||||
detailBo.setProgressId(add.getProgressId());
|
||||
detailService.insertByBo(detailBo);
|
||||
}
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public class OaReportDetailServiceImpl implements IOaReportDetailService {
|
||||
@Override
|
||||
public OaReportDetailVo queryById(Long id){
|
||||
|
||||
return baseMapper.selectVoById(id);
|
||||
return baseMapper.selectVoByIdPlus(id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,7 +119,7 @@ public class OaReportDetailServiceImpl implements IOaReportDetailService {
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
bo.setDetailId(add.getDetailId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ public class OaReportSummaryServiceImpl implements IOaReportSummaryService {
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
bo.setSummaryId(add.getSummaryId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
@@ -8,8 +8,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.oa.domain.LaborCostData;
|
||||
import com.ruoyi.oa.domain.OaAttendanceRecord;
|
||||
import com.ruoyi.oa.domain.vo.AttendanceMonthlyCount;
|
||||
import com.ruoyi.oa.domain.vo.SysOaProjectVo;
|
||||
import com.ruoyi.oa.domain.vo.SysUserVo;
|
||||
import com.ruoyi.oa.mapper.OaAttendanceRecordMapper;
|
||||
import com.ruoyi.oa.service.ISysOaProjectService;
|
||||
import com.ruoyi.system.mapper.SysUserRoleMapper;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
@@ -23,9 +26,10 @@ import com.ruoyi.oa.domain.SysOaAttendance;
|
||||
import com.ruoyi.oa.mapper.SysOaAttendanceMapper;
|
||||
import com.ruoyi.oa.service.ISysOaAttendanceService;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 人员考勤Service业务层处理
|
||||
@@ -49,6 +53,9 @@ public class SysOaAttendanceServiceImpl implements ISysOaAttendanceService {
|
||||
@Autowired
|
||||
private ISysOaProjectService projectService;
|
||||
|
||||
@Autowired
|
||||
private OaAttendanceRecordMapper recordMapper;
|
||||
|
||||
/**
|
||||
* 查询人员考勤
|
||||
*/
|
||||
@@ -84,7 +91,7 @@ public class SysOaAttendanceServiceImpl implements ISysOaAttendanceService {
|
||||
lqw.eq(bo.getProjectId() != null, SysOaAttendance::getProjectId, bo.getProjectId());
|
||||
lqw.eq(bo.getDayLength() != null, SysOaAttendance::getDayLength, bo.getDayLength());
|
||||
lqw.eq(bo.getHour() != null, SysOaAttendance::getHour, bo.getHour());
|
||||
lqw.like(bo.getCreateTime()!=null, SysOaAttendance::getCreateTime, bo.getCreateTime());
|
||||
lqw.like(bo.getCreateTime() != null, SysOaAttendance::getCreateTime, bo.getCreateTime());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@@ -122,8 +129,8 @@ public class SysOaAttendanceServiceImpl implements ISysOaAttendanceService {
|
||||
sysOaAttendanceVo.setProjectId(bo.getProjectId());
|
||||
sysOaAttendanceVo.setCreateTime(firstDay);
|
||||
sysOaAttendanceVo.setDelFlag(0L);
|
||||
sysOaAttendanceVo.setDayLength(bo.getDayLength()!=null?bo.getDayLength():0);
|
||||
sysOaAttendanceVo.setHour(bo.getHour()!=null?bo.getHour():0);
|
||||
sysOaAttendanceVo.setDayLength(bo.getDayLength() != null ? bo.getDayLength() : 0);
|
||||
sysOaAttendanceVo.setHour(bo.getHour() != null ? bo.getHour() : 0);
|
||||
return baseMapper.updateDelAttendance(BeanUtil.toBean(sysOaAttendanceVo, SysOaAttendance.class)) > 0;
|
||||
}
|
||||
|
||||
@@ -201,13 +208,29 @@ public class SysOaAttendanceServiceImpl implements ISysOaAttendanceService {
|
||||
*/
|
||||
@Override
|
||||
public List<LaborCostData> workerCalc(Date time) {
|
||||
// 查询所有的工人
|
||||
List<Long> userIds = sysUserRoleMapper.selectUserIdsByRoleId(1852970465740505090L);
|
||||
|
||||
Date firstDay = getFirstDay(time);
|
||||
Date lastDay = getLastDay(time);
|
||||
// 查询所有的工人
|
||||
List<Long> userIds = sysUserRoleMapper.selectUserIdsByRoleId(1852970465740505090L);
|
||||
List<Long> workerIds = baseMapper.selectNowMonthUserId(firstDay);
|
||||
// 合并并去重
|
||||
workerIds = Stream
|
||||
.concat(userIds.stream(), workerIds.stream())
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
List<LaborCostData> costDataList = new ArrayList<>();
|
||||
for (Long userId : userIds) {
|
||||
|
||||
|
||||
// 检测当天是否生成了完全一样的数据
|
||||
List<Long> recordIds = recordMapper.listCommonDateRecord(DateUtils.getDate(), firstDay);
|
||||
if (!recordIds.isEmpty()) {
|
||||
// 如果有重复的就删掉
|
||||
recordMapper.deleteBatchIds(recordIds);
|
||||
}
|
||||
|
||||
// 开始写入
|
||||
for (Long userId : workerIds) {
|
||||
SysUserVo sysUser = BeanUtil.toBean(sysUserService.selectUserByIdIncludingDel(userId), SysUserVo.class);
|
||||
SysOaAttendanceVo sysOaAttendanceVo = new SysOaAttendanceVo();
|
||||
sysOaAttendanceVo.setUserId(sysUser.getUserId());
|
||||
@@ -218,8 +241,19 @@ public class SysOaAttendanceServiceImpl implements ISysOaAttendanceService {
|
||||
Double workTimes = 0.0;
|
||||
Double hourWorkTimes = 0.0;
|
||||
Double overTime = 0.0;
|
||||
Double tripDays = 0.0;
|
||||
Double leaveCount = 0.0;
|
||||
Double workDays = 0.0;
|
||||
Set<Long> projSet = new HashSet<>();
|
||||
for (SysOaAttendanceVo oaAttendanceVo : sysOaAttendanceVos) {
|
||||
// 出差问题解决
|
||||
// 出差
|
||||
if (oaAttendanceVo.getProjectId() == 0) {
|
||||
tripDays++;
|
||||
|
||||
} else if (oaAttendanceVo.getProjectId() == 1) {
|
||||
leaveCount++;
|
||||
}
|
||||
if (oaAttendanceVo.getProjectId() != 0 && oaAttendanceVo.getProjectId() != 1) {
|
||||
SysOaProjectVo sysOaProjectVo = projectService.queryById(oaAttendanceVo.getProjectId());
|
||||
oaAttendanceVo.setColor(sysOaProjectVo.getColor());
|
||||
@@ -228,7 +262,9 @@ public class SysOaAttendanceServiceImpl implements ISysOaAttendanceService {
|
||||
projectVos.add(sysOaProjectVo);
|
||||
workTimes += oaAttendanceVo.getWorkTimes();
|
||||
hourWorkTimes += oaAttendanceVo.getHourWorkTimes();
|
||||
overTime+=oaAttendanceVo.getOverTime();
|
||||
overTime += oaAttendanceVo.getOverTime();
|
||||
projSet.add(oaAttendanceVo.getProjectId());
|
||||
workDays++;
|
||||
}
|
||||
}
|
||||
// 此为所有小时计的综合
|
||||
@@ -238,16 +274,43 @@ public class SysOaAttendanceServiceImpl implements ISysOaAttendanceService {
|
||||
laborCostData.setAttendances(sysOaAttendanceVos);
|
||||
laborCostData.setSysUser(sysUser);
|
||||
laborCostData.setWorkTimes(workTimes);
|
||||
laborCostData.setTripTimes(tripDays);
|
||||
laborCostData.setAbsenceDays(leaveCount);
|
||||
laborCostData.setHourWorkTime(hourWorkTimes);
|
||||
// 加班时间
|
||||
laborCostData.setOvertime(overTime);
|
||||
costDataList.add(laborCostData);
|
||||
// 构造并保存记录
|
||||
addGenData(firstDay, sysUser, tripDays, leaveCount, workDays, projSet, overTime);
|
||||
}
|
||||
|
||||
|
||||
return costDataList;
|
||||
}
|
||||
|
||||
private void addGenData(Date firstDay, SysUserVo sysUser, Double tripDays, Double leaveCount, Double workDays, Set<Long> projSet, Double overtimeSum) {
|
||||
OaAttendanceRecord rec = new OaAttendanceRecord();
|
||||
// relationMonth 只保留年月,可直接传入 firstDay(其 day=1)
|
||||
rec.setRelationMonth(firstDay);
|
||||
// calcTime 为当前时间
|
||||
rec.setCalcTime(new Date());
|
||||
// 当前操作人昵称
|
||||
rec.setNickName(sysUser.getNickName());
|
||||
rec.setUserId(sysUser.getUserId());
|
||||
rec.setTrips(BigDecimal.valueOf(tripDays));
|
||||
rec.setNotNum(BigDecimal.valueOf(leaveCount));
|
||||
rec.setWorks(BigDecimal.valueOf(workDays));
|
||||
rec.setProjectIds(
|
||||
String.join(",",
|
||||
projSet.stream().map(String::valueOf).toArray(String[]::new)
|
||||
)
|
||||
);
|
||||
rec.setOverNum(BigDecimal.valueOf(overtimeSum));
|
||||
rec.setRemark("自动统计生成");
|
||||
recordMapper.insert(rec);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除当月某日所有人的记录
|
||||
*
|
||||
@@ -261,6 +324,25 @@ public class SysOaAttendanceServiceImpl implements ISysOaAttendanceService {
|
||||
return baseMapper.delOaAttendanceAll(getFirstDay(now), getLastDay(now), day);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AttendanceMonthlyCount> selectLastSixMonthsByMonth(String refDate) {
|
||||
|
||||
return baseMapper.selectLastSixMonthsByMonth(refDate);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AttendanceMonthlyCount selectAttendanceMonthlyCountByMonth(String refDate) {
|
||||
|
||||
return baseMapper.selectAttendanceMonthlyCountByMonth(refDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AttendanceMonthlyCount> selectMonthlyCounts(String refDate) {
|
||||
|
||||
return baseMapper.selectMonthlyCounts(refDate);
|
||||
}
|
||||
|
||||
private Date getFirstDay(Date time) {
|
||||
String firstDay = DateUtils.parseDateToStr("yyyy-MM-01", time);
|
||||
return DateUtils.parseDate(firstDay);
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
<?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="com.ruoyi.oa.mapper.OaAttendanceRecordMapper">
|
||||
|
||||
<resultMap id="OaAttendanceRecordResult"
|
||||
type="com.ruoyi.oa.domain.vo.OaAttendanceRecordVo">
|
||||
<!-- ① 主键 -->
|
||||
<id property="recordId" column="record_id"/>
|
||||
<!-- ② 其他主字段 -->
|
||||
<result property="userId" column="user_id"/>
|
||||
<result property="relationMonth" column="relation_month"/>
|
||||
<result property="calcTime" column="calc_time"/>
|
||||
<result property="nickName" column="nick_name"/>
|
||||
<result property="trips" column="trips"/>
|
||||
<result property="notNum" column="not_num"/>
|
||||
<result property="works" column="works"/>
|
||||
<result property="projectIds" column="project_ids"/>
|
||||
<result property="overNum" column="over_num"/>
|
||||
<result property="laborCost" column="labor_cost"/>
|
||||
<result property="remark" column="remark"/>
|
||||
|
||||
<!-- ③ ▶︎ 项目维度汇总列表 -->
|
||||
<collection property="projectList"
|
||||
ofType="com.ruoyi.oa.domain.vo.ProjectAttendanceSummaryVo"
|
||||
javaType="list">
|
||||
<result property="projectId" column="project_id"/>
|
||||
<result property="projectName" column="project_name"/>
|
||||
<result property="color" column="color"/>
|
||||
<result property="workTimes" column="work_times"/>
|
||||
<result property="hourWorkTimes" column="hour_work_times"/>
|
||||
<result property="overTime" column="over_time"/>
|
||||
<result property="tripDays" column="trip_days"/>
|
||||
</collection>
|
||||
</resultMap>
|
||||
|
||||
<!-- ========= 项目维度汇总查询 ========= -->
|
||||
<select id="selectVoByIdPlus"
|
||||
parameterType="Long"
|
||||
resultMap="OaAttendanceRecordResult">
|
||||
|
||||
SELECT r.record_id,
|
||||
r.user_id,
|
||||
r.relation_month,
|
||||
r.calc_time,
|
||||
r.nick_name,
|
||||
u.labor_cost,
|
||||
r.trips,
|
||||
r.not_num,
|
||||
r.works,
|
||||
r.project_ids,
|
||||
r.over_num,
|
||||
r.remark,
|
||||
|
||||
p.project_id,
|
||||
p.project_name,
|
||||
p.color,
|
||||
|
||||
IFNULL(m.work_times, 0) AS work_times,
|
||||
IFNULL(m.hour_work_times, 0) AS hour_work_times,
|
||||
IFNULL(m.over_time, 0) AS over_time,
|
||||
IFNULL(m.trip_days, 0) AS trip_days
|
||||
|
||||
FROM oa_attendance_record r
|
||||
|
||||
LEFT JOIN sys_user u
|
||||
ON u.user_id = r.user_id
|
||||
|
||||
LEFT JOIN sys_oa_project p
|
||||
ON FIND_IN_SET(p.project_id, r.project_ids)
|
||||
|
||||
LEFT JOIN (SELECT user_id,
|
||||
project_id,
|
||||
DATE_FORMAT(create_time, '%Y-%m') AS relation_month,
|
||||
|
||||
COUNT(CASE WHEN project_id != 0 and project_id != 1 THEN 1 END) AS work_times,
|
||||
|
||||
SUM(CASE
|
||||
WHEN project_id != 0
|
||||
THEN IFNULL(hour, 0) + day_length * 8
|
||||
ELSE 0 END) AS hour_work_times,
|
||||
|
||||
SUM(CASE
|
||||
WHEN IFNULL(hour, 0) > 0
|
||||
THEN (IFNULL(hour, 0)) - 8
|
||||
ELSE 0 END) AS over_time,
|
||||
|
||||
SUM(CASE
|
||||
WHEN project_id = 1
|
||||
THEN day_length
|
||||
ELSE 0 END) AS trip_days
|
||||
FROM sys_oa_attendance
|
||||
WHERE del_flag = 0
|
||||
GROUP BY user_id, project_id, relation_month) m
|
||||
ON m.user_id = r.user_id
|
||||
AND m.project_id = p.project_id
|
||||
AND m.relation_month =DATE_FORMAT( r.relation_month , '%Y-%m')
|
||||
|
||||
WHERE r.del_flag = 0
|
||||
AND r.record_id = #{recordId}
|
||||
</select>
|
||||
|
||||
<select id="listGenDate" resultType="java.lang.String">
|
||||
select distinct calc_time
|
||||
from oa_attendance_record
|
||||
where YEAR(relation_month) = YEAR(#{date})
|
||||
and MONTH(relation_month) = month(#{date})
|
||||
and del_flag = 0
|
||||
</select>
|
||||
|
||||
<select id="listCommonDateRecord" resultType="Long">
|
||||
select record_id
|
||||
from oa_attendance_record
|
||||
where YEAR(calc_time) = YEAR(#{date})
|
||||
and MONTH(calc_time) = month(#{date})
|
||||
and DAY(calc_time) = DAY(#{date})
|
||||
and YEAR(relation_month) = YEAR(#{firstDay})
|
||||
and MONTH(relation_month) = month(#{firstDay})
|
||||
and del_flag = 0
|
||||
</select>
|
||||
|
||||
|
||||
|
||||
</mapper>
|
||||
@@ -5,7 +5,7 @@
|
||||
<mapper namespace="com.ruoyi.oa.mapper.OaReportDetailMapper">
|
||||
|
||||
<resultMap type="com.ruoyi.oa.domain.OaReportDetail" id="OaReportDetailResult">
|
||||
<result property="id" column="id"/>
|
||||
<result property="detailId" column="detail_id"/>
|
||||
<result property="summaryId" column="summary_id"/>
|
||||
<result property="deviceCode" column="device_code"/>
|
||||
<result property="category" column="category"/>
|
||||
@@ -19,6 +19,29 @@
|
||||
<result property="delFlag" column="del_flag"/>
|
||||
<result property="remark" column="remark"/>
|
||||
</resultMap>
|
||||
<select id="selectVoByIdPlus" parameterType="Long" resultType="com.ruoyi.oa.domain.vo.OaReportDetailVo">
|
||||
select ord.detail_id,
|
||||
summary_id,
|
||||
device_code,
|
||||
category,
|
||||
device_description,
|
||||
report_detail,
|
||||
oss_ids,
|
||||
create_by,
|
||||
create_time,
|
||||
update_by,
|
||||
update_time,
|
||||
del_flag,
|
||||
remark,
|
||||
(
|
||||
SELECT GROUP_CONCAT(so.url SEPARATOR ',')
|
||||
FROM sys_oss so
|
||||
WHERE FIND_IN_SET(so.oss_id, ord.oss_ids) > 0
|
||||
) AS images
|
||||
from oa_report_detail ord
|
||||
where ord.detail_id = #{id}
|
||||
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<mapper namespace="com.ruoyi.oa.mapper.OaReportSummaryMapper">
|
||||
|
||||
<resultMap type="com.ruoyi.oa.domain.OaReportSummary" id="OaReportSummaryResult">
|
||||
<result property="id" column="id"/>
|
||||
<result property="summaryId" column="summary_id"/>
|
||||
<result property="reportTitle" column="report_title"/>
|
||||
<result property="reportDate" column="report_date"/>
|
||||
<result property="reporter" column="reporter"/>
|
||||
@@ -16,11 +16,12 @@
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="delFlag" column="del_flag"/>
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="type" column="type"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectVoPageWithProject" resultType="com.ruoyi.oa.domain.vo.OaReportSummaryVo">
|
||||
SELECT
|
||||
s.id,
|
||||
s.summary_id as summaryId,
|
||||
s.report_title AS reportTitle,
|
||||
s.report_date AS reportDate,
|
||||
s.reporter,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?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">
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.oa.mapper.SysOaAttendanceMapper">
|
||||
|
||||
<resultMap type="com.ruoyi.oa.domain.vo.SysOaAttendanceVo" id="SysOaAttendanceResult">
|
||||
@@ -110,16 +110,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
ANY_VALUE(remark) AS remark,
|
||||
ANY_VALUE(del_flag) AS del_flag,
|
||||
COUNT(id) AS count,
|
||||
|
||||
/*
|
||||
1)如果这条记录是按天统计 (day_length>0),就直接用 day_length。
|
||||
2)如果这条记录是按小时统计 (hour>0),那么就算作 1 天。
|
||||
这样就不会把多日的小时相加再去整除 8。
|
||||
*/
|
||||
SUM(
|
||||
CASE
|
||||
WHEN day_length > 0 THEN day_length
|
||||
WHEN hour > 0 THEN ROUND(hour / 8, 1)
|
||||
WHEN day_length > 0 THEN 1
|
||||
WHEN hour > 0 THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
) AS work_times,
|
||||
@@ -130,20 +124,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
ELSE 0
|
||||
END
|
||||
) AS hour_work_times,
|
||||
/*
|
||||
overTime:如果是按小时统计,且 hour>8,才有加班 = (hour - 8)。
|
||||
如果是 day_length 统计,则一般不会再去算小时加班(你如果有需要,也可以自己按其它规则)。
|
||||
*/
|
||||
|
||||
SUM(
|
||||
IF(hour > 8, hour - 8, 0)
|
||||
) AS overTime,
|
||||
|
||||
/* ---------- 出差天数 (project_id = 0) ---------- */
|
||||
SUM(
|
||||
IF(project_id = 0, 1, 0)
|
||||
) AS tripDays,
|
||||
|
||||
/* ---------- 请假天数 (project_id = 1) ---------- */
|
||||
SUM(
|
||||
IF(project_id = 1, 1, 0)
|
||||
) AS absenceDays
|
||||
@@ -166,10 +153,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
soa.id,soa.attendance_day,soa.project_id,soa.day_length,soa.hour,
|
||||
color,
|
||||
sop.project_name, sop.project_num, sop.project_type, sop.address, sop.funds, sop.functionary, sop.begin_time,
|
||||
sop.finish_time, sop.delivery, sop.guarantee, sop.introduction, sop.project_grade, sop.project_status, sop.contract_id, sop.invoice_name,
|
||||
sop.invoice_number, sop.invoice_address, sop.invoice_bank, sop.accessory, sop.bail,sop.is_postpone, sop.postpone_reason,sop.postpone_time
|
||||
sop.finish_time, sop.delivery, sop.guarantee, sop.introduction, sop.project_grade, sop.project_status,
|
||||
sop.contract_id, sop.invoice_name,
|
||||
sop.invoice_number, sop.invoice_address, sop.invoice_bank, sop.accessory, sop.bail,sop.is_postpone,
|
||||
sop.postpone_reason,sop.postpone_time
|
||||
FROM sys_user su
|
||||
left join sys_oa_attendance soa on (su.user_id = soa.user_id and (soa.create_time BETWEEN #{firstDay} AND #{lastDay}))
|
||||
left join sys_oa_attendance soa on (su.user_id = soa.user_id and (soa.create_time BETWEEN #{firstDay} AND
|
||||
#{lastDay}))
|
||||
left join sys_oa_project sop on soa.project_id = sop.project_id
|
||||
WHERE su.user_id IN
|
||||
<foreach item="userId" index="index" collection="userIds"
|
||||
@@ -181,7 +171,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
|
||||
<select id="queryListByTime" resultMap="SysOaAttendanceResult">
|
||||
SELECT id, user_id, attendance_day, project_id, day_length, hour, create_time, create_by, update_time, update_by, remark, del_flag
|
||||
SELECT id,
|
||||
user_id,
|
||||
attendance_day,
|
||||
project_id,
|
||||
day_length,
|
||||
hour,
|
||||
create_time,
|
||||
create_by,
|
||||
update_time,
|
||||
update_by,
|
||||
remark,
|
||||
del_flag
|
||||
FROM sys_oa_attendance
|
||||
WHERE create_time BETWEEN #{startTime} AND #{endTime}
|
||||
AND user_id = #{userId}
|
||||
@@ -190,18 +191,143 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
|
||||
<delete id="delOaAttendanceAll">
|
||||
delete from sys_oa_attendance where
|
||||
attendance_day = #{day}
|
||||
and #{lastDay} > create_time
|
||||
and create_time > #{firstDay}
|
||||
delete
|
||||
from sys_oa_attendance
|
||||
where attendance_day = #{day}
|
||||
and #{lastDay} > create_time
|
||||
and create_time > #{firstDay}
|
||||
</delete>
|
||||
|
||||
|
||||
|
||||
<select id="getAttendanceDay" resultType="java.lang.Double">
|
||||
select sum(day_length)
|
||||
from sys_oa_attendance
|
||||
where user_id = #{userId} and project_id = #{projectId} and del_flag = '0'
|
||||
select sum(day_length)
|
||||
from sys_oa_attendance
|
||||
where user_id = #{userId}
|
||||
and project_id = #{projectId}
|
||||
and del_flag = '0'
|
||||
</select>
|
||||
<select id="selectNowMonthUserId" resultType="java.lang.Long">
|
||||
select distinct user_id
|
||||
from sys_oa_attendance
|
||||
where YEAR(create_time) = YEAR(#{firstDay})
|
||||
and MONTH(create_time) = MONTH(#{firstDay})
|
||||
</select>
|
||||
|
||||
|
||||
<!-- 结果映射 -->
|
||||
<resultMap id="AttendanceMonthlyCountMap" type="com.ruoyi.oa.domain.vo.AttendanceMonthlyCount">
|
||||
<result column="month" property="month"/>
|
||||
<result column="attendance_count" property="attendanceCount"/>
|
||||
<result column="leave_count" property="leaveCount"/>
|
||||
</resultMap>
|
||||
|
||||
|
||||
<select id="selectLastSixMonthsByMonth"
|
||||
resultMap="AttendanceMonthlyCountMap">
|
||||
SELECT DATE_FORMAT(create_time, '%Y-%m') AS month,
|
||||
SUM(CASE WHEN project_id != 1 THEN 1 ELSE 0 END) AS attendance_count,
|
||||
SUM(CASE WHEN project_id = 1 THEN 1 ELSE 0 END) AS leave_count
|
||||
FROM sys_oa_attendance
|
||||
WHERE create_time >= DATE_FORMAT(DATE_SUB(#{refDate}, INTERVAL 6 MONTH), '%Y-%m-01')
|
||||
AND IF(DATE_FORMAT(#{refDate}, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m'), NOW(),
|
||||
TIMESTAMP(LAST_DAY(DATE_SUB(#{refDate}, INTERVAL 1 MONTH)), '23:59:59'))
|
||||
>= create_time
|
||||
AND del_flag = 0
|
||||
GROUP BY month
|
||||
ORDER BY month;
|
||||
</select>
|
||||
<select id="selectAttendanceMonthlyCountByMonth"
|
||||
resultType="com.ruoyi.oa.domain.vo.AttendanceMonthlyCount">
|
||||
SELECT
|
||||
-- 1) project_id = 0 : 出勤 / 出差工时(天长 * 8 + 小时)
|
||||
SUM(
|
||||
IF(project_id != 1 and project_id != 0, IFNULL(day_length, 0) * 8 -- day_length(天)换算成小时
|
||||
+ IFNULL(hour, 0), 0)
|
||||
) AS workHours,
|
||||
SUM(
|
||||
IF(project_id = 0,8,0)
|
||||
) AS tripHours,
|
||||
-- 2) project_id = 1 : 请假工时(每条记录按 8 小时计)
|
||||
SUM(
|
||||
IF(project_id = 1, 8, 0)
|
||||
) AS leaveHours,
|
||||
-- 3) 加班工时:project_id = 0 情况下,hour 字段超出 8 小时的部分求和
|
||||
SUM(
|
||||
IF(project_id != 1, GREATEST(IFNULL(hour, 0) - 8, 0), 0)
|
||||
) AS overtimeHours
|
||||
FROM sys_oa_attendance
|
||||
WHERE del_flag = 0
|
||||
AND YEAR(create_time) = YEAR(#{refDate})
|
||||
and MONTH(create_time) = MONTH(#{refDate})
|
||||
</select>
|
||||
|
||||
|
||||
<select id="selectMonthlyCounts" resultType="com.ruoyi.oa.domain.vo.AttendanceMonthlyCount">
|
||||
SELECT m.month,
|
||||
|
||||
ROUND(
|
||||
COUNT(
|
||||
DISTINCT CASE
|
||||
WHEN a.project_id NOT IN (0, 1)
|
||||
THEN CONCAT(a.user_id, '_', DATE(a.create_time))
|
||||
END
|
||||
)
|
||||
/
|
||||
NULLIF(
|
||||
COUNT(
|
||||
DISTINCT CASE
|
||||
WHEN a.project_id != 0
|
||||
THEN a.user_id
|
||||
END
|
||||
)
|
||||
*
|
||||
COUNT(
|
||||
DISTINCT CASE
|
||||
WHEN a.project_id != 0
|
||||
THEN DATE(a.create_time)
|
||||
END
|
||||
),
|
||||
0
|
||||
),
|
||||
4
|
||||
) AS attendanceRate,
|
||||
|
||||
SUM(CASE WHEN a.project_id = 0 THEN 1 ELSE 0 END) AS tripCount,
|
||||
|
||||
COUNT(CASE WHEN a.project_id = 1 THEN 1 END) AS leavePeople,
|
||||
|
||||
SUM(CASE
|
||||
WHEN a.project_id NOT IN (0, 1)
|
||||
AND IFNULL(a.hour, 0) > 8
|
||||
THEN IFNULL(a.hour, 0) - 8
|
||||
ELSE 0
|
||||
END) AS overtimeHours
|
||||
|
||||
FROM (SELECT DATE_FORMAT(#{refDate}, '%Y-%m') AS month,
|
||||
LAST_DAY(#{refDate}) AS last_day,
|
||||
CASE
|
||||
WHEN DATE_FORMAT(#{refDate}, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
|
||||
THEN DAY(#{refDate}) -- 本月:已过天数
|
||||
ELSE DAY(LAST_DAY(#{refDate})) -- 历史月:整月天数
|
||||
END AS days_so_far
|
||||
UNION ALL
|
||||
SELECT DATE_FORMAT(DATE_SUB(#{refDate}, INTERVAL 1 MONTH), '%Y-%m'),
|
||||
LAST_DAY(DATE_SUB(#{refDate}, INTERVAL 1 MONTH)),
|
||||
DAY(LAST_DAY(DATE_SUB(#{refDate}, INTERVAL 1 MONTH)))) m
|
||||
|
||||
LEFT JOIN sys_oa_attendance a
|
||||
ON a.del_flag = 0
|
||||
AND DATE_FORMAT(a.create_time, '%Y-%m') = m.month
|
||||
AND a.create_time <=
|
||||
CASE
|
||||
WHEN m.month = DATE_FORMAT(CURDATE(), '%Y-%m')
|
||||
THEN #{refDate}
|
||||
ELSE TIMESTAMP(m.last_day, '23:59:59')
|
||||
END
|
||||
|
||||
GROUP BY m.month
|
||||
ORDER BY m.month DESC; -- 本月在前,上月在后
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user