Merge remote-tracking branch 'origin/lcj' into lcj
This commit is contained in:
		@ -11,12 +11,13 @@ import com.itextpdf.text.Image;
 | 
			
		||||
import com.itextpdf.text.pdf.PdfContentByte;
 | 
			
		||||
import com.itextpdf.text.pdf.PdfReader;
 | 
			
		||||
import com.itextpdf.text.pdf.PdfStamper;
 | 
			
		||||
import org.dromara.system.domain.vo.SysOssVo;
 | 
			
		||||
 | 
			
		||||
import java.awt.image.BufferedImage;
 | 
			
		||||
import java.io.ByteArrayOutputStream;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import java.net.FileNameMap;
 | 
			
		||||
import java.net.URLConnection;
 | 
			
		||||
import java.util.concurrent.CompletableFuture;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author lilemy
 | 
			
		||||
@ -121,22 +122,145 @@ public class PdfBoxQrCodeGenerator {
 | 
			
		||||
     * @param y           坐标
 | 
			
		||||
     * @return 插入二维码后的PDF文件流
 | 
			
		||||
     */
 | 
			
		||||
    public static ByteArrayOutputStream addQRCodeToPDF(String srcPdf, byte[] qrCodeBytes, int pageNum, float x, float y) throws IOException, DocumentException {
 | 
			
		||||
//    public static ByteArrayOutputStream addQRCodeToPDF(String srcPdf, byte[] qrCodeBytes, int pageNum, float x, float y) throws IOException, DocumentException {
 | 
			
		||||
//
 | 
			
		||||
//        PdfReader reader = new PdfReader(srcPdf);
 | 
			
		||||
//        ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();
 | 
			
		||||
//        PdfStamper stamper = new PdfStamper(reader, pdfOut);
 | 
			
		||||
//
 | 
			
		||||
//        PdfContentByte content = stamper.getOverContent(pageNum);
 | 
			
		||||
//        Image image = Image.getInstance(qrCodeBytes);
 | 
			
		||||
//        image.setAbsolutePosition(x, y); // 坐标:左下角为原点
 | 
			
		||||
//        image.scaleAbsolute(100, 100); // 设置二维码大小
 | 
			
		||||
//
 | 
			
		||||
//        content.addImage(image);
 | 
			
		||||
//        stamper.close();
 | 
			
		||||
//        reader.close();
 | 
			
		||||
//
 | 
			
		||||
//        return pdfOut;
 | 
			
		||||
//    }
 | 
			
		||||
    /**
 | 
			
		||||
     * 在PDF每一页的指定位置添加二维码并返回数据流(根据页面方向自动调整位置)
 | 
			
		||||
     *
 | 
			
		||||
     * @param srcPdf      原PDF文件路径(可以是本地路径或网络地址)
 | 
			
		||||
     * @param qrCodeBytes 二维码图片字节数组
 | 
			
		||||
     * @param x           X坐标(默认位置)
 | 
			
		||||
     * @param y           Y坐标(默认位置)
 | 
			
		||||
     * @return 插入二维码后的PDF文件流
 | 
			
		||||
     */
 | 
			
		||||
    public static ByteArrayOutputStream addQRCodeToPDFOnAllPages(String srcPdf, byte[] qrCodeBytes, float x, float y)
 | 
			
		||||
        throws IOException, DocumentException {
 | 
			
		||||
 | 
			
		||||
        PdfReader reader = new PdfReader(srcPdf);
 | 
			
		||||
        PdfReader reader = null;
 | 
			
		||||
        PdfStamper stamper = null;
 | 
			
		||||
        ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();
 | 
			
		||||
        PdfStamper stamper = new PdfStamper(reader, pdfOut);
 | 
			
		||||
 | 
			
		||||
        PdfContentByte content = stamper.getOverContent(pageNum);
 | 
			
		||||
        Image image = Image.getInstance(qrCodeBytes);
 | 
			
		||||
        image.setAbsolutePosition(x, y); // 坐标:左下角为原点
 | 
			
		||||
        image.scaleAbsolute(100, 100); // 设置二维码大小
 | 
			
		||||
        try {
 | 
			
		||||
            // 判断是网络地址还是本地文件路径
 | 
			
		||||
            if (srcPdf.startsWith("http://") || srcPdf.startsWith("https://")) {
 | 
			
		||||
                // 网络地址:从URL读取PDF
 | 
			
		||||
                java.net.URL url = new java.net.URL(srcPdf);
 | 
			
		||||
                java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
 | 
			
		||||
                connection.setConnectTimeout(10000); // 连接超时10秒
 | 
			
		||||
                connection.setReadTimeout(30000);    // 读取超时30秒
 | 
			
		||||
                connection.setRequestMethod("GET");
 | 
			
		||||
 | 
			
		||||
        content.addImage(image);
 | 
			
		||||
        stamper.close();
 | 
			
		||||
        reader.close();
 | 
			
		||||
                int responseCode = connection.getResponseCode();
 | 
			
		||||
                if (responseCode != java.net.HttpURLConnection.HTTP_OK) {
 | 
			
		||||
                    throw new IOException("无法从URL获取PDF文件,HTTP响应码: " + responseCode + ", URL: " + srcPdf);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                java.io.InputStream inputStream = connection.getInputStream();
 | 
			
		||||
                reader = new PdfReader(inputStream);
 | 
			
		||||
            } else {
 | 
			
		||||
                // 本地文件路径:检查文件是否存在
 | 
			
		||||
                File srcFile = new File(srcPdf);
 | 
			
		||||
                if (!srcFile.exists()) {
 | 
			
		||||
                    throw new IOException("源PDF文件不存在: " + srcPdf);
 | 
			
		||||
                }
 | 
			
		||||
                reader = new PdfReader(srcPdf);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            stamper = new PdfStamper(reader, pdfOut);
 | 
			
		||||
 | 
			
		||||
            int numberOfPages = reader.getNumberOfPages();
 | 
			
		||||
 | 
			
		||||
            // 遍历每一页并添加二维码
 | 
			
		||||
            for (int pageNum = 1; pageNum <= numberOfPages; pageNum++) {
 | 
			
		||||
                // 获取页面尺寸
 | 
			
		||||
                com.itextpdf.text.Rectangle pageSize = reader.getPageSize(pageNum);
 | 
			
		||||
                float pageWidth = pageSize.getWidth();
 | 
			
		||||
                float pageHeight = pageSize.getHeight();
 | 
			
		||||
 | 
			
		||||
                // 根据页面方向确定二维码位置
 | 
			
		||||
                float qrX, qrY;
 | 
			
		||||
 | 
			
		||||
                float newWidth, newHeight;
 | 
			
		||||
 | 
			
		||||
                // 判断页面方向:宽度大于高度为横版,否则为竖版
 | 
			
		||||
                if (pageWidth > pageHeight) {
 | 
			
		||||
                    // 横版页面:二维码放在右下角
 | 
			
		||||
                    qrX = (pageWidth - 90); // 距离右边90点
 | 
			
		||||
                    qrY = 24;                       // 距离底部24点
 | 
			
		||||
                    newWidth = 67;
 | 
			
		||||
                    newHeight = 79;
 | 
			
		||||
                } else {
 | 
			
		||||
                    // 竖版页面:二维码放在左上角
 | 
			
		||||
                    qrX = 226;                      // 距离左边226点
 | 
			
		||||
                    qrY = pageHeight - 185;         // 距离顶部185点
 | 
			
		||||
                    newWidth = 69;
 | 
			
		||||
                    newHeight = 80;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                PdfContentByte content = stamper.getOverContent(pageNum);
 | 
			
		||||
                Image image = Image.getInstance(qrCodeBytes);
 | 
			
		||||
                image.setAbsolutePosition(qrX, qrY);    // 坐标:左下角为原点
 | 
			
		||||
                image.scaleAbsolute(newWidth, newHeight); // 设置二维码大小
 | 
			
		||||
                content.addImage(image);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } finally {
 | 
			
		||||
            if (stamper != null) {
 | 
			
		||||
                try {
 | 
			
		||||
                    stamper.close();
 | 
			
		||||
                } catch (Exception e) {
 | 
			
		||||
                    // 忽略关闭异常
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (reader != null) {
 | 
			
		||||
                try {
 | 
			
		||||
                    reader.close();
 | 
			
		||||
                } catch (Exception e) {
 | 
			
		||||
                    // 忽略关闭异常
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return pdfOut;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//    public static void main(String[] args) {
 | 
			
		||||
//        String path = "C:\\Users\\YuanJie\\Desktop\\test.pdf";
 | 
			
		||||
//        String outputPath = "C:\\Users\\YuanJie\\Desktop\\test1.pdf";
 | 
			
		||||
//
 | 
			
		||||
//        String params = "ID:[" + 11111 + "] finish";
 | 
			
		||||
//        byte[] bytes = PdfBoxQrCodeGenerator.generateQRCodeBytes(params);
 | 
			
		||||
//
 | 
			
		||||
//        try {
 | 
			
		||||
//            System.out.println("二维码字节大小: " + bytes.length + " 字节");
 | 
			
		||||
//
 | 
			
		||||
//            // 在每一页添加二维码
 | 
			
		||||
//            PdfBoxQrCodeGenerator.addQRCodeToPDFOnAllPages(path, outputPath, bytes, 450, 700);
 | 
			
		||||
//
 | 
			
		||||
//            System.out.println("PDF文件已成功生成到: " + outputPath);
 | 
			
		||||
//            System.out.println("生成的PDF大小: " + new File(outputPath).length() + " 字节");
 | 
			
		||||
//
 | 
			
		||||
//        } catch (Exception e) {
 | 
			
		||||
//            e.printStackTrace();
 | 
			
		||||
//            System.out.println("图纸管理 => 审核结束,向文件添加二维码失败, 错误");
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -384,7 +384,7 @@ public class DesDrawingServiceImpl extends ServiceImpl<DesDrawingMapper, DesDraw
 | 
			
		||||
        String params = "ID:[" + drawing.getId() + "] finish";
 | 
			
		||||
        byte[] bytes = PdfBoxQrCodeGenerator.generateQRCodeBytes(params);
 | 
			
		||||
        try {
 | 
			
		||||
            ByteArrayOutputStream baos = PdfBoxQrCodeGenerator.addQRCodeToPDF(ossVo.getUrl(), bytes, 1, 1510, 900);
 | 
			
		||||
            ByteArrayOutputStream baos = PdfBoxQrCodeGenerator.addQRCodeToPDFOnAllPages(ossVo.getUrl(), bytes,1510, 900);
 | 
			
		||||
            FileNameMap fileNameMap = URLConnection.getFileNameMap();
 | 
			
		||||
            String originalName = drawing.getOriginalName();
 | 
			
		||||
            String contentType = fileNameMap.getContentTypeFor(originalName);
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,7 @@ import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.dromara.common.core.exception.ServiceException;
 | 
			
		||||
import org.dromara.common.core.utils.DateUtils;
 | 
			
		||||
import org.dromara.contractor.domain.SubConstructionUser;
 | 
			
		||||
import org.dromara.contractor.service.ISubConstructionUserService;
 | 
			
		||||
import org.dromara.project.constant.BusProjectConstant;
 | 
			
		||||
import org.dromara.project.domain.BusAttendance;
 | 
			
		||||
import org.dromara.project.domain.BusAttendanceRule;
 | 
			
		||||
@ -16,10 +17,7 @@ import org.dromara.project.domain.BusProject;
 | 
			
		||||
import org.dromara.project.domain.BusUserProjectRelevancy;
 | 
			
		||||
import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum;
 | 
			
		||||
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
 | 
			
		||||
import org.dromara.project.service.IBusAttendanceRuleService;
 | 
			
		||||
import org.dromara.project.service.IBusAttendanceService;
 | 
			
		||||
import org.dromara.project.service.IBusProjectService;
 | 
			
		||||
import org.dromara.project.service.IBusUserProjectRelevancyService;
 | 
			
		||||
import org.dromara.project.service.*;
 | 
			
		||||
import org.springframework.data.redis.core.Cursor;
 | 
			
		||||
import org.springframework.data.redis.core.ScanOptions;
 | 
			
		||||
import org.springframework.data.redis.core.StringRedisTemplate;
 | 
			
		||||
@ -48,9 +46,16 @@ public class AttendanceJob {
 | 
			
		||||
    @Resource
 | 
			
		||||
    private IBusProjectService projectService;
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private IBusLeaveService leaveService;
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private ISubConstructionUserService constructionUserService;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//    @Scheduled(cron = "0 0/10 * * * ?")
 | 
			
		||||
    public void clockInMiss() {
 | 
			
		||||
 | 
			
		||||
        log.info("执行定时任务:上班缺卡记录生成");
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
@ -76,6 +81,10 @@ public class AttendanceJob {
 | 
			
		||||
 | 
			
		||||
            //获取当前日期
 | 
			
		||||
            LocalDate date = LocalDate.now();
 | 
			
		||||
 | 
			
		||||
            //管理员关联多个项目,需要记录是否已生成缺卡记录
 | 
			
		||||
            HashSet<Long> manageUserIds = new HashSet<>();
 | 
			
		||||
 | 
			
		||||
            List<BusAttendance> missList = new ArrayList<>();
 | 
			
		||||
            for (BusAttendanceRule rule : list) {
 | 
			
		||||
                LocalTime clockInTime = rule.getClockInTime();
 | 
			
		||||
@ -115,16 +124,30 @@ public class AttendanceJob {
 | 
			
		||||
 | 
			
		||||
                for (BusUserProjectRelevancy relevancy : relevancyList) {
 | 
			
		||||
 | 
			
		||||
                    if (attendanceUserIds.contains(relevancy.getUserId())) {
 | 
			
		||||
                    if (attendanceUserIds.contains(relevancy.getUserId()) || "0".equals(relevancy.getUserType())) {
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                    BusAttendance busAttendance = new BusAttendance();
 | 
			
		||||
                    //todo: 管理人员 项目id是0
 | 
			
		||||
                    busAttendance.setProjectId(relevancy.getProjectId());
 | 
			
		||||
                    // 管理人员 项目id是0
 | 
			
		||||
                    if("2".equals(relevancy.getUserType()) && !manageUserIds.contains(relevancy.getUserId())){
 | 
			
		||||
                        manageUserIds.add(relevancy.getUserId());
 | 
			
		||||
                        busAttendance.setProjectId(0L);
 | 
			
		||||
                    }
 | 
			
		||||
                    SubConstructionUser constructionUser = constructionUserService.getBySysUserId(relevancy.getUserId());
 | 
			
		||||
 | 
			
		||||
                    busAttendance.setUserId(relevancy.getUserId());
 | 
			
		||||
                    busAttendance.setUserName(constructionUser.getUserName());
 | 
			
		||||
 | 
			
		||||
                    busAttendance.setClockDate(date);
 | 
			
		||||
                    busAttendance.setClockType(BusAttendanceCommuterEnum.CLOCKIN.getValue());
 | 
			
		||||
                    busAttendance.setClockStatus(BusAttendanceClockStatusEnum.UNCLOCK.getValue());
 | 
			
		||||
                    if(leaveService.isLeave(date, relevancy.getUserId())){
 | 
			
		||||
                        busAttendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue());
 | 
			
		||||
                    }else {
 | 
			
		||||
                        busAttendance.setClockStatus(BusAttendanceClockStatusEnum.UNCLOCK.getValue());
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    missList.add(busAttendance);
 | 
			
		||||
                }
 | 
			
		||||
@ -156,18 +179,22 @@ public class AttendanceJob {
 | 
			
		||||
            if (start.isAfter(end)) {
 | 
			
		||||
                // 跨天情况:查询时间 >= start OR 时间 < end
 | 
			
		||||
                list = attendanceRuleService.list(Wrappers.<BusAttendanceRule>lambdaQuery()
 | 
			
		||||
                    .and(wrapper -> wrapper.ge(BusAttendanceRule::getClockInResultTime, start)
 | 
			
		||||
                    .and(wrapper -> wrapper.ge(BusAttendanceRule::getClockOutResultTime, start)
 | 
			
		||||
                        .or()
 | 
			
		||||
                        .lt(BusAttendanceRule::getClockOutResultTime, end)));
 | 
			
		||||
            } else {
 | 
			
		||||
                // 非跨天情况:查询时间 >= start AND 时间 < end
 | 
			
		||||
                list = attendanceRuleService.list(Wrappers.<BusAttendanceRule>lambdaQuery()
 | 
			
		||||
                    .ge(BusAttendanceRule::getClockInResultTime, start)
 | 
			
		||||
                    .lt(BusAttendanceRule::getClockInResultTime, end));
 | 
			
		||||
                    .ge(BusAttendanceRule::getClockOutResultTime, start)
 | 
			
		||||
                    .lt(BusAttendanceRule::getClockOutResultTime, end));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //获取当前日期
 | 
			
		||||
            LocalDate date = LocalDate.now();
 | 
			
		||||
 | 
			
		||||
            //管理员关联多个项目,需要记录是否已生成缺卡记录
 | 
			
		||||
            HashSet<Long> manageUserIds = new HashSet<>();
 | 
			
		||||
 | 
			
		||||
            List<BusAttendance> missList = new ArrayList<>();
 | 
			
		||||
            for (BusAttendanceRule rule : list) {
 | 
			
		||||
 | 
			
		||||
@ -209,17 +236,29 @@ public class AttendanceJob {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                for (BusUserProjectRelevancy relevancy : relevancyList) {
 | 
			
		||||
 | 
			
		||||
                    if (attendanceUserIds.contains(relevancy.getUserId())) {
 | 
			
		||||
                    if (attendanceUserIds.contains(relevancy.getUserId()) || "0".equals(relevancy.getUserType())) {
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                    BusAttendance busAttendance = new BusAttendance();
 | 
			
		||||
                    //todo: 管理人员 项目id是0
 | 
			
		||||
                    // 管理人员 项目id是0
 | 
			
		||||
                    busAttendance.setProjectId(relevancy.getProjectId());
 | 
			
		||||
                    if("2".equals(relevancy.getUserType()) && !manageUserIds.contains(relevancy.getUserId())){
 | 
			
		||||
                        manageUserIds.add(relevancy.getUserId());
 | 
			
		||||
                        busAttendance.setProjectId(0L);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    SubConstructionUser constructionUser = constructionUserService.getBySysUserId(relevancy.getUserId());
 | 
			
		||||
 | 
			
		||||
                    busAttendance.setUserId(relevancy.getUserId());
 | 
			
		||||
                    busAttendance.setUserName(constructionUser.getUserName());
 | 
			
		||||
 | 
			
		||||
                    busAttendance.setClockDate(date);
 | 
			
		||||
                    busAttendance.setClockType(BusAttendanceCommuterEnum.CLOCKOUT.getValue());
 | 
			
		||||
                    busAttendance.setClockStatus(BusAttendanceClockStatusEnum.UNCLOCK.getValue());
 | 
			
		||||
                    if(leaveService.isLeave(date, relevancy.getUserId())){
 | 
			
		||||
                        busAttendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue());
 | 
			
		||||
                    }else {
 | 
			
		||||
                        busAttendance.setClockStatus(BusAttendanceClockStatusEnum.UNCLOCK.getValue());
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    missList.add(busAttendance);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,9 @@ import org.dromara.common.mybatis.core.domain.BaseEntity;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.*;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
import java.time.LocalDate;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonFormat;
 | 
			
		||||
 | 
			
		||||
@ -52,7 +55,7 @@ public class BusLandTransferLedger extends BaseEntity {
 | 
			
		||||
    /**
 | 
			
		||||
     * 设计面积
 | 
			
		||||
     */
 | 
			
		||||
    private String designArea;
 | 
			
		||||
    private BigDecimal designArea;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 责任人
 | 
			
		||||
@ -62,32 +65,32 @@ public class BusLandTransferLedger extends BaseEntity {
 | 
			
		||||
    /**
 | 
			
		||||
     * 预计完成时间
 | 
			
		||||
     */
 | 
			
		||||
    private Date expectedFinishDate;
 | 
			
		||||
    private LocalDate expectedFinishDate;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 已流转面积
 | 
			
		||||
     */
 | 
			
		||||
    private String transferAea;
 | 
			
		||||
    private BigDecimal transferAea;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 流转比例(百分比)
 | 
			
		||||
     */
 | 
			
		||||
    private String transferRatio;
 | 
			
		||||
    private BigDecimal transferRatio;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 土地租金(元)
 | 
			
		||||
     */
 | 
			
		||||
    private Long landRent;
 | 
			
		||||
    private BigDecimal landRent;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 青苗赔偿(元)
 | 
			
		||||
     */
 | 
			
		||||
    private Long seedlingCompensation;
 | 
			
		||||
    private BigDecimal seedlingCompensation;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 总金额(元)
 | 
			
		||||
     */
 | 
			
		||||
    private Long totalAmount;
 | 
			
		||||
    private BigDecimal totalAmount;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 流转状态
 | 
			
		||||
@ -109,5 +112,24 @@ public class BusLandTransferLedger extends BaseEntity {
 | 
			
		||||
     */
 | 
			
		||||
    private String nextStrategy;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不签合同面积(亩)
 | 
			
		||||
     */
 | 
			
		||||
    private BigDecimal noContractArea;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不签合同原因
 | 
			
		||||
     */
 | 
			
		||||
    private String noContractReason;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不测量面积(亩)
 | 
			
		||||
     */
 | 
			
		||||
    private BigDecimal noSurveyArea;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不流转原因
 | 
			
		||||
     */
 | 
			
		||||
    private String nonTransferReason;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -35,7 +35,7 @@ public class BusEnterRoadBo extends BaseEntity {
 | 
			
		||||
    /**
 | 
			
		||||
     * 道路编号
 | 
			
		||||
     */
 | 
			
		||||
    @NotBlank(message = "道路编号不能为空", groups = { AddGroup.class, EditGroup.class })
 | 
			
		||||
    @NotBlank(message = "道路编号不能为空", groups = { EditGroup.class })
 | 
			
		||||
    private String roadCode;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,9 @@ import io.github.linpeilie.annotations.AutoMapper;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import jakarta.validation.constraints.*;
 | 
			
		||||
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
import java.time.LocalDate;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonFormat;
 | 
			
		||||
 | 
			
		||||
@ -53,7 +56,7 @@ public class BusLandTransferLedgerBo extends BaseEntity {
 | 
			
		||||
    /**
 | 
			
		||||
     * 设计面积
 | 
			
		||||
     */
 | 
			
		||||
    private String designArea;
 | 
			
		||||
    private BigDecimal designArea;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 责任人
 | 
			
		||||
@ -63,32 +66,32 @@ public class BusLandTransferLedgerBo extends BaseEntity {
 | 
			
		||||
    /**
 | 
			
		||||
     * 预计完成时间
 | 
			
		||||
     */
 | 
			
		||||
    private Date expectedFinishDate;
 | 
			
		||||
    private LocalDate expectedFinishDate;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 已流转面积
 | 
			
		||||
     */
 | 
			
		||||
    private String transferAea;
 | 
			
		||||
    private BigDecimal transferAea;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 流转比例(百分比)
 | 
			
		||||
     */
 | 
			
		||||
    private String transferRatio;
 | 
			
		||||
    private BigDecimal transferRatio;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 土地租金(元)
 | 
			
		||||
     */
 | 
			
		||||
    private Long landRent;
 | 
			
		||||
    private BigDecimal landRent;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 青苗赔偿(元)
 | 
			
		||||
     */
 | 
			
		||||
    private Long seedlingCompensation;
 | 
			
		||||
    private BigDecimal seedlingCompensation;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 总金额(元)
 | 
			
		||||
     */
 | 
			
		||||
    private Long totalAmount;
 | 
			
		||||
    private BigDecimal totalAmount;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 流转状态
 | 
			
		||||
@ -110,5 +113,29 @@ public class BusLandTransferLedgerBo extends BaseEntity {
 | 
			
		||||
     */
 | 
			
		||||
    private String nextStrategy;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不签合同面积(亩)
 | 
			
		||||
     */
 | 
			
		||||
    private BigDecimal noContractArea;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不签合同原因
 | 
			
		||||
     */
 | 
			
		||||
    private String noContractReason;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不测量面积(亩)
 | 
			
		||||
     */
 | 
			
		||||
    private BigDecimal noSurveyArea;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不流转原因
 | 
			
		||||
     */
 | 
			
		||||
    private String nonTransferReason;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 列表类型 1-流转 2-不流转
 | 
			
		||||
     */
 | 
			
		||||
    private String listType;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -6,11 +6,15 @@ import io.github.linpeilie.annotations.AutoMapper;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
 | 
			
		||||
import org.dromara.common.excel.convert.ExcelDictConvert;
 | 
			
		||||
import org.dromara.common.translation.annotation.Translation;
 | 
			
		||||
import org.dromara.common.translation.constant.TransConstant;
 | 
			
		||||
import org.dromara.land.domain.BusLandTransferLedger;
 | 
			
		||||
import org.dromara.land.domain.bo.UnitBo;
 | 
			
		||||
 | 
			
		||||
import java.io.Serial;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
import java.time.LocalDate;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@ -47,6 +51,10 @@ public class BusLandTransferLedgerVo implements Serializable {
 | 
			
		||||
    @ExcelProperty(value = "土地类型")
 | 
			
		||||
    private String landType;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty(value = "土地类型")
 | 
			
		||||
    @Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "landType",other = "land_type")
 | 
			
		||||
    private String landTypeName;
 | 
			
		||||
    /**
 | 
			
		||||
     * 地块ID
 | 
			
		||||
     */
 | 
			
		||||
@ -63,7 +71,7 @@ public class BusLandTransferLedgerVo implements Serializable {
 | 
			
		||||
     * 设计面积
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "设计面积")
 | 
			
		||||
    private String designArea;
 | 
			
		||||
    private BigDecimal designArea;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 责任人
 | 
			
		||||
@ -75,41 +83,41 @@ public class BusLandTransferLedgerVo implements Serializable {
 | 
			
		||||
     * 预计完成时间
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "预计完成时间")
 | 
			
		||||
    private Date expectedFinishDate;
 | 
			
		||||
    private LocalDate expectedFinishDate;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 已流转面积
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "已流转面积")
 | 
			
		||||
    private String transferAea;
 | 
			
		||||
    private BigDecimal transferAea;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 流转比例(百分比)
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "流转比例", converter = ExcelDictConvert.class)
 | 
			
		||||
    @ExcelDictFormat(readConverterExp = "百=分比")
 | 
			
		||||
    private String transferRatio;
 | 
			
		||||
    @ExcelDictFormat(readConverterExp = "百分比")
 | 
			
		||||
    private BigDecimal transferRatio;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 土地租金(元)
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "土地租金", converter = ExcelDictConvert.class)
 | 
			
		||||
    @ExcelDictFormat(readConverterExp = "元=")
 | 
			
		||||
    private Long landRent;
 | 
			
		||||
    @ExcelDictFormat(readConverterExp = "元")
 | 
			
		||||
    private BigDecimal landRent;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 青苗赔偿(元)
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "青苗赔偿", converter = ExcelDictConvert.class)
 | 
			
		||||
    @ExcelDictFormat(readConverterExp = "元=")
 | 
			
		||||
    private Long seedlingCompensation;
 | 
			
		||||
    @ExcelDictFormat(readConverterExp = "元")
 | 
			
		||||
    private BigDecimal seedlingCompensation;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 总金额(元)
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "总金额", converter = ExcelDictConvert.class)
 | 
			
		||||
    @ExcelDictFormat(readConverterExp = "元=")
 | 
			
		||||
    private Long totalAmount;
 | 
			
		||||
    @ExcelDictFormat(readConverterExp = "元")
 | 
			
		||||
    private BigDecimal totalAmount;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 流转状态
 | 
			
		||||
@ -117,6 +125,10 @@ public class BusLandTransferLedgerVo implements Serializable {
 | 
			
		||||
    @ExcelProperty(value = "流转状态")
 | 
			
		||||
    private String transferStatus;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty(value = "流转状态名字")
 | 
			
		||||
    @Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "transferStatus",other = "land_transfer_status")
 | 
			
		||||
    private String transferStatusName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 状态说明
 | 
			
		||||
     */
 | 
			
		||||
@ -135,6 +147,27 @@ public class BusLandTransferLedgerVo implements Serializable {
 | 
			
		||||
    @ExcelProperty(value = "下一步策略")
 | 
			
		||||
    private String nextStrategy;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不签合同面积(亩)
 | 
			
		||||
     */
 | 
			
		||||
    private BigDecimal noContractArea;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不签合同原因
 | 
			
		||||
     */
 | 
			
		||||
    private String noContractReason;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不测量面积(亩)
 | 
			
		||||
     */
 | 
			
		||||
    private BigDecimal noSurveyArea;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不流转原因
 | 
			
		||||
     */
 | 
			
		||||
    private String nonTransferReason;
 | 
			
		||||
 | 
			
		||||
    private String roadCode;
 | 
			
		||||
 | 
			
		||||
    private String roadName;
 | 
			
		||||
 | 
			
		||||
@ -96,7 +96,7 @@ public class BusEnterRoadServiceImpl implements IBusEnterRoadService {
 | 
			
		||||
    private LambdaQueryWrapper<BusEnterRoad> buildQueryWrapper(BusEnterRoadBo bo) {
 | 
			
		||||
        Map<String, Object> params = bo.getParams();
 | 
			
		||||
        LambdaQueryWrapper<BusEnterRoad> lqw = Wrappers.lambdaQuery();
 | 
			
		||||
        lqw.orderByAsc(BusEnterRoad::getId);
 | 
			
		||||
        lqw.orderByDesc(BusEnterRoad::getId);
 | 
			
		||||
        lqw.eq(bo.getProjectId() != null, BusEnterRoad::getProjectId, bo.getProjectId());
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getRoadCode()), BusEnterRoad::getRoadCode, bo.getRoadCode());
 | 
			
		||||
        lqw.like(StringUtils.isNotBlank(bo.getRoadName()), BusEnterRoad::getRoadName, bo.getRoadName());
 | 
			
		||||
 | 
			
		||||
@ -93,7 +93,7 @@ public class BusLandBlockServiceImpl implements IBusLandBlockService {
 | 
			
		||||
    private LambdaQueryWrapper<BusLandBlock> buildQueryWrapper(BusLandBlockBo bo) {
 | 
			
		||||
        Map<String, Object> params = bo.getParams();
 | 
			
		||||
        LambdaQueryWrapper<BusLandBlock> lqw = Wrappers.lambdaQuery();
 | 
			
		||||
        lqw.orderByAsc(BusLandBlock::getId);
 | 
			
		||||
        lqw.orderByDesc(BusLandBlock::getId);
 | 
			
		||||
        lqw.eq(bo.getProjectId() != null, BusLandBlock::getProjectId, bo.getProjectId());
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getLandCode()), BusLandBlock::getLandCode, bo.getLandCode());
 | 
			
		||||
        lqw.like(StringUtils.isNotBlank(bo.getLandName()), BusLandBlock::getLandName, bo.getLandName());
 | 
			
		||||
 | 
			
		||||
@ -75,7 +75,7 @@ public class BusLandBlockUnitProjectServiceImpl implements IBusLandBlockUnitProj
 | 
			
		||||
    private LambdaQueryWrapper<BusLandBlockUnitProject> buildQueryWrapper(BusLandBlockUnitProjectBo bo) {
 | 
			
		||||
        Map<String, Object> params = bo.getParams();
 | 
			
		||||
        LambdaQueryWrapper<BusLandBlockUnitProject> lqw = Wrappers.lambdaQuery();
 | 
			
		||||
        lqw.orderByAsc(BusLandBlockUnitProject::getId);
 | 
			
		||||
        lqw.orderByDesc(BusLandBlockUnitProject::getId);
 | 
			
		||||
        lqw.eq(bo.getLandBlockId() != null, BusLandBlockUnitProject::getLandBlockId, bo.getLandBlockId());
 | 
			
		||||
        lqw.eq(bo.getUnitProjectId() != null, BusLandBlockUnitProject::getUnitProjectId, bo.getUnitProjectId());
 | 
			
		||||
        lqw.like(StringUtils.isNotBlank(bo.getUnitProjectName()), BusLandBlockUnitProject::getUnitProjectName, bo.getUnitProjectName());
 | 
			
		||||
 | 
			
		||||
@ -24,10 +24,7 @@ import org.dromara.land.service.IBusLandBlockUnitProjectService;
 | 
			
		||||
import org.dromara.land.service.IBusLandTransferLedgerService;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 项目土地流转台账Service业务层处理
 | 
			
		||||
@ -142,16 +139,16 @@ public class BusLandTransferLedgerServiceImpl implements IBusLandTransferLedgerS
 | 
			
		||||
    private LambdaQueryWrapper<BusLandTransferLedger> buildQueryWrapper(BusLandTransferLedgerBo bo) {
 | 
			
		||||
        Map<String, Object> params = bo.getParams();
 | 
			
		||||
        LambdaQueryWrapper<BusLandTransferLedger> lqw = Wrappers.lambdaQuery();
 | 
			
		||||
        lqw.orderByAsc(BusLandTransferLedger::getId);
 | 
			
		||||
        lqw.orderByDesc(BusLandTransferLedger::getId);
 | 
			
		||||
        lqw.eq(bo.getProjectId() != null, BusLandTransferLedger::getProjectId, bo.getProjectId());
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getLandType()), BusLandTransferLedger::getLandType, bo.getLandType());
 | 
			
		||||
        lqw.eq(bo.getLandBlockId() != null, BusLandTransferLedger::getLandBlockId, bo.getLandBlockId());
 | 
			
		||||
        lqw.eq(bo.getEnterRoadId() != null, BusLandTransferLedger::getEnterRoadId, bo.getEnterRoadId());
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getDesignArea()), BusLandTransferLedger::getDesignArea, bo.getDesignArea());
 | 
			
		||||
        lqw.eq(bo.getDesignArea()!= null, BusLandTransferLedger::getDesignArea, bo.getDesignArea());
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getResponsiblePerson()), BusLandTransferLedger::getResponsiblePerson, bo.getResponsiblePerson());
 | 
			
		||||
        lqw.eq(bo.getExpectedFinishDate() != null, BusLandTransferLedger::getExpectedFinishDate, bo.getExpectedFinishDate());
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getTransferAea()), BusLandTransferLedger::getTransferAea, bo.getTransferAea());
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getTransferRatio()), BusLandTransferLedger::getTransferRatio, bo.getTransferRatio());
 | 
			
		||||
        lqw.eq(bo.getTransferAea()!= null, BusLandTransferLedger::getTransferAea, bo.getTransferAea());
 | 
			
		||||
        lqw.eq(bo.getTransferRatio()!= null, BusLandTransferLedger::getTransferRatio, bo.getTransferRatio());
 | 
			
		||||
        lqw.eq(bo.getLandRent() != null, BusLandTransferLedger::getLandRent, bo.getLandRent());
 | 
			
		||||
        lqw.eq(bo.getSeedlingCompensation() != null, BusLandTransferLedger::getSeedlingCompensation, bo.getSeedlingCompensation());
 | 
			
		||||
        lqw.eq(bo.getTotalAmount() != null, BusLandTransferLedger::getTotalAmount, bo.getTotalAmount());
 | 
			
		||||
@ -159,6 +156,8 @@ public class BusLandTransferLedgerServiceImpl implements IBusLandTransferLedgerS
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getStatusDescription()), BusLandTransferLedger::getStatusDescription, bo.getStatusDescription());
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getIssueSummary()), BusLandTransferLedger::getIssueSummary, bo.getIssueSummary());
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getNextStrategy()), BusLandTransferLedger::getNextStrategy, bo.getNextStrategy());
 | 
			
		||||
        lqw.in("1".equals(bo.getListType()),BusLandTransferLedger::getTransferStatus, Arrays.asList("0","1"));
 | 
			
		||||
        lqw.eq("2".equals(bo.getListType()),BusLandTransferLedger::getTransferStatus, "2");
 | 
			
		||||
        return lqw;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -106,7 +106,10 @@ public class OutTableController extends BaseController {
 | 
			
		||||
        // 方法1: 使用 YearMonth 进行比较(推荐)
 | 
			
		||||
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
 | 
			
		||||
 | 
			
		||||
        YearMonth yearMonth = YearMonth.parse(month, formatter);
 | 
			
		||||
        //当前月
 | 
			
		||||
        LocalDate now = LocalDate.now();
 | 
			
		||||
        YearMonth yearMonth = YearMonth.parse(now.format(formatter));
 | 
			
		||||
        YearMonth paramMonth = YearMonth.parse(month);
 | 
			
		||||
 | 
			
		||||
        //构建返回数据
 | 
			
		||||
        List<OutMonthlyConstructionVo> outMonthlyConstructionVos = new ArrayList<>();
 | 
			
		||||
@ -117,12 +120,12 @@ public class OutTableController extends BaseController {
 | 
			
		||||
            vo.setProjectName(busProjectVo.getProjectName());
 | 
			
		||||
 | 
			
		||||
            //1.总产值的计算  2.预计累计产值(截止当前月) 3.月预计产值
 | 
			
		||||
            List<BusProject> subProjects =  projectService.lambdaQuery().eq(BusProject::getPId, busProjectVo.getId()).list();
 | 
			
		||||
            List<Long> subProjectIds = subProjects.stream().map(BusProject::getId).toList();
 | 
			
		||||
//            List<BusProject> subProjects =  projectService.lambdaQuery().eq(BusProject::getPId, busProjectVo.getId()).list();
 | 
			
		||||
//            List<Long> subProjectIds = subProjects.stream().map(BusProject::getId).toList();
 | 
			
		||||
 | 
			
		||||
            //所有分项工程
 | 
			
		||||
            List<PgsProgressCategory> collect = pgsProgressCategories.stream()
 | 
			
		||||
                .filter(category -> subProjectIds.contains(category.getProjectId())).toList();
 | 
			
		||||
//            List<PgsProgressCategory> collect = pgsProgressCategories.stream()
 | 
			
		||||
//                .filter(category -> subProjectIds.contains(category.getProjectId())).toList();
 | 
			
		||||
 | 
			
		||||
            BigDecimal totalValue = BigDecimal.ZERO;
 | 
			
		||||
            BigDecimal estimatedTotalValue = BigDecimal.ZERO;
 | 
			
		||||
@ -132,13 +135,10 @@ public class OutTableController extends BaseController {
 | 
			
		||||
            for (OutMonthPlanAudit planAudit : planAudits) {
 | 
			
		||||
                totalValue = totalValue.add(planAudit.getConstructionValue());
 | 
			
		||||
                YearMonth planMonth = YearMonth.parse(planAudit.getPlanMonth(), formatter);
 | 
			
		||||
                // 比较大小
 | 
			
		||||
                if (planMonth.isBefore(yearMonth)) {
 | 
			
		||||
                if(!planMonth.isAfter(yearMonth)){
 | 
			
		||||
                    estimatedTotalValue=estimatedTotalValue.add(planAudit.getConstructionValue());
 | 
			
		||||
                } else if (planMonth.isAfter(yearMonth)) {
 | 
			
		||||
 | 
			
		||||
                } else {
 | 
			
		||||
                    estimatedTotalValue = estimatedTotalValue.add(planAudit.getConstructionValue());
 | 
			
		||||
                }
 | 
			
		||||
                if(planMonth.equals(paramMonth)){
 | 
			
		||||
                    monthlyEstimatedValue = planAudit.getConstructionValue();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -388,28 +388,28 @@ public class OutTableController extends BaseController {
 | 
			
		||||
            vo.setProjectId(projectVo.getId());
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            List<OutMonthPlan> list = monthPlanService.lambdaQuery().eq(OutMonthPlan::getProjectId, projectVo.getId())
 | 
			
		||||
            List<OutMonthPlan> list = monthPlanService.lambdaQuery()
 | 
			
		||||
                .eq(OutMonthPlan::getProjectId, projectVo.getId())
 | 
			
		||||
                .eq(OutMonthPlan::getValueType, bo.getValueType())
 | 
			
		||||
                .list();
 | 
			
		||||
 | 
			
		||||
            // 计算累计完成值
 | 
			
		||||
            BigDecimal totalValue =   list.stream()
 | 
			
		||||
                .map(OutMonthPlan::getCompleteValue)
 | 
			
		||||
            BigDecimal totalValue = list.stream()
 | 
			
		||||
                .map(OutMonthPlan::getPlanValue)
 | 
			
		||||
                .filter(Objects::nonNull)
 | 
			
		||||
                .reduce(BigDecimal.ZERO, BigDecimal::add);
 | 
			
		||||
            vo.setTotalValue(totalValue);
 | 
			
		||||
 | 
			
		||||
            OutMonthPlan matchedPlan = list.stream()
 | 
			
		||||
                .filter(plan -> Objects.equals(plan.getValueType(), bo.getValueType())
 | 
			
		||||
                    && Objects.equals(plan.getPlanMonth(), bo.getMonth()))
 | 
			
		||||
                .filter(plan -> Objects.equals(plan.getPlanMonth(), bo.getMonth()))
 | 
			
		||||
                .findFirst()
 | 
			
		||||
                .orElse(null);
 | 
			
		||||
 | 
			
		||||
            List<OutMonthPlan> matchedPlans = list.stream()
 | 
			
		||||
                .filter(plan -> Objects.equals(plan.getValueType(), bo.getValueType())
 | 
			
		||||
                    && plan.getPlanMonth() != null
 | 
			
		||||
                    && bo.getMonth() != null
 | 
			
		||||
                    && plan.getPlanMonth().compareTo(bo.getMonth()) <= 0)
 | 
			
		||||
                .toList();
 | 
			
		||||
//            List<OutMonthPlan> matchedPlans = list.stream()
 | 
			
		||||
//                .filter(plan -> plan.getPlanMonth() != null
 | 
			
		||||
//                    && bo.getMonth() != null
 | 
			
		||||
//                    && plan.getPlanMonth().compareTo(bo.getMonth()) <= 0)
 | 
			
		||||
//                .toList();
 | 
			
		||||
 | 
			
		||||
            vo.setMonthEstimatedValue(matchedPlan == null? BigDecimal.ZERO :matchedPlan.getPlanValue());
 | 
			
		||||
 | 
			
		||||
@ -417,7 +417,7 @@ public class OutTableController extends BaseController {
 | 
			
		||||
                vo.setMonthCompletionValue(matchedPlan == null? BigDecimal.ZERO :matchedPlan.getCompleteValue());
 | 
			
		||||
 | 
			
		||||
                // 计算累计完成值
 | 
			
		||||
                BigDecimal accumulatedCompleteValue = matchedPlans.stream()
 | 
			
		||||
                BigDecimal accumulatedCompleteValue = list.stream()
 | 
			
		||||
                    .map(OutMonthPlan::getCompleteValue)
 | 
			
		||||
                    .filter(Objects::nonNull)
 | 
			
		||||
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
 | 
			
		||||
 | 
			
		||||
@ -71,5 +71,10 @@ public class OutMonthPlanBo extends BaseEntity {
 | 
			
		||||
     */
 | 
			
		||||
    private String completeAuditStatus;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否设计
 | 
			
		||||
     */
 | 
			
		||||
    private Boolean isDesign;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -99,7 +99,7 @@ public class OutConstructionValueServiceImpl extends ServiceImpl<OutConstruction
 | 
			
		||||
    private LambdaQueryWrapper<OutConstructionValue> buildQueryWrapper(OutConstructionValueBo bo) {
 | 
			
		||||
        Map<String, Object> params = bo.getParams();
 | 
			
		||||
        LambdaQueryWrapper<OutConstructionValue> lqw = Wrappers.lambdaQuery();
 | 
			
		||||
        lqw.orderByAsc(OutConstructionValue::getId);
 | 
			
		||||
        lqw.orderByDesc(OutConstructionValue::getId);
 | 
			
		||||
        lqw.eq(bo.getProjectId() != null, OutConstructionValue::getProjectId, bo.getProjectId());
 | 
			
		||||
        lqw.eq(bo.getMatrixId() != null, OutConstructionValue::getMatrixId, bo.getMatrixId());
 | 
			
		||||
        lqw.eq(bo.getProgressCategoryId() != null, OutConstructionValue::getProgressCategoryId, bo.getProgressCategoryId());
 | 
			
		||||
 | 
			
		||||
@ -72,7 +72,7 @@ public class OutMonthPlanAuditServiceImpl extends ServiceImpl<OutMonthPlanAuditM
 | 
			
		||||
    private LambdaQueryWrapper<OutMonthPlanAudit> buildQueryWrapper(OutMonthPlanAuditBo bo) {
 | 
			
		||||
        Map<String, Object> params = bo.getParams();
 | 
			
		||||
        LambdaQueryWrapper<OutMonthPlanAudit> lqw = Wrappers.lambdaQuery();
 | 
			
		||||
        lqw.orderByAsc(OutMonthPlanAudit::getId);
 | 
			
		||||
        lqw.orderByDesc(OutMonthPlanAudit::getId);
 | 
			
		||||
        lqw.eq(bo.getProjectId() != null, OutMonthPlanAudit::getProjectId, bo.getProjectId());
 | 
			
		||||
        lqw.eq(bo.getDesignValue() != null, OutMonthPlanAudit::getDesignValue, bo.getDesignValue());
 | 
			
		||||
        lqw.eq(bo.getPurchaseValue() != null, OutMonthPlanAudit::getPurchaseValue, bo.getPurchaseValue());
 | 
			
		||||
 | 
			
		||||
@ -35,10 +35,7 @@ import org.dromara.out.service.IOutMonthPlanService;
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
import java.time.LocalDate;
 | 
			
		||||
import java.time.temporal.TemporalAdjusters;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -103,7 +100,7 @@ public class OutMonthPlanServiceImpl extends ServiceImpl<OutMonthPlanMapper, Out
 | 
			
		||||
    private LambdaQueryWrapper<OutMonthPlan> buildQueryWrapper(OutMonthPlanBo bo) {
 | 
			
		||||
        Map<String, Object> params = bo.getParams();
 | 
			
		||||
        LambdaQueryWrapper<OutMonthPlan> lqw = Wrappers.lambdaQuery();
 | 
			
		||||
        lqw.orderByAsc(OutMonthPlan::getId);
 | 
			
		||||
        lqw.orderByDesc(OutMonthPlan::getId);
 | 
			
		||||
        lqw.eq(bo.getProjectId() != null, OutMonthPlan::getProjectId, bo.getProjectId());
 | 
			
		||||
        lqw.eq(bo.getPlanValue() != null, OutMonthPlan::getPlanValue, bo.getPlanValue());
 | 
			
		||||
        lqw.eq(bo.getCompleteValue() != null, OutMonthPlan::getCompleteValue, bo.getCompleteValue());
 | 
			
		||||
@ -142,6 +139,17 @@ public class OutMonthPlanServiceImpl extends ServiceImpl<OutMonthPlanMapper, Out
 | 
			
		||||
    public Boolean updateByBo(OutMonthPlanBo bo) {
 | 
			
		||||
        OutMonthPlan update = MapstructUtils.convert(bo, OutMonthPlan.class);
 | 
			
		||||
        validEntityBeforeSave(update);
 | 
			
		||||
        OutMonthPlan outMonthPlan = baseMapper.selectById(update.getId());
 | 
			
		||||
        String status;
 | 
			
		||||
        if(bo.getIsDesign()){
 | 
			
		||||
            status = outMonthPlan.getPlanAuditStatus();
 | 
			
		||||
        }else {
 | 
			
		||||
            status = outMonthPlan.getCompleteAuditStatus();
 | 
			
		||||
        }
 | 
			
		||||
        if(Arrays.asList(BusinessStatusEnum.FINISH.getStatus(),BusinessStatusEnum.WAITING.getStatus()).contains(status)){
 | 
			
		||||
            String msg =   BusinessStatusEnum.WAITING.getStatus().equals(status) ? "计划正在审核中,请勿修改" : "计划已审核完成,请勿修改";
 | 
			
		||||
            throw new ServiceException(msg);
 | 
			
		||||
        }
 | 
			
		||||
        return baseMapper.updateById(update) > 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -173,6 +181,17 @@ public class OutMonthPlanServiceImpl extends ServiceImpl<OutMonthPlanMapper, Out
 | 
			
		||||
        if(isValid){
 | 
			
		||||
            //TODO 做一些业务上的校验,判断是否需要校验
 | 
			
		||||
        }
 | 
			
		||||
        List<OutMonthPlan> outMonthPlans = baseMapper.selectList(Wrappers.<OutMonthPlan>lambdaQuery().in(OutMonthPlan::getId, ids));
 | 
			
		||||
        if (!outMonthPlans.isEmpty()) {
 | 
			
		||||
            List<String> statusList = outMonthPlans.stream().map(OutMonthPlan::getValueType).collect(Collectors.toList());
 | 
			
		||||
            if (statusList.contains(BusinessStatusEnum.WAITING.getStatus())) {
 | 
			
		||||
                throw new ServiceException("计划正在审核中,请勿删除");
 | 
			
		||||
            }
 | 
			
		||||
            if (statusList.contains(BusinessStatusEnum.FINISH.getStatus())) {
 | 
			
		||||
                throw new ServiceException("计划已审核完成,请勿删除");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return baseMapper.deleteByIds(ids) > 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -73,7 +73,7 @@ public class OutSettlementValueOwnerServiceImpl extends ServiceImpl<OutSettlemen
 | 
			
		||||
    private LambdaQueryWrapper<OutSettlementValueOwner> buildQueryWrapper(OutSettlementValueOwnerBo bo) {
 | 
			
		||||
        Map<String, Object> params = bo.getParams();
 | 
			
		||||
        LambdaQueryWrapper<OutSettlementValueOwner> lqw = Wrappers.lambdaQuery();
 | 
			
		||||
        lqw.orderByAsc(OutSettlementValueOwner::getId);
 | 
			
		||||
        lqw.orderByDesc(OutSettlementValueOwner::getId);
 | 
			
		||||
        lqw.eq(bo.getProjectId() != null, OutSettlementValueOwner::getProjectId, bo.getProjectId());
 | 
			
		||||
        lqw.eq(bo.getSettlementValue() != null, OutSettlementValueOwner::getSettlementValue, bo.getSettlementValue());
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getValueType()), OutSettlementValueOwner::getValueType, bo.getValueType());
 | 
			
		||||
 | 
			
		||||
@ -79,7 +79,7 @@ public class OutSettlementValueSubcontractServiceImpl extends ServiceImpl<OutSet
 | 
			
		||||
    private LambdaQueryWrapper<OutSettlementValueSubcontract> buildQueryWrapper(OutSettlementValueSubcontractBo bo) {
 | 
			
		||||
        Map<String, Object> params = bo.getParams();
 | 
			
		||||
        LambdaQueryWrapper<OutSettlementValueSubcontract> lqw = Wrappers.lambdaQuery();
 | 
			
		||||
        lqw.orderByAsc(OutSettlementValueSubcontract::getId);
 | 
			
		||||
        lqw.orderByDesc(OutSettlementValueSubcontract::getId);
 | 
			
		||||
        lqw.eq(bo.getProjectId() != null, OutSettlementValueSubcontract::getProjectId, bo.getProjectId());
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getDocumentCode()), OutSettlementValueSubcontract::getDocumentCode, bo.getDocumentCode());
 | 
			
		||||
        lqw.eq(StringUtils.isNotBlank(bo.getSettlementDescribe()), OutSettlementValueSubcontract::getSettlementDescribe, bo.getSettlementDescribe());
 | 
			
		||||
 | 
			
		||||
@ -72,7 +72,7 @@ public class OutValueAllocationServiceImpl extends ServiceImpl<OutValueAllocatio
 | 
			
		||||
    private LambdaQueryWrapper<OutValueAllocation> buildQueryWrapper(OutValueAllocationBo bo) {
 | 
			
		||||
        Map<String, Object> params = bo.getParams();
 | 
			
		||||
        LambdaQueryWrapper<OutValueAllocation> lqw = Wrappers.lambdaQuery();
 | 
			
		||||
        lqw.orderByAsc(OutValueAllocation::getId);
 | 
			
		||||
        lqw.orderByDesc(OutValueAllocation::getId);
 | 
			
		||||
        lqw.eq(bo.getProjectId() != null, OutValueAllocation::getProjectId, bo.getProjectId());
 | 
			
		||||
        lqw.eq(bo.getOwnerDesignValue() != null, OutValueAllocation::getOwnerDesignValue, bo.getOwnerDesignValue());
 | 
			
		||||
        lqw.eq(bo.getOwnerPurchaseValue() != null, OutValueAllocation::getOwnerPurchaseValue, bo.getOwnerPurchaseValue());
 | 
			
		||||
 | 
			
		||||
@ -4,10 +4,12 @@ import jakarta.annotation.Resource;
 | 
			
		||||
import jakarta.validation.constraints.NotNull;
 | 
			
		||||
import org.dromara.common.core.domain.R;
 | 
			
		||||
import org.dromara.common.satoken.utils.LoginHelper;
 | 
			
		||||
import org.dromara.common.web.core.BaseController;
 | 
			
		||||
import org.dromara.contractor.service.ISubConstructionUserService;
 | 
			
		||||
import org.dromara.project.domain.dto.attendance.BusAttendancePunchCardByFaceReq;
 | 
			
		||||
import org.dromara.project.domain.vo.BusAttendanceRuleVo;
 | 
			
		||||
import org.dromara.project.domain.vo.BusAttendanceVo;
 | 
			
		||||
import org.dromara.project.domain.vo.BusMonthAttendanceVo;
 | 
			
		||||
import org.dromara.project.service.IBusAttendanceRuleService;
 | 
			
		||||
import org.dromara.project.service.IBusAttendanceService;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
@ -24,8 +26,8 @@ import java.util.List;
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/app/project/attendance/app")
 | 
			
		||||
public class BusAttendanceAppController {
 | 
			
		||||
@RequestMapping("/app/project/attendance")
 | 
			
		||||
public class BusAttendanceAppController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private IBusAttendanceService attendanceService;
 | 
			
		||||
@ -71,12 +73,28 @@ public class BusAttendanceAppController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取用户当天打卡记录
 | 
			
		||||
     */
 | 
			
		||||
    @PostMapping("/getTodayAttendance/{projectId}")
 | 
			
		||||
    @GetMapping("/getTodayAttendance/{projectId}")
 | 
			
		||||
    public R<List<BusAttendanceVo>> getTodayAttendance(@NotNull @PathVariable("projectId") Long projectId){
 | 
			
		||||
        return R.ok(attendanceService.getTodayAttendance(projectId));
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取用户指定月份打卡记录
 | 
			
		||||
     */
 | 
			
		||||
    @GetMapping("/getMonthAttendance/{projectId}")
 | 
			
		||||
    public R<List<BusMonthAttendanceVo>> getMonthAttendance(@NotNull @PathVariable("projectId") Long projectId,
 | 
			
		||||
                                                            @NotNull String  month){
 | 
			
		||||
        return R.ok(attendanceService.getMonthAttendance(projectId,month));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取用户打卡异常记录
 | 
			
		||||
     */
 | 
			
		||||
    @GetMapping("/getAbnormalAttendance/{projectId}")
 | 
			
		||||
    public R<List<BusAttendanceVo>> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId){
 | 
			
		||||
        return R.ok(attendanceService.getAbnormalAttendance(projectId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,18 +1,27 @@
 | 
			
		||||
package org.dromara.project.controller.app;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import jakarta.annotation.Resource;
 | 
			
		||||
import jakarta.validation.constraints.NotNull;
 | 
			
		||||
import org.dromara.common.core.domain.R;
 | 
			
		||||
import org.dromara.common.core.validate.AddGroup;
 | 
			
		||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
 | 
			
		||||
import org.dromara.common.log.annotation.Log;
 | 
			
		||||
import org.dromara.common.log.enums.BusinessType;
 | 
			
		||||
import org.dromara.common.mybatis.core.page.PageQuery;
 | 
			
		||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
 | 
			
		||||
import org.dromara.common.satoken.utils.LoginHelper;
 | 
			
		||||
import org.dromara.common.web.core.BaseController;
 | 
			
		||||
import org.dromara.contractor.domain.SubConstructionUser;
 | 
			
		||||
import org.dromara.contractor.service.ISubConstructionUserService;
 | 
			
		||||
import org.dromara.project.domain.bo.BusAttendanceBo;
 | 
			
		||||
import org.dromara.project.domain.dto.leave.BusLeaveAddReq;
 | 
			
		||||
import org.dromara.project.domain.dto.leave.BusLeaveManagerReviewReq;
 | 
			
		||||
import org.dromara.project.domain.dto.leave.BusLeaveQueryReq;
 | 
			
		||||
import org.dromara.project.domain.vo.leave.BusLeaveVo;
 | 
			
		||||
import org.dromara.project.service.IBusLeaveService;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.GetMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author lilemy
 | 
			
		||||
@ -21,7 +30,7 @@ import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
@Validated
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/app/project/leave")
 | 
			
		||||
public class BusLeaveAppController {
 | 
			
		||||
public class BusLeaveAppController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private IBusLeaveService leaveService;
 | 
			
		||||
@ -34,9 +43,28 @@ public class BusLeaveAppController {
 | 
			
		||||
     */
 | 
			
		||||
    @GetMapping("/list/loginUser")
 | 
			
		||||
    public TableDataInfo<BusLeaveVo> listByLoginUser(BusLeaveQueryReq req, PageQuery pageQuery) {
 | 
			
		||||
        SubConstructionUser constructionUser = constructionUserService.getBySysUserId(LoginHelper.getUserId());
 | 
			
		||||
        req.setUserId(constructionUser.getId());
 | 
			
		||||
        return leaveService.queryPageList(req, pageQuery);
 | 
			
		||||
//        SubConstructionUser constructionUser = constructionUserService.getBySysUserId(LoginHelper.getUserId());
 | 
			
		||||
        req.setUserId(LoginHelper.getUserId());
 | 
			
		||||
        //管理员呢
 | 
			
		||||
        return leaveService.listByLoginUser(req, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 提交请假
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "提交请假", businessType = BusinessType.INSERT)
 | 
			
		||||
    @RepeatSubmit()
 | 
			
		||||
    @PostMapping()
 | 
			
		||||
    public R<Long> add(@RequestBody BusLeaveAddReq req) {
 | 
			
		||||
        return R.ok(leaveService.add(req));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,18 +1,23 @@
 | 
			
		||||
package org.dromara.project.controller.app;
 | 
			
		||||
 | 
			
		||||
import jakarta.annotation.Resource;
 | 
			
		||||
import org.dromara.common.core.domain.R;
 | 
			
		||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
 | 
			
		||||
import org.dromara.common.log.annotation.Log;
 | 
			
		||||
import org.dromara.common.log.enums.BusinessType;
 | 
			
		||||
import org.dromara.common.mybatis.core.page.PageQuery;
 | 
			
		||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
 | 
			
		||||
import org.dromara.common.satoken.utils.LoginHelper;
 | 
			
		||||
import org.dromara.common.web.core.BaseController;
 | 
			
		||||
import org.dromara.contractor.domain.SubConstructionUser;
 | 
			
		||||
import org.dromara.contractor.service.ISubConstructionUserService;
 | 
			
		||||
import org.dromara.project.domain.dto.leave.BusLeaveAddReq;
 | 
			
		||||
import org.dromara.project.domain.dto.reissuecard.BusReissueCardAddReq;
 | 
			
		||||
import org.dromara.project.domain.dto.reissuecard.BusReissueCardQueryReq;
 | 
			
		||||
import org.dromara.project.domain.vo.reissuecard.BusReissueCardVo;
 | 
			
		||||
import org.dromara.project.service.IBusReissueCardService;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.GetMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author lilemy
 | 
			
		||||
@ -21,7 +26,7 @@ import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
@Validated
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/app/project/reissueCard")
 | 
			
		||||
public class BusReissueCardAppController {
 | 
			
		||||
public class BusReissueCardAppController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private IBusReissueCardService reissueCardService;
 | 
			
		||||
@ -34,8 +39,19 @@ public class BusReissueCardAppController {
 | 
			
		||||
     */
 | 
			
		||||
    @GetMapping("/list/loginUser")
 | 
			
		||||
    public TableDataInfo<BusReissueCardVo> listByLoginUser(BusReissueCardQueryReq req, PageQuery pageQuery) {
 | 
			
		||||
        SubConstructionUser constructionUser = constructionUserService.getBySysUserId(LoginHelper.getUserId());
 | 
			
		||||
        req.setUserId(constructionUser.getId());
 | 
			
		||||
        return reissueCardService.queryPageList(req, pageQuery);
 | 
			
		||||
//        SubConstructionUser constructionUser = constructionUserService.getBySysUserId(LoginHelper.getUserId());
 | 
			
		||||
        req.setUserId(LoginHelper.getUserId());
 | 
			
		||||
        return reissueCardService.listByLoginUser(req, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 提交补卡
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "提交补卡", businessType = BusinessType.INSERT)
 | 
			
		||||
    @RepeatSubmit()
 | 
			
		||||
    @PostMapping()
 | 
			
		||||
    public R<Long> add(@RequestBody BusReissueCardAddReq req) {
 | 
			
		||||
        return R.ok(reissueCardService.add(req));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -37,6 +37,11 @@ public class BusAttendance extends BaseEntity {
 | 
			
		||||
     */
 | 
			
		||||
    private Long userId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户名
 | 
			
		||||
     */
 | 
			
		||||
    private String userName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 人脸照
 | 
			
		||||
     */
 | 
			
		||||
@ -62,6 +67,11 @@ public class BusAttendance extends BaseEntity {
 | 
			
		||||
     */
 | 
			
		||||
    private String clockStatus;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 迟到或早退的分钟
 | 
			
		||||
     */
 | 
			
		||||
    private Integer minuteCount;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 上下班(1上班2下班)
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ import lombok.EqualsAndHashCode;
 | 
			
		||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
 | 
			
		||||
 | 
			
		||||
import java.io.Serial;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -47,7 +48,7 @@ public class BusLeave extends BaseEntity {
 | 
			
		||||
    /**
 | 
			
		||||
     * 请假申请时间
 | 
			
		||||
     */
 | 
			
		||||
    private Date userTime;
 | 
			
		||||
    private LocalDateTime userTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请假类型(1事假 2病假)
 | 
			
		||||
@ -57,12 +58,12 @@ public class BusLeave extends BaseEntity {
 | 
			
		||||
    /**
 | 
			
		||||
     * 请假开始时间
 | 
			
		||||
     */
 | 
			
		||||
    private Date startTime;
 | 
			
		||||
    private LocalDateTime startTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请假结束时间
 | 
			
		||||
     */
 | 
			
		||||
    private Date endTime;
 | 
			
		||||
    private LocalDateTime endTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 班组长
 | 
			
		||||
@ -87,7 +88,7 @@ public class BusLeave extends BaseEntity {
 | 
			
		||||
    /**
 | 
			
		||||
     * 班组长操作时间
 | 
			
		||||
     */
 | 
			
		||||
    private Date gangerTime;
 | 
			
		||||
    private LocalDateTime gangerTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 管理员id
 | 
			
		||||
@ -112,7 +113,7 @@ public class BusLeave extends BaseEntity {
 | 
			
		||||
    /**
 | 
			
		||||
     * 管理员操作时间
 | 
			
		||||
     */
 | 
			
		||||
    private Date managerTime;
 | 
			
		||||
    private LocalDateTime managerTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 项目id
 | 
			
		||||
@ -134,4 +135,9 @@ public class BusLeave extends BaseEntity {
 | 
			
		||||
     */
 | 
			
		||||
    private String remark;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请假申请状态
 | 
			
		||||
     */
 | 
			
		||||
    private String auditStatus;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ import lombok.EqualsAndHashCode;
 | 
			
		||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
 | 
			
		||||
 | 
			
		||||
import java.io.Serial;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -47,7 +48,7 @@ public class BusReissueCard extends BaseEntity {
 | 
			
		||||
    /**
 | 
			
		||||
     * 补卡申请时间
 | 
			
		||||
     */
 | 
			
		||||
    private Date userTime;
 | 
			
		||||
    private LocalDateTime userTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 班组长
 | 
			
		||||
@ -72,7 +73,7 @@ public class BusReissueCard extends BaseEntity {
 | 
			
		||||
    /**
 | 
			
		||||
     * 班组长操作时间
 | 
			
		||||
     */
 | 
			
		||||
    private Date gangerTime;
 | 
			
		||||
    private LocalDateTime gangerTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 管理员id
 | 
			
		||||
@ -97,7 +98,7 @@ public class BusReissueCard extends BaseEntity {
 | 
			
		||||
    /**
 | 
			
		||||
     * 管理员操作时间
 | 
			
		||||
     */
 | 
			
		||||
    private Date managerTime;
 | 
			
		||||
    private LocalDateTime managerTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 项目id
 | 
			
		||||
@ -124,4 +125,9 @@ public class BusReissueCard extends BaseEntity {
 | 
			
		||||
     */
 | 
			
		||||
    private String remark;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 备注
 | 
			
		||||
     */
 | 
			
		||||
    private String status;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -37,6 +37,11 @@ public class BusAttendanceBo extends BaseEntity {
 | 
			
		||||
    @NotNull(message = "人员id不能为空", groups = { AddGroup.class, EditGroup.class })
 | 
			
		||||
    private Long userId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户名
 | 
			
		||||
     */
 | 
			
		||||
    private String userName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 人脸照
 | 
			
		||||
     */
 | 
			
		||||
@ -63,6 +68,11 @@ public class BusAttendanceBo extends BaseEntity {
 | 
			
		||||
     */
 | 
			
		||||
    private String clockStatus;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 迟到或早退的分钟
 | 
			
		||||
     */
 | 
			
		||||
    private Integer minuteCount;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 上下班(1上班2下班)
 | 
			
		||||
     */
 | 
			
		||||
@ -83,5 +93,4 @@ public class BusAttendanceBo extends BaseEntity {
 | 
			
		||||
     */
 | 
			
		||||
    private String lat;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,59 @@
 | 
			
		||||
package org.dromara.project.domain.dto.leave;
 | 
			
		||||
 | 
			
		||||
import jakarta.validation.constraints.NotNull;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import java.io.Serial;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author lilemy
 | 
			
		||||
 * @date 2025/4/8 11:44
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
public class BusLeaveAddReq implements Serializable {
 | 
			
		||||
 | 
			
		||||
    @Serial
 | 
			
		||||
    private static final long serialVersionUID = 43795533290515099L;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 申请人id
 | 
			
		||||
     */
 | 
			
		||||
    private Long userId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 申请人名字
 | 
			
		||||
     */
 | 
			
		||||
    private String userName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请假类型(1事假 2病假)
 | 
			
		||||
     */
 | 
			
		||||
    private String leaveType;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 申请请假说明
 | 
			
		||||
     */
 | 
			
		||||
    private String userExplain;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请假开始时间
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "请假开始时间不能为空")
 | 
			
		||||
    private LocalDateTime startTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请假结束时间
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "请假结束时间不能为空")
 | 
			
		||||
    private LocalDateTime endTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 项目id
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "项目id不能为空")
 | 
			
		||||
    private Long projectId;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -5,6 +5,7 @@ import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import java.io.Serial;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.time.LocalDate;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author lilemy
 | 
			
		||||
@ -67,4 +68,9 @@ public class BusLeaveQueryReq implements Serializable {
 | 
			
		||||
     */
 | 
			
		||||
    private Long teamId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 日期
 | 
			
		||||
     */
 | 
			
		||||
    private LocalDate date;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,52 @@
 | 
			
		||||
package org.dromara.project.domain.dto.reissuecard;
 | 
			
		||||
 | 
			
		||||
import jakarta.validation.constraints.NotNull;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import java.io.Serial;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.time.LocalDate;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author lilemy
 | 
			
		||||
 * @date 2025/4/8 9:58
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
public class BusReissueCardAddReq implements Serializable {
 | 
			
		||||
 | 
			
		||||
    @Serial
 | 
			
		||||
    private static final long serialVersionUID = -3708280254564807491L;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 申请人id
 | 
			
		||||
     */
 | 
			
		||||
    private Long userId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 申请人名字
 | 
			
		||||
     */
 | 
			
		||||
    private String userName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 申请补卡说明
 | 
			
		||||
     */
 | 
			
		||||
    private String userExplain;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 项目id
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "项目id不能为空")
 | 
			
		||||
    private Long projectId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 考勤表主键id
 | 
			
		||||
     */
 | 
			
		||||
    private Long attendanceId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 补卡申请时间
 | 
			
		||||
     */
 | 
			
		||||
    private LocalDateTime userTime;
 | 
			
		||||
}
 | 
			
		||||
@ -5,6 +5,7 @@ import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import java.io.Serial;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.time.LocalDate;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author lilemy
 | 
			
		||||
@ -72,4 +73,10 @@ public class BusReissueCardQueryReq implements Serializable {
 | 
			
		||||
     */
 | 
			
		||||
    private Long attendanceId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 日期
 | 
			
		||||
     */
 | 
			
		||||
    private LocalDate date;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,11 @@ public class BusAttendanceVo implements Serializable {
 | 
			
		||||
    @ExcelProperty(value = "")
 | 
			
		||||
    private Long id;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户名
 | 
			
		||||
     */
 | 
			
		||||
    private String userName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 人员id
 | 
			
		||||
     */
 | 
			
		||||
@ -74,6 +79,12 @@ public class BusAttendanceVo implements Serializable {
 | 
			
		||||
    @ExcelProperty(value = "1正常,2迟到,3早退,4缺勤,5补卡,6请假,7外勤")
 | 
			
		||||
    private String clockStatus;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 迟到或早退的分钟
 | 
			
		||||
     */
 | 
			
		||||
    private Integer minuteCount;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 上下班(1上班2下班)
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,42 @@
 | 
			
		||||
package org.dromara.project.domain.vo;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
 | 
			
		||||
import com.alibaba.excel.annotation.ExcelProperty;
 | 
			
		||||
import io.github.linpeilie.annotations.AutoMapper;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
 | 
			
		||||
import org.dromara.common.excel.convert.ExcelDictConvert;
 | 
			
		||||
import org.dromara.project.domain.BusAttendance;
 | 
			
		||||
 | 
			
		||||
import java.io.Serial;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.time.LocalDate;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 考勤视图对象 bus_attendance
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 * @date 2025-08-05
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
@ExcelIgnoreUnannotated
 | 
			
		||||
@AutoMapper(target = BusAttendance.class)
 | 
			
		||||
public class BusMonthAttendanceVo implements Serializable {
 | 
			
		||||
 | 
			
		||||
    @Serial
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 打卡日期
 | 
			
		||||
     */
 | 
			
		||||
    private LocalDate clockDate;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 考勤记录
 | 
			
		||||
     */
 | 
			
		||||
    private List<BusAttendanceVo> list;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -10,6 +10,7 @@ import org.dromara.project.domain.BusLeave;
 | 
			
		||||
 | 
			
		||||
import java.io.Serial;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -53,7 +54,7 @@ public class BusLeaveVo implements Serializable {
 | 
			
		||||
     * 请假申请时间
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "请假申请时间")
 | 
			
		||||
    private Date userTime;
 | 
			
		||||
    private LocalDateTime userTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请假类型(1事假 2病假)
 | 
			
		||||
@ -66,13 +67,13 @@ public class BusLeaveVo implements Serializable {
 | 
			
		||||
     * 请假开始时间
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "请假开始时间")
 | 
			
		||||
    private Date startTime;
 | 
			
		||||
    private LocalDateTime startTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请假结束时间
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "请假结束时间")
 | 
			
		||||
    private Date endTime;
 | 
			
		||||
    private LocalDateTime endTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 项目id
 | 
			
		||||
@ -117,7 +118,7 @@ public class BusLeaveVo implements Serializable {
 | 
			
		||||
     * 班组长操作时间
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "班组长操作时间")
 | 
			
		||||
    private Date gangerTime;
 | 
			
		||||
    private LocalDateTime gangerTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 管理员id
 | 
			
		||||
@ -146,7 +147,7 @@ public class BusLeaveVo implements Serializable {
 | 
			
		||||
     * 管理员操作时间
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "管理员操作时间")
 | 
			
		||||
    private Date managerTime;
 | 
			
		||||
    private LocalDateTime managerTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 备注
 | 
			
		||||
@ -157,6 +158,8 @@ public class BusLeaveVo implements Serializable {
 | 
			
		||||
    /**
 | 
			
		||||
     * 审核状态
 | 
			
		||||
     */
 | 
			
		||||
    private String status;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请假申请状态
 | 
			
		||||
     */
 | 
			
		||||
    private String auditStatus;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,7 @@ import org.dromara.project.domain.BusReissueCard;
 | 
			
		||||
 | 
			
		||||
import java.io.Serial;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -53,7 +54,7 @@ public class BusReissueCardVo implements Serializable {
 | 
			
		||||
     * 补卡申请时间
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "补卡申请时间")
 | 
			
		||||
    private Date userTime;
 | 
			
		||||
    private LocalDateTime userTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 项目id
 | 
			
		||||
@ -98,7 +99,7 @@ public class BusReissueCardVo implements Serializable {
 | 
			
		||||
     * 班组长操作时间
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "班组长操作时间")
 | 
			
		||||
    private Date gangerTime;
 | 
			
		||||
    private LocalDateTime gangerTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 管理员id
 | 
			
		||||
@ -127,7 +128,7 @@ public class BusReissueCardVo implements Serializable {
 | 
			
		||||
     * 管理员操作时间
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "管理员操作时间")
 | 
			
		||||
    private Date managerTime;
 | 
			
		||||
    private LocalDateTime  managerTime;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 备注
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
package org.dromara.project.service;
 | 
			
		||||
 | 
			
		||||
import jakarta.validation.constraints.NotNull;
 | 
			
		||||
import org.dromara.project.domain.dto.attendance.BusAttendancePunchCardByFaceReq;
 | 
			
		||||
import org.dromara.project.domain.vo.BusAttendanceVo;
 | 
			
		||||
import org.dromara.project.domain.bo.BusAttendanceBo;
 | 
			
		||||
@ -8,6 +9,8 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
 | 
			
		||||
import org.dromara.common.mybatis.core.page.PageQuery;
 | 
			
		||||
 | 
			
		||||
import com.baomidou.mybatisplus.extension.service.IService;
 | 
			
		||||
import org.dromara.project.domain.vo.BusMonthAttendanceVo;
 | 
			
		||||
import org.springframework.web.bind.annotation.PathVariable;
 | 
			
		||||
import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
@ -108,4 +111,14 @@ public interface IBusAttendanceService extends IService<BusAttendance>{
 | 
			
		||||
     * 获取用户当天打卡记录
 | 
			
		||||
     */
 | 
			
		||||
    List<BusAttendanceVo> getTodayAttendance(Long projectId);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取用户指定月份的打卡记录
 | 
			
		||||
     */
 | 
			
		||||
    List<BusMonthAttendanceVo> getMonthAttendance(Long projectId, String  month);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取用户指定月份的打卡记录
 | 
			
		||||
     */
 | 
			
		||||
    List<BusAttendanceVo> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -6,11 +6,13 @@ import com.baomidou.mybatisplus.extension.service.IService;
 | 
			
		||||
import org.dromara.common.mybatis.core.page.PageQuery;
 | 
			
		||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
 | 
			
		||||
import org.dromara.project.domain.BusLeave;
 | 
			
		||||
import org.dromara.project.domain.dto.leave.BusLeaveAddReq;
 | 
			
		||||
import org.dromara.project.domain.dto.leave.BusLeaveGangerReviewReq;
 | 
			
		||||
import org.dromara.project.domain.dto.leave.BusLeaveManagerReviewReq;
 | 
			
		||||
import org.dromara.project.domain.dto.leave.BusLeaveQueryReq;
 | 
			
		||||
import org.dromara.project.domain.vo.leave.BusLeaveVo;
 | 
			
		||||
 | 
			
		||||
import java.time.LocalDate;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@ -96,4 +98,19 @@ public interface IBusLeaveService extends IService<BusLeave> {
 | 
			
		||||
     */
 | 
			
		||||
    Page<BusLeaveVo> getVoPage(Page<BusLeave> leavePage);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询是否请假
 | 
			
		||||
     */
 | 
			
		||||
   Boolean isLeave(LocalDate date,Long userId);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     * 新增申请
 | 
			
		||||
     */
 | 
			
		||||
   Long add(BusLeaveAddReq req);
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     * 查询当前登录用户请假申请列表
 | 
			
		||||
     */
 | 
			
		||||
   TableDataInfo<BusLeaveVo>  listByLoginUser(BusLeaveQueryReq req, PageQuery pageQuery);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -6,9 +6,11 @@ import com.baomidou.mybatisplus.extension.service.IService;
 | 
			
		||||
import org.dromara.common.mybatis.core.page.PageQuery;
 | 
			
		||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
 | 
			
		||||
import org.dromara.project.domain.BusReissueCard;
 | 
			
		||||
import org.dromara.project.domain.dto.reissuecard.BusReissueCardAddReq;
 | 
			
		||||
import org.dromara.project.domain.dto.reissuecard.BusReissueCardManagerReviewReq;
 | 
			
		||||
import org.dromara.project.domain.dto.reissuecard.BusReissueCardQueryReq;
 | 
			
		||||
import org.dromara.project.domain.vo.reissuecard.BusReissueCardVo;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestBody;
 | 
			
		||||
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
@ -87,4 +89,14 @@ public interface IBusReissueCardService extends IService<BusReissueCard> {
 | 
			
		||||
     */
 | 
			
		||||
    Page<BusReissueCardVo> getVoPage(Page<BusReissueCard> reissueCardPage);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取施工人员补卡申请分页列表
 | 
			
		||||
     */
 | 
			
		||||
    TableDataInfo<BusReissueCardVo> listByLoginUser(BusReissueCardQueryReq req, PageQuery pageQuery);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增施工人员补卡申请
 | 
			
		||||
     */
 | 
			
		||||
    Long add(BusReissueCardAddReq req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,7 @@ import org.dromara.project.domain.dto.attendance.BusAttendancePunchCardByFaceReq
 | 
			
		||||
import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum;
 | 
			
		||||
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
 | 
			
		||||
import org.dromara.project.domain.vo.BusAttendanceRuleVo;
 | 
			
		||||
import org.dromara.project.domain.vo.BusMonthAttendanceVo;
 | 
			
		||||
import org.dromara.project.domain.vo.BusProjectPunchrangeVo;
 | 
			
		||||
import org.dromara.project.service.*;
 | 
			
		||||
import org.dromara.system.domain.vo.SysOssVo;
 | 
			
		||||
@ -86,6 +87,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
 | 
			
		||||
 | 
			
		||||
    private final IBusProjectTeamService projectTeamService;
 | 
			
		||||
 | 
			
		||||
    private final IBusLeaveService leaveService;
 | 
			
		||||
 | 
			
		||||
    // 出勤状态(正常、迟到、早退)
 | 
			
		||||
    private static final Set<String> ATTENDANCE_STATUS = new HashSet<>(Arrays.asList(BusAttendanceClockStatusEnum.NORMAL.getValue(),
 | 
			
		||||
@ -248,6 +250,10 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
 | 
			
		||||
            //确定考勤日期
 | 
			
		||||
            LocalDate localDate = calculateAttendanceDate(now, busAttendanceRuleVo);
 | 
			
		||||
 | 
			
		||||
            if(leaveService.isLeave(localDate, userId)){
 | 
			
		||||
                throw new ServiceException("当前用户正在请假中", HttpStatus.BAD_REQUEST);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 判断当前用户打卡状态
 | 
			
		||||
            List<BusAttendance> attendances = this.lambdaQuery()
 | 
			
		||||
                .eq(BusAttendance::getUserId, userId)
 | 
			
		||||
@ -396,6 +402,73 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<BusMonthAttendanceVo> getMonthAttendance(Long projectId, String month) {
 | 
			
		||||
        // 解析月份字符串获取开始和结束日期
 | 
			
		||||
        LocalDate startDate = LocalDate.parse(month + "-01");
 | 
			
		||||
        LocalDate endDate = startDate.withDayOfMonth(startDate.lengthOfMonth());
 | 
			
		||||
        // 获取当前用户ID
 | 
			
		||||
        Long userId = LoginHelper.getUserId();
 | 
			
		||||
 | 
			
		||||
        List<BusUserProjectRelevancy> relevancyList = userProjectRelevancyService.list(
 | 
			
		||||
            Wrappers.lambdaQuery(BusUserProjectRelevancy.class)
 | 
			
		||||
                .eq(BusUserProjectRelevancy::getProjectId, projectId)
 | 
			
		||||
                .eq(BusUserProjectRelevancy::getUserId, userId));
 | 
			
		||||
 | 
			
		||||
        boolean b = relevancyList.stream().allMatch(relevancy -> "1".equals(relevancy.getUserType()));
 | 
			
		||||
 | 
			
		||||
        // 查询该月的所有考勤记录
 | 
			
		||||
        List<BusAttendanceVo> attendanceList = baseMapper.selectVoList(Wrappers.lambdaQuery(BusAttendance.class)
 | 
			
		||||
            .eq(BusAttendance::getUserId, userId)
 | 
			
		||||
            .eq(b, BusAttendance::getProjectId, projectId)
 | 
			
		||||
            .ge(BusAttendance::getClockDate, startDate)
 | 
			
		||||
            .le(BusAttendance::getClockDate, endDate)
 | 
			
		||||
            .orderByAsc(BusAttendance::getClockDate));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // 按日期分组考勤记录
 | 
			
		||||
        Map<LocalDate, List<BusAttendanceVo>> attendanceMap = attendanceList.stream()
 | 
			
		||||
            .collect(Collectors.groupingBy(BusAttendanceVo::getClockDate));
 | 
			
		||||
 | 
			
		||||
        // 生成每日考勤记录
 | 
			
		||||
        List<BusMonthAttendanceVo> result = new ArrayList<>();
 | 
			
		||||
        LocalDate currentDate = startDate;
 | 
			
		||||
 | 
			
		||||
        while (!currentDate.isAfter(endDate)) {
 | 
			
		||||
            BusMonthAttendanceVo busMonthAttendanceVo = new BusMonthAttendanceVo();
 | 
			
		||||
            busMonthAttendanceVo.setClockDate(currentDate);
 | 
			
		||||
            busMonthAttendanceVo.setList(attendanceMap.getOrDefault(currentDate, Collections.emptyList()));
 | 
			
		||||
            result.add(busMonthAttendanceVo);
 | 
			
		||||
            currentDate = currentDate.plusDays(1);
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<BusAttendanceVo> getAbnormalAttendance(Long projectId) {
 | 
			
		||||
 | 
			
		||||
        List<String> abnormalList = Arrays.asList(BusAttendanceClockStatusEnum.LATE.getValue(),
 | 
			
		||||
            BusAttendanceClockStatusEnum.LEAVEEARLY.getValue(),
 | 
			
		||||
            BusAttendanceClockStatusEnum.UNCLOCK.getValue());
 | 
			
		||||
 | 
			
		||||
        // 获取当前用户ID
 | 
			
		||||
        Long userId = LoginHelper.getUserId();
 | 
			
		||||
        List<BusUserProjectRelevancy> relevancyList = userProjectRelevancyService.list(
 | 
			
		||||
            Wrappers.lambdaQuery(BusUserProjectRelevancy.class)
 | 
			
		||||
                .eq(BusUserProjectRelevancy::getProjectId, projectId)
 | 
			
		||||
                .eq(BusUserProjectRelevancy::getUserId, userId));
 | 
			
		||||
 | 
			
		||||
        boolean b = relevancyList.stream().allMatch(relevancy -> "1".equals(relevancy.getUserType()));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        return baseMapper.selectVoList(Wrappers.lambdaQuery(BusAttendance.class)
 | 
			
		||||
            .eq(BusAttendance::getUserId, userId)
 | 
			
		||||
            .eq(b, BusAttendance::getProjectId, projectId)
 | 
			
		||||
            .in(BusAttendance::getClockStatus, abnormalList)
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 计算打卡时间归属的考勤日(关键:解决跨天场景的日期映射)
 | 
			
		||||
     */
 | 
			
		||||
@ -428,7 +501,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
 | 
			
		||||
     */
 | 
			
		||||
    private Boolean isLate(LocalDateTime checkTime, BusAttendanceRuleVo vo) {
 | 
			
		||||
 | 
			
		||||
        long clockInSeconds = vo.getClockInTime().toSecondOfDay();
 | 
			
		||||
        long clockInSeconds = vo.getClockInTime().plusMinutes(1).toSecondOfDay();
 | 
			
		||||
        long clockInResultSeconds = vo.getClockInResultTime().toSecondOfDay();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,22 @@
 | 
			
		||||
package org.dromara.project.service.impl;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.bean.BeanUtil;
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import cn.hutool.core.convert.Convert;
 | 
			
		||||
import cn.hutool.core.map.MapUtil;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 | 
			
		||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 | 
			
		||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 | 
			
		||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 | 
			
		||||
import jakarta.annotation.Resource;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.dromara.common.core.constant.HttpStatus;
 | 
			
		||||
import org.dromara.common.core.domain.R;
 | 
			
		||||
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
 | 
			
		||||
import org.dromara.common.core.domain.event.ProcessEvent;
 | 
			
		||||
import org.dromara.common.core.domain.event.ProcessTaskEvent;
 | 
			
		||||
import org.dromara.common.core.enums.BusinessStatusEnum;
 | 
			
		||||
import org.dromara.common.core.exception.ServiceException;
 | 
			
		||||
import org.dromara.common.core.utils.DateUtils;
 | 
			
		||||
import org.dromara.common.core.utils.ObjectUtils;
 | 
			
		||||
@ -16,25 +27,25 @@ import org.dromara.common.satoken.utils.LoginHelper;
 | 
			
		||||
import org.dromara.contractor.domain.SubConstructionUser;
 | 
			
		||||
import org.dromara.contractor.service.ISubConstructionUserService;
 | 
			
		||||
import org.dromara.contractor.service.ISubContractorService;
 | 
			
		||||
import org.dromara.project.domain.BusAttendance;
 | 
			
		||||
import org.dromara.project.domain.BusLeave;
 | 
			
		||||
import org.dromara.project.domain.BusProjectTeam;
 | 
			
		||||
import org.dromara.project.domain.BusProjectTeamMember;
 | 
			
		||||
import org.dromara.project.domain.*;
 | 
			
		||||
import org.dromara.project.domain.dto.leave.BusLeaveAddReq;
 | 
			
		||||
import org.dromara.project.domain.dto.leave.BusLeaveGangerReviewReq;
 | 
			
		||||
import org.dromara.project.domain.enums.*;
 | 
			
		||||
import org.dromara.project.domain.dto.leave.BusLeaveManagerReviewReq;
 | 
			
		||||
import org.dromara.project.domain.dto.leave.BusLeaveQueryReq;
 | 
			
		||||
import org.dromara.project.domain.vo.leave.BusLeaveVo;
 | 
			
		||||
import org.dromara.project.mapper.BusLeaveMapper;
 | 
			
		||||
import org.dromara.project.service.IBusAttendanceService;
 | 
			
		||||
import org.dromara.project.service.IBusLeaveService;
 | 
			
		||||
import org.dromara.project.service.IBusProjectTeamMemberService;
 | 
			
		||||
import org.dromara.project.service.IBusProjectTeamService;
 | 
			
		||||
import org.dromara.project.service.*;
 | 
			
		||||
import org.dromara.workflow.domain.TestLeave;
 | 
			
		||||
import org.springframework.beans.BeanUtils;
 | 
			
		||||
import org.springframework.context.annotation.Lazy;
 | 
			
		||||
import org.springframework.context.event.EventListener;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
 | 
			
		||||
import java.time.LocalDate;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.time.LocalTime;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
@ -46,6 +57,7 @@ import java.util.stream.Collectors;
 | 
			
		||||
 * @date 2025-04-08
 | 
			
		||||
 */
 | 
			
		||||
@Service
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
 | 
			
		||||
    implements IBusLeaveService {
 | 
			
		||||
 | 
			
		||||
@ -65,6 +77,8 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
 | 
			
		||||
    @Resource
 | 
			
		||||
    private ISubContractorService contractorService;
 | 
			
		||||
 | 
			
		||||
    private IBusUserProjectRelevancyService userProjectRelevancyService;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询施工人员请假申请
 | 
			
		||||
     *
 | 
			
		||||
@ -141,7 +155,7 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
 | 
			
		||||
        newLeave.setId(id);
 | 
			
		||||
        newLeave.setGangerOpinion(gangerOpinion);
 | 
			
		||||
        newLeave.setGangerExplain(req.getGangerExplain());
 | 
			
		||||
        newLeave.setGangerTime(new Date());
 | 
			
		||||
        newLeave.setGangerTime(LocalDateTime.now());
 | 
			
		||||
        newLeave.setRemark(req.getRemark());
 | 
			
		||||
        boolean result = this.updateById(newLeave);
 | 
			
		||||
        if (!result) {
 | 
			
		||||
@ -200,21 +214,21 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
 | 
			
		||||
        leave.setManagerId(constructionUser.getId());
 | 
			
		||||
        leave.setManagerOpinion(managerOpinion);
 | 
			
		||||
        leave.setManagerExplain(req.getManagerExplain());
 | 
			
		||||
        leave.setManagerTime(new Date());
 | 
			
		||||
        leave.setManagerTime(LocalDateTime.now());
 | 
			
		||||
        leave.setRemark(req.getRemark());
 | 
			
		||||
        boolean result = this.updateById(leave);
 | 
			
		||||
        if (!result) {
 | 
			
		||||
            throw new ServiceException("更新管理员审核操作失败", HttpStatus.ERROR);
 | 
			
		||||
        }
 | 
			
		||||
        // 更新考勤表记录
 | 
			
		||||
        Date startTime = oldLeave.getStartTime();
 | 
			
		||||
        Date endTime = oldLeave.getEndTime();
 | 
			
		||||
        LocalDateTime startTime = oldLeave.getStartTime();
 | 
			
		||||
        LocalDateTime endTime = oldLeave.getEndTime();
 | 
			
		||||
        // 计算相差的时间
 | 
			
		||||
        long diffInMillis = endTime.getTime() - startTime.getTime();
 | 
			
		||||
        long day = TimeUnit.MILLISECONDS.toDays(diffInMillis) + 1;
 | 
			
		||||
        Long userId = oldLeave.getUserId();
 | 
			
		||||
        String userName = oldLeave.getUserName();
 | 
			
		||||
        Long projectId = oldLeave.getProjectId();
 | 
			
		||||
//        long diffInMillis = endTime.getTime() - startTime.getTime();
 | 
			
		||||
//        long day = TimeUnit.MILLISECONDS.toDays(diffInMillis) + 1;
 | 
			
		||||
//        Long userId = oldLeave.getUserId();
 | 
			
		||||
//        String userName = oldLeave.getUserName();
 | 
			
		||||
//        Long projectId = oldLeave.getProjectId();
 | 
			
		||||
        // 遍历每一天
 | 
			
		||||
        List<BusAttendance> attendanceList = new ArrayList<>();
 | 
			
		||||
//        for (long i = 0; i < day; i++) {
 | 
			
		||||
@ -274,7 +288,7 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
 | 
			
		||||
        }
 | 
			
		||||
        // 添加审核状态
 | 
			
		||||
        String status = BusReviewStatusEnum.getEnumByOpinionStatus(leave.getGangerOpinion(), leave.getManagerOpinion());
 | 
			
		||||
        leaveVo.setStatus(status);
 | 
			
		||||
        leaveVo.setAuditStatus(status);
 | 
			
		||||
        return leaveVo;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -348,10 +362,152 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
 | 
			
		||||
            leaveVo.setTeamName(teamName);
 | 
			
		||||
            // 添加审核状态
 | 
			
		||||
            String status = BusReviewStatusEnum.getEnumByOpinionStatus(leave.getGangerOpinion(), leave.getManagerOpinion());
 | 
			
		||||
            leaveVo.setStatus(status);
 | 
			
		||||
            leaveVo.setAuditStatus(status);
 | 
			
		||||
            return leaveVo;
 | 
			
		||||
        }).toList();
 | 
			
		||||
        leaveVoPage.setRecords(leaveVoList);
 | 
			
		||||
        return leaveVoPage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Boolean isLeave(LocalDate date, Long userId) {
 | 
			
		||||
        LocalDateTime dateStart = LocalDateTime.of(date, LocalTime.MIN);
 | 
			
		||||
        LocalDateTime dateEnd = LocalDateTime.of(date, LocalTime.MAX);
 | 
			
		||||
 | 
			
		||||
        LambdaQueryWrapper<BusLeave> wrappers = new LambdaQueryWrapper<>();
 | 
			
		||||
        wrappers.eq(BusLeave::getUserId, userId)
 | 
			
		||||
            .eq(BusLeave::getAuditStatus, BusinessStatusEnum.FINISH.getStatus())
 | 
			
		||||
            .le(BusLeave::getStartTime, dateEnd)    // 请假开始时间 <= 当天结束时间
 | 
			
		||||
            .ge(BusLeave::getEndTime, dateStart);   // 请假结束时间 >= 当天开始时间
 | 
			
		||||
 | 
			
		||||
        return count(wrappers) > 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Long add(BusLeaveAddReq req) {
 | 
			
		||||
        // 1. 转换请求对象
 | 
			
		||||
        BusLeave leave = new BusLeave();
 | 
			
		||||
        BeanUtils.copyProperties(leave, req);
 | 
			
		||||
 | 
			
		||||
        // 2. 获取当前用户ID和时间区间
 | 
			
		||||
        Long userId = req.getUserId();
 | 
			
		||||
        LocalDateTime newStart = req.getStartTime();
 | 
			
		||||
        LocalDateTime newEnd = req.getEndTime();
 | 
			
		||||
 | 
			
		||||
        // 3. 构造查询条件
 | 
			
		||||
        LambdaQueryWrapper<BusLeave> wrapper = new LambdaQueryWrapper<>();
 | 
			
		||||
        wrapper
 | 
			
		||||
            .eq(BusLeave::getUserId, userId)
 | 
			
		||||
            .le(BusLeave::getStartTime, newEnd)     // 已有记录的开始时间 < 新记录的结束时间
 | 
			
		||||
            .ge(BusLeave::getEndTime, newStart);    // 已有记录的结束时间 > 新记录的开始时间
 | 
			
		||||
 | 
			
		||||
        // 4. 执行冲突校验
 | 
			
		||||
        if (count(wrapper) > 0) {
 | 
			
		||||
            throw new ServiceException("该时间段已存在请假申请记录", HttpStatus.BAD_REQUEST);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 5. 保存新记录(需补充完整字段赋值)
 | 
			
		||||
        leave.setUserTime(LocalDateTime.now());
 | 
			
		||||
        this.save(leave);
 | 
			
		||||
        return leave.getId();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TableDataInfo<BusLeaveVo> listByLoginUser(BusLeaveQueryReq req, PageQuery pageQuery) {
 | 
			
		||||
        LambdaQueryWrapper<BusLeave> lqw = new LambdaQueryWrapper<>();
 | 
			
		||||
 | 
			
		||||
        lqw.eq(ObjectUtils.isNotEmpty(req.getUserId()), BusLeave::getUserId, req.getUserId());
 | 
			
		||||
 | 
			
		||||
        List<BusUserProjectRelevancy> relevancyList = userProjectRelevancyService.list(
 | 
			
		||||
            Wrappers.lambdaQuery(BusUserProjectRelevancy.class)
 | 
			
		||||
            .eq(BusUserProjectRelevancy::getProjectId, req.getProjectId())
 | 
			
		||||
            .eq(BusUserProjectRelevancy::getUserId, req.getUserId()));
 | 
			
		||||
 | 
			
		||||
        boolean b = relevancyList.stream().anyMatch(relevancy -> "2".equals(relevancy.getUserType()));
 | 
			
		||||
 | 
			
		||||
        lqw.eq(!b, BusLeave::getProjectId, req.getProjectId());
 | 
			
		||||
        // 新增日期范围筛选条件
 | 
			
		||||
        if (req.getDate() != null) {
 | 
			
		||||
            LocalDateTime dateStart = LocalDateTime.of(req.getDate(), LocalTime.MIN);
 | 
			
		||||
            LocalDateTime dateEnd = LocalDateTime.of(req.getDate(), LocalTime.MAX);
 | 
			
		||||
 | 
			
		||||
            lqw.and(wrapper -> wrapper
 | 
			
		||||
                .le(BusLeave::getStartTime, dateEnd)     // 开始时间 ≤ 当天结束时间
 | 
			
		||||
                .ge(BusLeave::getEndTime, dateStart)    // 结束时间 ≥ 当天开始时间
 | 
			
		||||
        );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        Page<BusLeave> result = this.page(pageQuery.build(), lqw);
 | 
			
		||||
        return TableDataInfo.build(this.getVoPage(result));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
 | 
			
		||||
     * 正常使用只需#processEvent.flowCode=='leave1'
 | 
			
		||||
     * 示例为了方便则使用startsWith匹配了全部示例key
 | 
			
		||||
     *
 | 
			
		||||
     * @param processEvent 参数
 | 
			
		||||
     */
 | 
			
		||||
    @org.springframework.context.event.EventListener(condition = "#processEvent.flowCode.startsWith('projectLeave')")
 | 
			
		||||
    public void processHandler(ProcessEvent processEvent) {
 | 
			
		||||
        log.info("项目请假任务执行了{}", processEvent.toString());
 | 
			
		||||
        BusLeave busLeave = baseMapper.selectById(Convert.toLong(processEvent.getBusinessId()));
 | 
			
		||||
        busLeave.setAuditStatus(processEvent.getStatus());
 | 
			
		||||
        // 用于例如审批附件 审批意见等 存储到业务表内 自行根据业务实现存储流程
 | 
			
		||||
//        Map<String, Object> params = processEvent.getParams();
 | 
			
		||||
//        if (MapUtil.isNotEmpty(params)) {
 | 
			
		||||
//            // 历史任务扩展(通常为附件)
 | 
			
		||||
//            String hisTaskExt = Convert.toStr(params.get("hisTaskExt"));
 | 
			
		||||
//            // 办理人
 | 
			
		||||
//            String handler = Convert.toStr(params.get("handler"));
 | 
			
		||||
//            // 办理意见
 | 
			
		||||
//            String message = Convert.toStr(params.get("message"));
 | 
			
		||||
//        }
 | 
			
		||||
        if (processEvent.getSubmit()) {
 | 
			
		||||
            busLeave.setAuditStatus(BusinessStatusEnum.WAITING.getStatus());
 | 
			
		||||
        }
 | 
			
		||||
        baseMapper.updateById(busLeave);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 执行任务创建监听
 | 
			
		||||
     * 示例:也可通过  @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
 | 
			
		||||
     * 在方法中判断流程节点key
 | 
			
		||||
     * if ("xxx".equals(processTaskEvent.getNodeCode())) {
 | 
			
		||||
     * //执行业务逻辑
 | 
			
		||||
     * }
 | 
			
		||||
     *
 | 
			
		||||
     * @param processTaskEvent 参数
 | 
			
		||||
     */
 | 
			
		||||
    @org.springframework.context.event.EventListener(condition = "#processTaskEvent.flowCode.startsWith('projectLeave')")
 | 
			
		||||
    public void processTaskHandler(ProcessTaskEvent processTaskEvent) {
 | 
			
		||||
        log.info("项目请假任务创建了{}", processTaskEvent.toString());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 监听删除流程事件
 | 
			
		||||
     * 正常使用只需#processDeleteEvent.flowCode=='leave1'
 | 
			
		||||
     * 示例为了方便则使用startsWith匹配了全部示例key
 | 
			
		||||
     *
 | 
			
		||||
     * @param processDeleteEvent 参数
 | 
			
		||||
     */
 | 
			
		||||
    @EventListener(condition = "#processDeleteEvent.flowCode.startsWith('projectLeave')")
 | 
			
		||||
    public void processDeleteHandler(ProcessDeleteEvent processDeleteEvent) {
 | 
			
		||||
        log.info("监听删除流程事件,项目请假任务执行了{}", processDeleteEvent.toString());
 | 
			
		||||
//        BusLeave busLeave = baseMapper.selectById(Convert.toLong(processDeleteEvent.getBusinessId()));
 | 
			
		||||
//        if (ObjectUtil.isNull(busLeave)) {
 | 
			
		||||
//            return;
 | 
			
		||||
//        }
 | 
			
		||||
//        baseMapper.deleteById(busLeave.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,21 +1,27 @@
 | 
			
		||||
package org.dromara.project.service.impl;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.bean.BeanUtil;
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import cn.hutool.core.convert.Convert;
 | 
			
		||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 | 
			
		||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 | 
			
		||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 | 
			
		||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 | 
			
		||||
import jakarta.annotation.Resource;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.dromara.common.core.constant.HttpStatus;
 | 
			
		||||
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
 | 
			
		||||
import org.dromara.common.core.domain.event.ProcessEvent;
 | 
			
		||||
import org.dromara.common.core.domain.event.ProcessTaskEvent;
 | 
			
		||||
import org.dromara.common.core.enums.BusinessStatusEnum;
 | 
			
		||||
import org.dromara.common.core.exception.ServiceException;
 | 
			
		||||
import org.dromara.common.core.utils.DateUtils;
 | 
			
		||||
import org.dromara.common.core.utils.ObjectUtils;
 | 
			
		||||
import org.dromara.common.core.utils.StringUtils;
 | 
			
		||||
import org.dromara.common.mybatis.core.page.PageQuery;
 | 
			
		||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
 | 
			
		||||
import org.dromara.project.domain.BusAttendance;
 | 
			
		||||
import org.dromara.project.domain.BusProject;
 | 
			
		||||
import org.dromara.project.domain.BusProjectTeam;
 | 
			
		||||
import org.dromara.project.domain.BusReissueCard;
 | 
			
		||||
import org.dromara.project.domain.*;
 | 
			
		||||
import org.dromara.project.domain.dto.reissuecard.BusReissueCardAddReq;
 | 
			
		||||
import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum;
 | 
			
		||||
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
 | 
			
		||||
import org.dromara.project.domain.enums.BusOpinionStatusEnum;
 | 
			
		||||
@ -24,14 +30,14 @@ import org.dromara.project.domain.dto.reissuecard.BusReissueCardManagerReviewReq
 | 
			
		||||
import org.dromara.project.domain.dto.reissuecard.BusReissueCardQueryReq;
 | 
			
		||||
import org.dromara.project.domain.vo.reissuecard.BusReissueCardVo;
 | 
			
		||||
import org.dromara.project.mapper.BusReissueCardMapper;
 | 
			
		||||
import org.dromara.project.service.IBusAttendanceService;
 | 
			
		||||
import org.dromara.project.service.IBusProjectService;
 | 
			
		||||
import org.dromara.project.service.IBusProjectTeamService;
 | 
			
		||||
import org.dromara.project.service.IBusReissueCardService;
 | 
			
		||||
import org.dromara.project.service.*;
 | 
			
		||||
import org.springframework.beans.BeanUtils;
 | 
			
		||||
import org.springframework.context.event.EventListener;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.time.LocalTime;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
@ -42,6 +48,7 @@ import java.util.stream.Collectors;
 | 
			
		||||
 * @date 2025-04-08
 | 
			
		||||
 */
 | 
			
		||||
@Service
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class BusReissueCardServiceImpl extends ServiceImpl<BusReissueCardMapper, BusReissueCard>
 | 
			
		||||
    implements IBusReissueCardService {
 | 
			
		||||
 | 
			
		||||
@ -53,6 +60,8 @@ public class BusReissueCardServiceImpl extends ServiceImpl<BusReissueCardMapper,
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private IBusAttendanceService attendanceService;
 | 
			
		||||
    @Resource
 | 
			
		||||
    private  IBusUserProjectRelevancyService userProjectRelevancyService;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询施工人员补卡申请
 | 
			
		||||
@ -275,4 +284,116 @@ public class BusReissueCardServiceImpl extends ServiceImpl<BusReissueCardMapper,
 | 
			
		||||
        reissueCardVoPage.setRecords(reissueCardVoList);
 | 
			
		||||
        return reissueCardVoPage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TableDataInfo<BusReissueCardVo> listByLoginUser(BusReissueCardQueryReq req, PageQuery pageQuery) {
 | 
			
		||||
 | 
			
		||||
        LambdaQueryWrapper<BusReissueCard> lqw = new LambdaQueryWrapper<>();
 | 
			
		||||
 | 
			
		||||
        lqw.eq(ObjectUtils.isNotEmpty(req.getUserId()), BusReissueCard::getUserId, req.getUserId());
 | 
			
		||||
 | 
			
		||||
        List<BusUserProjectRelevancy> relevancyList = userProjectRelevancyService.list(
 | 
			
		||||
            Wrappers.lambdaQuery(BusUserProjectRelevancy.class)
 | 
			
		||||
                .eq(BusUserProjectRelevancy::getProjectId, req.getProjectId())
 | 
			
		||||
                .eq(BusUserProjectRelevancy::getUserId, req.getUserId()));
 | 
			
		||||
 | 
			
		||||
        boolean b = relevancyList.stream().anyMatch(relevancy -> "2".equals(relevancy.getUserType()));
 | 
			
		||||
 | 
			
		||||
        lqw.eq(!b, BusReissueCard::getProjectId, req.getProjectId());
 | 
			
		||||
        // 新增日期范围筛选条件
 | 
			
		||||
        if (req.getDate() != null) {
 | 
			
		||||
            LocalDateTime dateStart = LocalDateTime.of(req.getDate(), LocalTime.MIN);
 | 
			
		||||
            LocalDateTime dateEnd = LocalDateTime.of(req.getDate(), LocalTime.MAX);
 | 
			
		||||
 | 
			
		||||
            // 结束时间 ≥ 当天开始时间
 | 
			
		||||
            lqw.between(BusReissueCard::getUserTime, dateStart, dateEnd);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Page<BusReissueCard> result = this.page(pageQuery.build(), lqw);
 | 
			
		||||
        return TableDataInfo.build(this.getVoPage(result));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Long add(BusReissueCardAddReq req) {
 | 
			
		||||
        BusReissueCard bean = BeanUtil.toBean(req, BusReissueCard.class);
 | 
			
		||||
 | 
			
		||||
        //查看是否已提交该id的申请
 | 
			
		||||
        List<BusReissueCard> busReissueCards = baseMapper.selectList(Wrappers.<BusReissueCard>lambdaQuery()
 | 
			
		||||
            .eq(BusReissueCard::getAttendanceId, bean.getAttendanceId()));
 | 
			
		||||
        if (CollUtil.isNotEmpty(busReissueCards)) {
 | 
			
		||||
            throw new ServiceException("已提交该申请");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        save(bean);
 | 
			
		||||
        return bean.getId();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
 | 
			
		||||
     * 正常使用只需#processEvent.flowCode=='leave1'
 | 
			
		||||
     * 示例为了方便则使用startsWith匹配了全部示例key
 | 
			
		||||
     *
 | 
			
		||||
     * @param processEvent 参数
 | 
			
		||||
     */
 | 
			
		||||
    @org.springframework.context.event.EventListener(condition = "#processEvent.flowCode.startsWith('projectLeave')")
 | 
			
		||||
    public void processHandler(ProcessEvent processEvent) {
 | 
			
		||||
        log.info("项目补卡任务执行了{}", processEvent.toString());
 | 
			
		||||
        BusReissueCard busReissueCard = baseMapper.selectById(Convert.toLong(processEvent.getBusinessId()));
 | 
			
		||||
        busReissueCard.setStatus(processEvent.getStatus());
 | 
			
		||||
        // 用于例如审批附件 审批意见等 存储到业务表内 自行根据业务实现存储流程
 | 
			
		||||
//        Map<String, Object> params = processEvent.getParams();
 | 
			
		||||
//        if (MapUtil.isNotEmpty(params)) {
 | 
			
		||||
//            // 历史任务扩展(通常为附件)
 | 
			
		||||
//            String hisTaskExt = Convert.toStr(params.get("hisTaskExt"));
 | 
			
		||||
//            // 办理人
 | 
			
		||||
//            String handler = Convert.toStr(params.get("handler"));
 | 
			
		||||
//            // 办理意见
 | 
			
		||||
//            String message = Convert.toStr(params.get("message"));
 | 
			
		||||
//        }
 | 
			
		||||
        if (processEvent.getSubmit()) {
 | 
			
		||||
            busReissueCard.setStatus(BusinessStatusEnum.WAITING.getStatus());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(BusinessStatusEnum.FINISH.getStatus().equals(processEvent.getStatus())){
 | 
			
		||||
            BusAttendance byId = attendanceService.getById(busReissueCard.getAttendanceId());
 | 
			
		||||
            byId.setClockStatus(BusAttendanceClockStatusEnum.REISSUE.getValue());
 | 
			
		||||
        }
 | 
			
		||||
        if(processEvent.getSubmit())
 | 
			
		||||
 | 
			
		||||
        baseMapper.updateById(busReissueCard);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 执行任务创建监听
 | 
			
		||||
     * 示例:也可通过  @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
 | 
			
		||||
     * 在方法中判断流程节点key
 | 
			
		||||
     * if ("xxx".equals(processTaskEvent.getNodeCode())) {
 | 
			
		||||
     * //执行业务逻辑
 | 
			
		||||
     * }
 | 
			
		||||
     *
 | 
			
		||||
     * @param processTaskEvent 参数
 | 
			
		||||
     */
 | 
			
		||||
    @org.springframework.context.event.EventListener(condition = "#processTaskEvent.flowCode.startsWith('projectLeave')")
 | 
			
		||||
    public void processTaskHandler(ProcessTaskEvent processTaskEvent) {
 | 
			
		||||
        log.info("项目补卡任务创建了{}", processTaskEvent.toString());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 监听删除流程事件
 | 
			
		||||
     * 正常使用只需#processDeleteEvent.flowCode=='leave1'
 | 
			
		||||
     * 示例为了方便则使用startsWith匹配了全部示例key
 | 
			
		||||
     *
 | 
			
		||||
     * @param processDeleteEvent 参数
 | 
			
		||||
     */
 | 
			
		||||
    @EventListener(condition = "#processDeleteEvent.flowCode.startsWith('projectLeave')")
 | 
			
		||||
    public void processDeleteHandler(ProcessDeleteEvent processDeleteEvent) {
 | 
			
		||||
        log.info("监听删除流程事件,项目补卡任务执行了{}", processDeleteEvent.toString());
 | 
			
		||||
//        BusLeave busLeave = baseMapper.selectById(Convert.toLong(processDeleteEvent.getBusinessId()));
 | 
			
		||||
//        if (ObjectUtil.isNull(busLeave)) {
 | 
			
		||||
//            return;
 | 
			
		||||
//        }
 | 
			
		||||
//        baseMapper.deleteById(busLeave.getId());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user