This commit is contained in:
zt
2025-09-06 19:20:40 +08:00
parent 96d0406931
commit da0dd8f78f
12 changed files with 213 additions and 67 deletions

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.math.BigDecimal;
/**
* 物资-批次需求计划与采购单关联对象 bus_plan_doc_association
@ -37,6 +38,11 @@ public class BusPlanDocAssociation extends BaseEntity {
*/
private Long planId;
/**
* 需求数量
*/
private BigDecimal demandQuantity;
/**
* 采购联系单id
*/

View File

@ -9,6 +9,8 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
/**
* 物资-批次需求计划与采购单关联业务对象 bus_plan_doc_association
*
@ -41,5 +43,8 @@ public class BusPlanDocAssociationBo extends BaseEntity {
*/
private Long docId;
/**
* 需求数量
*/
private BigDecimal demandQuantity;
}

View File

@ -10,6 +10,7 @@ import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
@ -52,5 +53,8 @@ public class BusPlanDocAssociationVo implements Serializable {
@ExcelProperty(value = "采购联系单id")
private Long docId;
/**
* 需求数量
*/
private BigDecimal demandQuantity;
}

View File

@ -57,6 +57,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.net.URLEncoder;
@ -69,6 +70,7 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* 物资-采购联系单Service业务层处理
@ -184,6 +186,7 @@ public class BusPurchaseDocServiceImpl extends ServiceImpl<BusPurchaseDocMapper,
BusPurchaseDoc add = MapstructUtils.convert(bo, BusPurchaseDoc.class);
validEntityBeforeSave(add);
validNum(bo.getAssociationList());
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
@ -199,6 +202,30 @@ public class BusPurchaseDocServiceImpl extends ServiceImpl<BusPurchaseDocMapper,
return flag;
}
public void validNum(List<BusPlanDocAssociationBo> associationList){
for (BusPlanDocAssociationBo association : associationList) {
BusMaterialbatchdemandplan byId = materialbatchdemandplanService.getById(association.getPlanId());
List<BusPlanDocAssociation> list = planDocAssociationService.list(Wrappers.lambdaQuery(BusPlanDocAssociation.class)
.eq(BusPlanDocAssociation::getPlanId, association.getPlanId()));
BigDecimal total = list.stream()
.map(BusPlanDocAssociation::getDemandQuantity)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
if(total.add(association.getDemandQuantity()).compareTo(byId.getDemandQuantity()) > 0){
throw new ServiceException("材料:" + byId.getName() + "已超出计划单的物料批次需求计划数量");
}
}
}
/**
* 修改物资-采购联系单
*
@ -320,8 +347,9 @@ public class BusPurchaseDocServiceImpl extends ServiceImpl<BusPurchaseDocMapper,
.eq(BusPlanDocAssociation::getDocId, purchaseDoc.getId())
.list();
if (CollUtil.isNotEmpty(planDocAssociationList)) {
List<Long> planIds = planDocAssociationList.stream().map(BusPlanDocAssociation::getPlanId).toList();
items = materialbatchdemandplanService.listByIds(planIds);
Map<Long, BigDecimal> map = planDocAssociationList.stream().collect(Collectors.toMap(BusPlanDocAssociation::getPlanId, BusPlanDocAssociation::getDemandQuantity));
items = materialbatchdemandplanService.listByIds(map.keySet());
items.forEach(item -> item.setDemandQuantity(map.get(item.getId())));
}
BusPurchaseDocWordDto data = this.getReplacementDto(purchaseDoc, items);
Path newTargetDir = Paths.get(System.getProperty("user.dir"), constant.getBusPurchaseDocFileUrl(purchaseDoc, now));

View File

@ -260,39 +260,53 @@ public class PdfBoxQrCodeGenerator {
int numberOfPages = pdfDoc.getNumberOfPages();
// 默认放大倍数为10倍
float scaleMultiplier = 10.0f;
float baseQrSize = 80f;
float qrSize = baseQrSize * scaleMultiplier;
for (int pageNum = 1; pageNum <= numberOfPages; pageNum++) {
PdfPage page = pdfDoc.getPage(pageNum);
Rectangle pageSize = page.getPageSize();
float pageWidth = pageSize.getWidth();
float pageHeight = pageSize.getHeight();
// 获取页面的实际可见区域(裁剪框)
Rectangle cropBox = page.getCropBox();
if (cropBox == null) {
cropBox = page.getPageSize();
}
// 确保二维码尺寸不会超过页面尺寸的80%
float maxQrSize = Math.min(pageWidth, pageHeight) * 0.8f;
float finalQrSize = Math.min(qrSize, maxQrSize);
float pageWidth = cropBox.getWidth();
float pageHeight = cropBox.getHeight();
// 将二维码放在页面中央
float qrX = (pageWidth - finalQrSize) / 2;
float qrY = (pageHeight - finalQrSize) / 2;
// 输出页面尺寸信息
System.out.println("页面 " + pageNum + " 宽度: " + pageWidth + ", 高度: " + pageHeight);
// 根据页面大小动态计算二维码尺寸页面宽度的15%
float qrSize = pageWidth * 0.15f;
// 设置边距页面宽度的2%
float margin = pageWidth * 0.02f;
// 计算二维码位置 - 左上角
// 注意PDF坐标系的原点在左下角所以Y坐标需要从页面高度减去二维码高度和边距
float qrX = cropBox.getLeft() + margin;
float qrY = cropBox.getTop() - qrSize - margin;
try {
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc);
try (Canvas canvas = new Canvas(pdfCanvas, pageSize)) {
ImageData imageData = ImageDataFactory.create(qrCodeBytes);
com.itextpdf.layout.element.Image image = new com.itextpdf.layout.element.Image(imageData);
image.scaleAbsolute(finalQrSize, finalQrSize);
image.setFixedPosition(qrX, qrY);
canvas.add(image);
}
// 使用最简单的方法:直接添加图像
addQRCodeSimple(pdfDoc, page, qrCodeBytes, qrX, qrY, qrSize);
} catch (Exception e) {
System.err.println("在页面 " + pageNum + " 添加二维码时出错: " + e.getMessage());
e.printStackTrace();
// 尝试使用Canvas方法作为备用
try {
addQRCodeWithCanvas(pdfDoc, page, qrCodeBytes, qrX, qrY, qrSize, cropBox);
} catch (Exception ex) {
System.err.println("Canvas备用方法也失败: " + ex.getMessage());
// 最后尝试使用原始大小
try {
addQRCodeSimple(pdfDoc, page, qrCodeBytes, qrX, qrY, 50); // 使用固定大小
} catch (Exception ex2) {
System.err.println("最简单方法也失败: " + ex2.getMessage());
}
}
}
}
@ -300,10 +314,85 @@ public class PdfBoxQrCodeGenerator {
return pdfOut;
}
// 使用Canvas的备用方法
private static void addQRCodeWithCanvas(PdfDocument pdfDoc, PdfPage page,
byte[] qrCodeBytes, float x, float y, float size, Rectangle pageSize) throws IOException {
// 如果使用带放大倍数参数的方法需要修改main方法
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc);
try (Canvas canvas = new Canvas(pdfCanvas, pageSize)) {
ImageData imageData = ImageDataFactory.create(qrCodeBytes);
com.itextpdf.layout.element.Image image = new com.itextpdf.layout.element.Image(imageData);
// 设置二维码尺寸和位置
image.scaleAbsolute(size, size);
image.setFixedPosition(x, y);
// 设置透明度确保不会被背景遮挡
image.setOpacity(0.9f);
canvas.add(image);
}
}
// 最简单的方法:使用原始图像大小
private static void addQRCodeSimple(PdfDocument pdfDoc, PdfPage page,
byte[] qrCodeBytes, float x, float y, float size) throws IOException {
PdfCanvas canvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc);
// 创建图像对象
ImageData imageData = ImageDataFactory.create(qrCodeBytes);
com.itextpdf.kernel.pdf.xobject.PdfImageXObject imageXObject =
new com.itextpdf.kernel.pdf.xobject.PdfImageXObject(imageData);
// 添加图像到指定位置(使用原始大小)
canvas.addXObjectAt(imageXObject, x, y);
canvas.release();
}
public static void simpleTest(String pdfPath, String outputPath, byte[] qrCodeBytes) {
try {
PdfDocument pdfDoc = new PdfDocument(new PdfReader(pdfPath), new PdfWriter(outputPath));
for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
PdfPage page = pdfDoc.getPage(i);
Rectangle rect = page.getPageSize();
// 简单地在左上角添加一个固定大小的二维码
PdfCanvas canvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc);
ImageData imageData = ImageDataFactory.create(qrCodeBytes);
com.itextpdf.kernel.pdf.xobject.PdfImageXObject imageXObject =
new com.itextpdf.kernel.pdf.xobject.PdfImageXObject(imageData);
// 固定位置和大小
float x = 20; // 固定X位置
float y = rect.getHeight() - 70; // 固定Y位置
canvas.addXObjectAt(imageXObject, x, y);
canvas.release();
}
pdfDoc.close();
System.out.println("简单测试完成");
} catch (Exception e) {
e.printStackTrace();
}
}
// public static void main(String[] args) {
// String path = "C:\\Users\\YuanJie\\Desktop\\test.pdf";
// String outputPath = "C:\\Users\\YuanJie\\Desktop\\test1.pdf";
// String params = "http://192.168.110.151:7788/codeDetail?id=" + "1957649652924448769";
// byte[] bytes = PdfBoxQrCodeGenerator.generateQRCodeBytes(params);
// simpleTest(path, outputPath, bytes);
// }
// 如果使用带放大倍数参数的方法需要修改main方法
public static void main(String[] args) {
String path = "C:\\Users\\YuanJie\\Desktop\\test.pdf";
//合规性手续业务流 test 测试101_101
String path = "C:\\Users\\YuanJie\\Desktop\\合规性手续业务流.pdf";
String outputPath = "C:\\Users\\YuanJie\\Desktop\\test1.pdf";
String params = "http://192.168.110.151:7788/codeDetail?id=" + "1957649652924448769";

View File

@ -8,6 +8,8 @@ import org.dromara.design.domain.DesVolumeFile;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
/**
@ -80,4 +82,7 @@ public class DesVolumeFileCodeVo implements Serializable {
* 是否最新
*/
private Boolean isLatest;
private Date createTime;
}

View File

@ -138,8 +138,13 @@ public class AttendanceJob {
manageUserIds.add(relevancy.getUserId());
busAttendance.setProjectId(0L);
}
SubConstructionUser constructionUser = constructionUserService.getBySysUserId(relevancy.getUserId());
SubConstructionUser constructionUser = constructionUserService.lambdaQuery()
.eq(SubConstructionUser::getSysUserId, relevancy.getUserId())
.last("limit 1")
.one();
if(constructionUser==null){
continue;
}
busAttendance.setUserId(relevancy.getUserId());
busAttendance.setUserName(constructionUser.getUserName());
@ -251,7 +256,15 @@ public class AttendanceJob {
busAttendance.setProjectId(0L);
}
SubConstructionUser constructionUser = constructionUserService.getBySysUserId(relevancy.getUserId());
SubConstructionUser constructionUser = constructionUserService.lambdaQuery()
.eq(SubConstructionUser::getSysUserId, relevancy.getUserId())
.last("limit 1")
.one();
if(constructionUser==null){
continue;
}
busAttendance.setUserId(relevancy.getUserId());
busAttendance.setUserName(constructionUser.getUserName());

View File

@ -133,10 +133,10 @@ public class OutMonthPlanController extends BaseController {
* 获取该月份3种类型计划产值
*/
@SaCheckPermission("out:monthPlan:monthInfo")
@GetMapping("/monthInfo")
public R<List<OutMonthPlanVo>> infoByPlanMonth(@NotNull(message = "项目ID不能为空") Long projectId,
@NotNull(message = "计划月份不能为空") String planMonth) {
return R.ok(outMonthPlanService.infoByPlanMonth(projectId, planMonth));
@GetMapping("/monthInfo/{id}")
public R<List<OutMonthPlanVo>> infoByPlanMonth(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(outMonthPlanService.infoByPlanMonth(id));
}

View File

@ -98,7 +98,7 @@ public interface IOutMonthPlanService extends IService<OutMonthPlan>{
/**
* 根据计划月份查询计划
*/
List<OutMonthPlanVo> infoByPlanMonth(Long projectId, String planMonth);
List<OutMonthPlanVo> infoByPlanMonth(Long id);
/**
* 采购完工产值对甲

View File

@ -239,10 +239,9 @@ public class OutMonthPlanServiceImpl extends ServiceImpl<OutMonthPlanMapper, Out
}
@Override
public List<OutMonthPlanVo> infoByPlanMonth(Long projectId, String planMonth) {
public List<OutMonthPlanVo> infoByPlanMonth(Long id) {
return baseMapper.selectVoList(Wrappers.<OutMonthPlan>lambdaQuery()
.eq(OutMonthPlan::getProjectId, projectId)
.eq(OutMonthPlan::getPlanMonth, planMonth)
.eq(OutMonthPlan::getId, id)
);
}
@ -299,31 +298,21 @@ public class OutMonthPlanServiceImpl extends ServiceImpl<OutMonthPlanMapper, Out
@EventListener(condition = "#processEvent.flowCode.endsWith('monthPlan')")
public void monthPlanProcessHandler(ProcessEvent processEvent) {
log.info("月度计划产值审核任务执行了{}", processEvent.toString());
//这里的业务id项目id_月份
//这里的业务idid_plan
String str = Convert.toStr(processEvent.getBusinessId());
String[] split = str.split("_");
List<OutMonthPlan> outMonthPlans = baseMapper.selectList(Wrappers.<OutMonthPlan>lambdaQuery()
.eq(OutMonthPlan::getProjectId, split[0])
.eq(OutMonthPlan::getPlanMonth, split[1])
);
log.info("月度计划产值审核任务,计划数量{}", outMonthPlans.size());
outMonthPlans.forEach(outMonthPlan -> {
OutMonthPlan outMonthPlan = baseMapper.selectById(Long.valueOf(split[0]));
outMonthPlan.setPlanAuditStatus(processEvent.getStatus());
if (processEvent.getSubmit()) {
outMonthPlan.setPlanAuditStatus(BusinessStatusEnum.WAITING.getStatus());
}
log.info("月度计划产值审核任务状态改变后{}", outMonthPlan.toString());
});
updateById(outMonthPlan);
if(BusinessStatusEnum.FINISH.getStatus().equals(processEvent.getStatus())){
OutMonthPlanAudit outMonthPlanAudit = getOutMonthPlanAudit(outMonthPlans);
OutMonthPlanAudit outMonthPlanAudit = getOutMonthPlanAudit(outMonthPlan);
outMonthPlanAuditService.save(outMonthPlanAudit);
}
updateBatchById(outMonthPlans);
}
private static @NotNull OutMonthPlanAudit getOutMonthPlanAudit(List<OutMonthPlan> outMonthPlans) {
private static @NotNull OutMonthPlanAudit getOutMonthPlanAudit(OutMonthPlan outMonthPlan) {
OutMonthPlanAudit outMonthPlanAudit = new OutMonthPlanAudit();
for (OutMonthPlan outMonthPlan : outMonthPlans) {
outMonthPlanAudit.setProjectId(outMonthPlan.getProjectId());
outMonthPlanAudit.setPlanMonth(outMonthPlan.getPlanMonth());
if(outMonthPlan.getValueType().equals("1")){
@ -335,7 +324,7 @@ public class OutMonthPlanServiceImpl extends ServiceImpl<OutMonthPlanMapper, Out
if(outMonthPlan.getValueType().equals("3")){
outMonthPlanAudit.setConstructionValue(outMonthPlan.getPlanValue());
}
}
outMonthPlanAudit.setTotalValue(outMonthPlanAudit.getDesignValue().add(outMonthPlanAudit.getPurchaseValue()).add(outMonthPlanAudit.getConstructionValue()));
return outMonthPlanAudit;
}

View File

@ -349,7 +349,8 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
*/
private int getMinutesDifference(LocalDateTime actualTime, LocalTime expectedTime) {
LocalDateTime expectedDateTime = LocalDateTime.of(actualTime.toLocalDate(), expectedTime);
return (int) Duration.between(expectedDateTime, actualTime).toMinutes();
long minutesDiff = Duration.between(expectedDateTime, actualTime).toMinutes();
return Math.abs((int) minutesDiff); // 取绝对值
}
@ -525,18 +526,24 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
* 判断是否迟到
*/
private Boolean isLate(LocalDateTime checkTime, BusAttendanceRuleVo vo) {
// 获取上班时间和下班时间
LocalTime clockInTime = vo.getClockInTime();
LocalTime clockInResultTime = vo.getClockInResultTime();
long clockInSeconds = vo.getClockInTime().plusMinutes(1).toSecondOfDay();
long clockInResultSeconds = vo.getClockInResultTime().toSecondOfDay();
// 将实际打卡时间转换为当天的秒数
long localTime = checkTime.toLocalTime().toSecondOfDay();
// 将规定时间转换为当天的秒数
long clockInSeconds = clockInTime.toSecondOfDay();
long clockInResultSeconds = clockInResultTime.toSecondOfDay();
if (vo.getClockInResultTime().isBefore(vo.getClockInTime())) {
// 处理跨天情况如晚上8点上班第二天凌晨2点结束
if (clockInResultTime.isBefore(clockInTime)) {
clockInResultSeconds += 24 * 60 * 60; // 加24小时的秒数
}
long localTime = checkTime.toLocalTime().toSecondOfDay();
// 判断是否迟到
// 迟到定义:在规定上班时间之后,但在允许的最晚打卡时间之前
return localTime > clockInSeconds && localTime < clockInResultSeconds;
}

View File

@ -425,9 +425,9 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
throw new ServiceException("修改用户" + user.getUserName() + "信息失败");
}
// 没有修改部门则不需要修改用户与项目的关联
if (oldUser.getDeptId().equals(user.getDeptId())) {
return flag;
}
// if (oldUser.getDeptId().equals(user.getDeptId())) {
// return flag;
// }
/*Long deptId = user.getDeptId();
SysDeptVo deptVo = deptService.selectDeptById(deptId);
String deptType = deptVo.getDeptType();