采购历史增强代码

This commit is contained in:
2025-05-22 19:49:01 +08:00
parent 69de2b28cf
commit af5ae35562
31 changed files with 922 additions and 67 deletions

View File

@@ -1,5 +1,7 @@
package com.ruoyi.oa.controller;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
@@ -10,12 +12,16 @@ import com.ruoyi.common.excel.ExcelResult;
import com.ruoyi.oa.domain.SysOaWarehouseMaster;
import com.ruoyi.oa.domain.bo.SysOaWarehouseDetailBo;
import com.ruoyi.oa.domain.bo.SysOaWarehouseMasterBo;
import com.ruoyi.oa.domain.dto.MonthlyStatsDTO;
import com.ruoyi.oa.domain.dto.SummaryFilterDTO;
import com.ruoyi.oa.domain.vo.SummaryCardVo;
import com.ruoyi.oa.listener.SysOaWarehouseListener;
import com.ruoyi.oa.service.ISysOaWarehouseMasterService;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
@@ -188,4 +194,38 @@ public class SysOaWarehouseController extends BaseController {
public void importTemplate(HttpServletResponse response) {
ExcelUtil.exportExcel(new ArrayList<>(), "投诉工单", SysOaWarehouseVo.class, response);
}
@GetMapping("/recent")
public R<List<SysOaWarehouseVo>> selectRecentOutbound(@RequestParam(name = "limit", defaultValue = "10") int limit){
return R.ok(iSysOaWarehouseService.selectRecentOutbound(limit));
}
@GetMapping("/cards")
public R<List<SummaryCardVo>> summaryCards(
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime beginTime,
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime endTime,
@RequestParam(required = false) String name,
@RequestParam(required = false) String brand,
@RequestParam(required = false) String supplier
) {
SummaryFilterDTO filter = new SummaryFilterDTO();
filter.setBeginTime(beginTime);
filter.setEndTime(endTime);
filter.setName(name);
filter.setBrand(brand);
filter.setSupplier(supplier);
return R.ok(iSysOaWarehouseService.getSummaryCards(filter));
}
/**
* 获取某年 112 月的入库/出库/库存快照数据
* @param month 可选参数,格式 yyyy-MM-dd只读取其年份
*/
@GetMapping("/monthly")
public R<MonthlyStatsDTO> monthly( @RequestParam(required = false) String month ) {
return R.ok(iSysOaWarehouseService.getMonthlyStats(month));
}
}

View File

@@ -108,6 +108,15 @@ public class SysOaWarehouseMasterController extends BaseController {
return toAjax(iSysOaWarehouseMasterService.updateByBo(bo));
}
/**
* 修改出库单管理
*/
@RepeatSubmit()
@PutMapping("/updateMasterAndInsertBatchWare")
public R<Void> updateMasterAndInsertBatchWare(@Validated(EditGroup.class) @RequestBody SysOaWarehouseMasterBo bo) {
return toAjax(iSysOaWarehouseMasterService.updateMasterAndInsertBatchWare(bo));
}
/**
* 删除出库单管理
*

View File

@@ -111,6 +111,40 @@ public class SysOaWarehouseTaskController extends BaseController {
return toAjax(iSysOaWarehouseTaskService.updateByBo(bo));
}
/**
* 修改采购计划
*/
@Log(title = "采购计划", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/editBatch")
public R<Void> editBatch(@Validated(EditGroup.class) @RequestBody List<SysOaWarehouseTaskBo> bo) {
return toAjax(iSysOaWarehouseTaskService.updateByBoBatch(bo));
}
/**
* 处理单个物料入库
*/
@RepeatSubmit()
@PutMapping("/status")
public R<Void> status(@Validated(EditGroup.class) @RequestBody SysOaWarehouseTaskBo bo) {
return toAjax(iSysOaWarehouseTaskService.updateToWare(bo));
}
/**
* 处理单个物料入库
*/
@RepeatSubmit()
@PutMapping("/status-list")
public R<Void> status(@Validated(EditGroup.class) @RequestBody List<SysOaWarehouseTaskBo> boList) {
boList.forEach(bo -> {
int i = iSysOaWarehouseTaskService.updateToWare(bo);
});
return toAjax(1);
}
/**
* 删除采购计划
*

View File

@@ -50,5 +50,7 @@ public class SysOaWarehouseDetail extends BaseEntity {
private Double signPrice;
private Long fatherId;
}

View File

@@ -1,6 +1,7 @@
package com.ruoyi.oa.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
@@ -8,6 +9,7 @@ import java.util.Date;
import java.math.BigDecimal;
import com.ruoyi.common.core.domain.BaseEntity;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 采购计划对象 sys_oa_warehouse_task
@@ -66,4 +68,15 @@ public class SysOaWarehouseTask extends BaseEntity {
*/
private String remark;
/**
* 采购细节状态
*/
private Long taskStatus;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date endTime;
}

View File

@@ -80,5 +80,10 @@ public class SysOaWarehouseBo extends BaseEntity {
private Long warehouseId;
/**
* 批量新增时状态
*/
private Long taskStatus;
}

View File

@@ -66,4 +66,7 @@ public class SysOaWarehouseDetailBo extends BaseEntity {
// 当为1的时候为入库单
private Long type;
private Long fatherId;
}

View File

@@ -65,6 +65,11 @@ public class SysOaWarehouseMasterBo extends BaseEntity {
*/
private List<SysOaWarehouseDetailBo> warehouseList;
/**
* 采购物料详情列表
*/
private List<SysOaWarehouseTaskBo> warehouseTaskList;
private Long status;
}

View File

@@ -1,5 +1,6 @@
package com.ruoyi.oa.domain.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import lombok.Data;
@@ -9,6 +10,7 @@ import javax.validation.constraints.*;
import java.util.Date;
import com.ruoyi.common.core.domain.BaseEntity;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 采购计划业务对象 sys_oa_warehouse_task
@@ -71,5 +73,15 @@ public class SysOaWarehouseTaskBo extends BaseEntity {
*/
private Long id;
/**
* 采购细节状态
*/
private Long taskStatus;
private Double price;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date endTime;
}

View File

@@ -0,0 +1,40 @@
package com.ruoyi.oa.domain.dto;
import java.util.List;
import java.util.Map;
public class MonthlyStatsDTO {
/**
* key 为 "月"value 为 12 个点1 月12 月)
*/
private Map<String, List<Long>> inData;
private Map<String, List<Long>> outData;
private Map<String, List<Long>> dataMap;
// —— getters & setters ——
public Map<String, List<Long>> getInData() {
return inData;
}
public void setInData(Map<String, List<Long>> inData) {
this.inData = inData;
}
public Map<String, List<Long>> getOutData() {
return outData;
}
public void setOutData(Map<String, List<Long>> outData) {
this.outData = outData;
}
public Map<String, List<Long>> getDataMap() {
return dataMap;
}
public void setDataMap(Map<String, List<Long>> dataMap) {
this.dataMap = dataMap;
}
}

View File

@@ -0,0 +1,17 @@
package com.ruoyi.oa.domain.dto;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class SummaryFilterDTO {
private LocalDateTime beginTime;
private LocalDateTime endTime;
private String name;
private String brand;
private String supplier;
}

View File

@@ -0,0 +1,18 @@
package com.ruoyi.oa.domain.vo;
import lombok.Data;
@Data
public class SummaryCardVo {
private String title;
private Long value;
private Double trend;
public SummaryCardVo(String title, Long value, Double trend) {
this.title = title;
this.value = value;
this.trend = trend;
}
}

View File

@@ -69,4 +69,6 @@ public class SysOaWarehouseDetailVo extends BaseEntity {
private String specifications;
private String brand;
private Long fatherId;
}

View File

@@ -79,5 +79,6 @@ public class SysOaWarehouseMasterVo {
private Long status;
private Date nearestEndTime;
}

View File

@@ -2,9 +2,12 @@ package com.ruoyi.oa.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.convert.ExcelDictConvert;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@@ -73,5 +76,14 @@ public class SysOaWarehouseTaskVo {
*/
private Long warehouseId;
/**
* 采购细节状态
*/
private Long taskStatus;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date endTime;
}

View File

@@ -88,4 +88,10 @@ public class SysOaWarehouseVo extends SysOaWarehouse {
private Long threshold;
private Long taskInventory;
private Long lastInbound;
private Long lastOutbound;
}

View File

@@ -6,6 +6,7 @@ import com.ruoyi.oa.domain.bo.SysOaWarehouseDetailBo;
import com.ruoyi.oa.domain.vo.SysOaOutWarehouseListVo;
import com.ruoyi.oa.domain.vo.SysOaWarehouseDetailVo;
import com.ruoyi.common.core.mapper.BaseMapperPlus;
import com.ruoyi.oa.domain.vo.SysOaWarehouseVo;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@@ -32,4 +33,6 @@ public interface SysOaWarehouseDetailMapper extends BaseMapperPlus<SysOaWarehous
@Select("select * from sys_oa_warehouse_detail where project_id = #{projectId} and del_flag = 0")
List<SysOaWarehouseDetail> List(@Param("projectId") Long projectId);
List<SysOaWarehouseVo> selectRecentOutbound(int limit);
}

View File

@@ -5,10 +5,15 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.oa.domain.SysOaWarehouse;
import com.ruoyi.oa.domain.dto.SummaryFilterDTO;
import com.ruoyi.oa.domain.vo.SysOaWarehouseVo;
import com.ruoyi.common.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
/**
* 仓库管理Mapper接口
*
@@ -28,4 +33,33 @@ public interface SysOaWarehouseMapper extends BaseMapperPlus<SysOaWarehouseMappe
Page<SysOaWarehouseVo> selectVoPageThreshold(@Param("page")Page<SysOaWarehouseVo> build,@Param(Constants.WRAPPER) LambdaQueryWrapper<SysOaWarehouse> lqw);
Page<SysOaWarehouseVo> selectListVoPage(@Param("page")Page<SysOaWarehouseVo> build,@Param(Constants.WRAPPER) QueryWrapper<SysOaWarehouse> lqw);
/**
* 数据报表使用接口
*/
// 快照时点的库存总量
Long selectInventoryAt(@Param("f") SummaryFilterDTO filter);
// 区间内的在途物料
Long selectInTransitBetween(@Param("f") SummaryFilterDTO filter);
// 某日的入库量
Long selectInboundOn(@Param("f") SummaryFilterDTO filter);
// 某日的出库量
Long selectOutboundOn(@Param("f") SummaryFilterDTO filter);
// 某日的预警信息
Integer selectWarningOn(@Param("f") SummaryFilterDTO filter);
/** 年度入库量按月分组 */
List<Map<String,Object>> selectInboundByMonth(@Param("year") int year);
/** 年度出库量按月分组 */
List<Map<String,Object>> selectOutboundByMonth(@Param("year") int year);
/** 任意日期的库存快照 */
Long selectInventorySnapshot(@Param("date") LocalDate date);
}

View File

@@ -55,4 +55,12 @@ public interface ISysOaWarehouseMasterService {
* @return
*/
int insertInWarehouse(SysOaWarehouseBo bo, Long id);
/**
* 更新采购单状态 并且将未作废的以及未完成的 taskStatus=0,1的完成入库操作
* @param bo
* @return
*/
int updateMasterAndInsertBatchWare(SysOaWarehouseMasterBo bo);
}

View File

@@ -1,5 +1,8 @@
package com.ruoyi.oa.service;
import com.ruoyi.oa.domain.dto.MonthlyStatsDTO;
import com.ruoyi.oa.domain.dto.SummaryFilterDTO;
import com.ruoyi.oa.domain.vo.SummaryCardVo;
import com.ruoyi.oa.domain.vo.SysOaWarehouseVo;
import com.ruoyi.oa.domain.bo.SysOaWarehouseBo;
import com.ruoyi.common.core.page.TableDataInfo;
@@ -67,4 +70,19 @@ public interface ISysOaWarehouseService {
* @return
*/
Boolean insertBatch(List<SysOaWarehouseBo> boList);
/**
* 以下为数据分析专用
* @param filter
* @return
*/
List<SummaryCardVo> getSummaryCards(SummaryFilterDTO filter);
/**
* @param ymStr 格式 "yyyy-MM",可选;不传则默认当前年月
*/
MonthlyStatsDTO getMonthlyStats(String ymStr);
List<SysOaWarehouseVo> selectRecentOutbound(int limit);
}

View File

@@ -57,4 +57,8 @@ public interface ISysOaWarehouseTaskService {
*/
Boolean addBatch(List<SysOaWarehouseTaskBo> boList);
int updateByBoBatch(List<SysOaWarehouseTaskBo> bo);
int updateToWare(SysOaWarehouseTaskBo bo);
}

View File

@@ -243,28 +243,20 @@ public class SysOaAttendanceServiceImpl implements ISysOaAttendanceService {
Double overTime = 0.0;
Double tripDays = 0.0;
Double leaveCount = 0.0;
Double workDays = 0.0;
Set<Long> projSet = new HashSet<>();
for (SysOaAttendanceVo oaAttendanceVo : sysOaAttendanceVos) {
// 出差问题解决
// 出差
if (oaAttendanceVo.getProjectId() == 0) {
tripDays++;
} else if (oaAttendanceVo.getProjectId() == 1) {
leaveCount++;
}
if (oaAttendanceVo.getProjectId() != 0 && oaAttendanceVo.getProjectId() != 1) {
tripDays += oaAttendanceVo.getTripDays();
leaveCount+=oaAttendanceVo.getAbsenceDays();
workTimes += oaAttendanceVo.getWorkTimes();
hourWorkTimes += oaAttendanceVo.getHourWorkTimes();
overTime += oaAttendanceVo.getOverTime();
if (oaAttendanceVo.getProjectId() != 0L && oaAttendanceVo.getProjectId() != 1L) {
SysOaProjectVo sysOaProjectVo = projectService.queryById(oaAttendanceVo.getProjectId());
oaAttendanceVo.setColor(sysOaProjectVo.getColor());
oaAttendanceVo.setSysOaProjectVo(sysOaProjectVo);
oaAttendanceVo.setProjectName(sysOaProjectVo.getProjectName());
projectVos.add(sysOaProjectVo);
workTimes += oaAttendanceVo.getWorkTimes();
hourWorkTimes += oaAttendanceVo.getHourWorkTimes();
overTime += oaAttendanceVo.getOverTime();
projSet.add(oaAttendanceVo.getProjectId());
workDays++;
}
}
// 此为所有小时计的综合
@@ -281,7 +273,7 @@ public class SysOaAttendanceServiceImpl implements ISysOaAttendanceService {
laborCostData.setOvertime(overTime);
costDataList.add(laborCostData);
// 构造并保存记录
addGenData(firstDay, sysUser, tripDays, leaveCount, workDays, projSet, overTime);
addGenData(firstDay, sysUser, tripDays, leaveCount, workTimes, projSet, overTime);
}
@@ -297,9 +289,9 @@ public class SysOaAttendanceServiceImpl implements ISysOaAttendanceService {
// 当前操作人昵称
rec.setNickName(sysUser.getNickName());
rec.setUserId(sysUser.getUserId());
rec.setTrips(BigDecimal.valueOf(tripDays));
rec.setNotNum(BigDecimal.valueOf(leaveCount));
rec.setWorks(BigDecimal.valueOf(workDays));
rec.setTrips(new BigDecimal(tripDays.toString()));
rec.setNotNum(new BigDecimal(leaveCount.toString()));
rec.setWorks(new BigDecimal(workDays.toString()));
rec.setProjectIds(
String.join(",",
projSet.stream().map(String::valueOf).toArray(String[]::new)
@@ -362,7 +354,6 @@ public class SysOaAttendanceServiceImpl implements ISysOaAttendanceService {
// 将字符串拼接
format += dateLength;
format += " 23:59:59";
return DateUtils.parseDate(DateUtils.parseDateToStr(format, time));
}
}

View File

@@ -126,6 +126,7 @@ public class SysOaWarehouseDetailServiceImpl implements ISysOaWarehouseDetailSer
lqw.eq(bo.getProjectId() != null, SysOaWarehouseDetail::getProjectId, bo.getProjectId());
lqw.eq(bo.getAmount() != null, SysOaWarehouseDetail::getAmount, bo.getAmount());
lqw.eq(bo.getWarehouseId() != null, SysOaWarehouseDetail::getWarehouseId, bo.getWarehouseId());
lqw.eq(bo.getFatherId() != null, SysOaWarehouseDetail::getFatherId, bo.getFatherId());
return lqw;
}

View File

@@ -70,19 +70,31 @@ public class SysOaWarehouseMasterServiceImpl implements ISysOaWarehouseMasterSer
private QueryWrapper<SysOaWarehouseMaster> buildQueryWrapper(SysOaWarehouseMasterBo bo) {
Map<String, Object> params = bo.getParams();
QueryWrapper<SysOaWarehouseMaster> lqw = Wrappers.query();
lqw.eq(bo.getType() != null, "sowm.type", bo.getType());
lqw.eq(bo.getProjectId() != null, "sowm.project_id", bo.getProjectId());
lqw.eq(bo.getType() != null, "sowm.type", bo.getType())
.eq(bo.getProjectId()!= null, "sowm.project_id", bo.getProjectId())
// 其他过滤……
.eq("sowm.del_flag", 0)
.orderByDesc("sowm.create_time");
if (bo.getSignTime() != null) {
long time = bo.getSignTime().getTime();
lqw.apply(
"DATE(sowm.sign_time) = {0}", // MySQL DATE() 抽取日期部分
new Date(time)); // 20250513
// 只有在 type = 2 时,才附带这个子查询字段
if (bo.getType() != null && bo.getType() == 2L) {
lqw.select(
"sowm.*", // 先选出主表所有列
// 然后选出子查询,重命名为 nearest_end_time实体上需要有对应的 @TableField(exist = false) 字段)
"(SELECT COALESCE(\n" +
" MIN(CASE WHEN sowt.end_time > NOW() THEN sowt.end_time END),\n" +
" MAX(CASE WHEN sowt.end_time <= NOW() THEN sowt.end_time END)\n" +
")\n" +
"FROM sys_oa_warehouse_task sowt\n" +
"WHERE sowt.master_id = sowm.master_id\n" +
" AND sowt.task_status IN (0,1)\n" +
") AS nearest_end_time"
);
} else {
// 否则只选主表列
lqw.select("sowm.*");
}
lqw.like(StringUtils.isNotBlank(bo.getSignUser()), "sowm.sign_user", bo.getSignUser());
lqw.eq("sowm.del_flag", 0L);
lqw.orderByDesc("sowm.create_time");
return lqw;
}
@@ -112,7 +124,7 @@ public class SysOaWarehouseMasterServiceImpl implements ISysOaWarehouseMasterSer
*/
@Override
public Boolean updateByBo(SysOaWarehouseMasterBo bo) {
System.out.println(bo);
// 判断是否为采购单,采购单,用户是直接点击完成按钮,所以直接更新单子状态就可以
if (bo.getType() != 2L) {
SysOaWarehouseMaster update = BeanUtil.toBean(bo, SysOaWarehouseMaster.class);
@@ -124,12 +136,12 @@ public class SysOaWarehouseMasterServiceImpl implements ISysOaWarehouseMasterSer
sysOaWarehouseDetailBo.setMasterId(bo.getMasterId());
sysOaWarehouseDetailBo.setType(bo.getType());
warehouseDetailService.insertByBo(sysOaWarehouseDetailBo);
}
}
return flag;
} else {
SysOaWarehouseMaster update = BeanUtil.toBean(bo, SysOaWarehouseMaster.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
@@ -180,4 +192,59 @@ public class SysOaWarehouseMasterServiceImpl implements ISysOaWarehouseMasterSer
return flag;
}
@Override
public int updateMasterAndInsertBatchWare(SysOaWarehouseMasterBo bo) {
// 判断是否为采购单,采购单,用户是直接点击完成按钮,所以直接更新单子状态就可以
if (bo.getType() == 2L) {
SysOaWarehouseMaster update = BeanUtil.toBean(bo, SysOaWarehouseMaster.class);
validEntityBeforeSave(update);
int flag = baseMapper.updateById(update);
bo.getWarehouseList().forEach(warehouse -> {
});
// 判断是否为采购单,采购单,用户是直接点击完成按钮,所以直接更新单子状态就可以
// 我认为首先要先判断是否已经有此单子的入库单 如果有的话应该直接根据入库单id从而将其他的新增进去就可以了
return flag;
// // 获取是否存在此采购单的入库单
// if (bo.getType() == 2L) {
// for (SysOaWarehouseDetailBo sysOaWarehouseDetailBo : bo.getWarehouseList()) {
// Long taskStatus = item.getTaskStatus();
// if (taskStatus == 1|| taskStatus == 0) {
// item.setInventory(item.getTaskInventory());
// SysOaWarehouseDetailBo bo = new SysOaWarehouseDetailBo();
// bo.setAmount(item.getInventory());
// bo.setSignPrice(item.getPrice());
// Long warehouseId = insertByBo2(item);
// bo.setWarehouseId(warehouseId);
// list.add(bo);
// }
// }
// SysOaWarehouseMasterBo sysOaWarehouseMaster = new SysOaWarehouseMasterBo();
// sysOaWarehouseMaster.setType(1L);
// List<SysOaWarehouseDetailBo> list = new ArrayList<>();
// boList.forEach(item -> {
//
// });
// sysOaWarehouseMaster.setWarehouseList(list);
// sysOaWarehouseMaster.setMasterNum(UUID.randomUUID().toString());
// return masterService.insertByBo(sysOaWarehouseMaster);
// }
//
//
// // 如果不是2应该进不来 后面看一下是否删除掉
}
// 如果不是2应该进不来
return 0;
}
}

View File

@@ -10,6 +10,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.oa.domain.bo.SysOaWarehouseDetailBo;
import com.ruoyi.oa.domain.bo.SysOaWarehouseMasterBo;
import com.ruoyi.oa.domain.dto.MonthlyStatsDTO;
import com.ruoyi.oa.domain.dto.SummaryFilterDTO;
import com.ruoyi.oa.domain.vo.SummaryCardVo;
import com.ruoyi.oa.mapper.SysOaWarehouseDetailMapper;
import com.ruoyi.oa.service.ISysOaWarehouseMasterService;
import lombok.RequiredArgsConstructor;
@@ -21,6 +24,10 @@ import com.ruoyi.oa.domain.SysOaWarehouse;
import com.ruoyi.oa.mapper.SysOaWarehouseMapper;
import com.ruoyi.oa.service.ISysOaWarehouseService;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
@@ -39,6 +46,7 @@ public class SysOaWarehouseServiceImpl implements ISysOaWarehouseService {
private final SysOaWarehouseDetailMapper outWareMapper;
private final ISysOaWarehouseMasterService masterService;
/**
* 查询仓库管理
*/
@@ -54,14 +62,14 @@ public class SysOaWarehouseServiceImpl implements ISysOaWarehouseService {
public TableDataInfo<SysOaWarehouseVo> queryPageList(SysOaWarehouseBo bo, PageQuery pageQuery) {
QueryWrapper<SysOaWarehouse> lqw = new QueryWrapper<>();
lqw.eq("sow.del_flag", 0);
lqw.and(StringUtils.isNotBlank(bo.getName()),qw -> qw
.like( "sow.name", bo.getName())
lqw.and(StringUtils.isNotBlank(bo.getName()), qw -> qw
.like("sow.name", bo.getName())
.or()
.like("sow.brand", bo.getName())
.or()
.like("sow.model", bo.getName())
)
.eq(StringUtils.isNotBlank(bo.getModel()), "sow.model", bo.getModel())
.eq(StringUtils.isNotBlank(bo.getModel()), "sow.model", bo.getModel())
.eq(StringUtils.isNotBlank(bo.getBrand()), "sow.brand", bo.getBrand());
Page<SysOaWarehouseVo> result = baseMapper.selectListVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
@@ -71,22 +79,22 @@ public class SysOaWarehouseServiceImpl implements ISysOaWarehouseService {
public TableDataInfo<SysOaWarehouseVo> queryPageListThreshold(SysOaWarehouseBo bo, PageQuery pageQuery, boolean b) {
QueryWrapper<SysOaWarehouse> lqw = new QueryWrapper<>();
lqw.eq("sow.del_flag", 0);
if (b){
if (b) {
lqw.apply("sow.inventory < sow.threshold");
}else{
} else {
lqw.apply("sow.inventory >= sow.threshold");
}
lqw.eq(StringUtils.isNotBlank(bo.getModel()), "sow.model", bo.getModel());
lqw.eq(StringUtils.isNotBlank(bo.getBrand()), "sow.brand", bo.getBrand());
lqw.and(StringUtils.isNotBlank(bo.getName()),qw -> qw
.like( "sow.name", bo.getName())
lqw.and(StringUtils.isNotBlank(bo.getName()), qw -> qw
.like("sow.name", bo.getName())
.or()
.like("sow.brand", bo.getName())
.or()
.like("sow.model", bo.getName())
)
.eq(StringUtils.isNotBlank(bo.getModel()), "sow.model", bo.getModel())
.eq(StringUtils.isNotBlank(bo.getModel()), "sow.model", bo.getModel())
.eq(StringUtils.isNotBlank(bo.getBrand()), "sow.brand", bo.getBrand());
Page<SysOaWarehouseVo> result = baseMapper.selectListVoPage(pageQuery.build(), lqw);
@@ -106,12 +114,14 @@ public class SysOaWarehouseServiceImpl implements ISysOaWarehouseService {
Long warehouseId = insertByBo2(item);
bo.setWarehouseId(warehouseId);
list.add(bo);
});
sysOaWarehouseMaster.setWarehouseList(list);
sysOaWarehouseMaster.setMasterNum(UUID.randomUUID().toString());
return masterService.insertByBo(sysOaWarehouseMaster);
}
/**
* 查询仓库管理列表
*/
@@ -132,7 +142,6 @@ public class SysOaWarehouseServiceImpl implements ISysOaWarehouseService {
}
private LambdaQueryWrapper<SysOaWarehouse> buildQueryWrapper(SysOaWarehouseBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<SysOaWarehouse> lqw = Wrappers.lambdaQuery();
@@ -162,11 +171,11 @@ public class SysOaWarehouseServiceImpl implements ISysOaWarehouseService {
Long flag;
if (select == null) {
baseMapper.insert(add);
flag = add.getId();
flag = add.getId();
} else {
select.setInventory(select.getInventory() + bo.getInventory());
select.setPrice((select.getPrice()*select.getInventory() + bo.getPrice()*bo.getInventory())/(select.getInventory()+bo.getInventory()));
flag = select.getId();
select.setPrice((select.getPrice() * select.getInventory() + bo.getPrice() * bo.getInventory()) / (select.getInventory() + bo.getInventory()));
flag = select.getId();
}
return flag;
@@ -189,9 +198,8 @@ public class SysOaWarehouseServiceImpl implements ISysOaWarehouseService {
baseMapper.insert(add);
return add.getId();
} else {
System.out.println(select);
select.setInventory(select.getInventory() + bo.getTaskInventory());
select.setPrice((select.getPrice()*select.getInventory() + bo.getPrice()*bo.getInventory())/(select.getInventory()+bo.getInventory()));
select.setPrice((select.getPrice() * select.getInventory() + bo.getPrice() * bo.getInventory()) / (select.getInventory() + bo.getInventory()));
baseMapper.updateById(select);
return select.getId();
}
@@ -227,5 +235,161 @@ public class SysOaWarehouseServiceImpl implements ISysOaWarehouseService {
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public List<SysOaWarehouseVo> selectRecentOutbound(int limit) {
return outWareMapper.selectRecentOutbound(limit);
}
@Override
public List<SummaryCardVo> getSummaryCards(SummaryFilterDTO f) {
// —— 1. 处理默认 endTime ——
// 如果调用方没有传 endTime则当日查询用当前时点
LocalDateTime now = LocalDateTime.now();
LocalDateTime end = f.getEndTime() != null ? f.getEndTime() : now;
f.setEndTime(end);
// ① 快照时点库存
Long endInv = baseMapper.selectInventoryAt(f);
// ② 月份对比:如果同时传了 beginTime则按 begin/end 计算环比
double invTrend;
if (f.getBeginTime() != null) {
SummaryFilterDTO fb = new SummaryFilterDTO();
fb.setEndTime(f.getBeginTime());
fb.setName(f.getName());
fb.setBrand(f.getBrand());
fb.setSupplier(f.getSupplier());
long beginInv = baseMapper.selectInventoryAt(fb);
invTrend = ratio(endInv, beginInv);
} else {
// 回退上月快照计算CURDATE()-1月
SummaryFilterDTO fb = new SummaryFilterDTO();
fb.setEndTime(f.getEndTime() != null
? f.getEndTime().minusMonths(1)
: LocalDateTime.now().minusMonths(1));
fb.setName(f.getName());
fb.setBrand(f.getBrand());
fb.setSupplier(f.getSupplier());
long prevInv = baseMapper.selectInventoryAt(fb);
invTrend = ratio(endInv, prevInv);
}
// ③ 在途
long currTransit = baseMapper.selectInTransitBetween(f);
// —— 上一周期在途(若有 beginTime/endTime则平移同长度否则前一天
long prevTransit;
if (f.getBeginTime() != null && f.getEndTime() != null) {
Duration dur = Duration.between(f.getBeginTime(), f.getEndTime());
SummaryFilterDTO fp = new SummaryFilterDTO();
fp.setBeginTime(f.getBeginTime().minus(dur));
fp.setEndTime(f.getEndTime().minus(dur));
fp.setName(f.getName());
fp.setBrand(f.getBrand());
fp.setSupplier(f.getSupplier());
prevTransit = baseMapper.selectInTransitBetween(fp);
} else {
SummaryFilterDTO fp = new SummaryFilterDTO();
fp.setEndTime(f.getEndTime() != null
? f.getEndTime().minusDays(1)
: LocalDateTime.now().minusDays(1));
fp.setName(f.getName());
fp.setBrand(f.getBrand());
fp.setSupplier(f.getSupplier());
prevTransit = baseMapper.selectInTransitBetween(fp);
}
double transitTrend = ratio(currTransit, prevTransit);
// ④ 当日入/出库 & 增长
// 注意:此时 f.endTime 已经一定不为 nullselectInboundOn/selectOutboundOn 都是“当日”
long todayIn = baseMapper.selectInboundOn(f);
long todayOut = baseMapper.selectOutboundOn(f);
// 前一天快照
SummaryFilterDTO fPrev = new SummaryFilterDTO();
fPrev.setEndTime(end.minusDays(1));
fPrev.setBeginTime(null); // 不影响“当日”接口
fPrev.setName(f.getName());
fPrev.setBrand(f.getBrand());
fPrev.setSupplier(f.getSupplier());
long prevIn = baseMapper.selectInboundOn(fPrev);
long prevOut = baseMapper.selectOutboundOn(fPrev);
double inTrend = ratio(todayIn, prevIn);
double outTrend = ratio(todayOut, prevOut);
// ⑤ 预警(默认是“当日”,因为我们一开始就把 f.endTime 设成了 today
int warnCount = baseMapper.selectWarningOn(f);
// —— 拼装返回 ——
List<SummaryCardVo> cards = new ArrayList<>();
cards.add(new SummaryCardVo("当前总库存量", endInv, round(invTrend)));
cards.add(new SummaryCardVo("在途物料数量", currTransit, round(transitTrend)));
cards.add(new SummaryCardVo("当日入库量", todayIn, round(inTrend)));
cards.add(new SummaryCardVo("当日出库量", todayOut, round(outTrend)));
cards.add(new SummaryCardVo("预警信息", (long) warnCount, 0.0));
return cards;
}
@Override
public MonthlyStatsDTO getMonthlyStats(String ymStr) {
// 1. 解析年月
YearMonth ym = (ymStr != null && !ymStr.isEmpty())
? YearMonth.parse(ymStr, DateTimeFormatter.ofPattern("yyyy-MM"))
: YearMonth.now();
int year = ym.getYear();
int month = ym.getMonthValue();
// 2. 年度入/出库原始数据
List<Map<String, Object>> inRaw = baseMapper.selectInboundByMonth(year);
List<Map<String, Object>> outRaw = baseMapper.selectOutboundByMonth(year);
// 3. 填充 12 个月的占位列表
List<Long> inMonthList = new ArrayList<>(Collections.nCopies(12, 0L));
List<Long> outMonthList = new ArrayList<>(Collections.nCopies(12, 0L));
inRaw.forEach(r -> {
int m = (Integer) r.get("month");
long t = ((Number) r.get("total")).longValue();
inMonthList.set(m - 1, t);
});
outRaw.forEach(r -> {
int m = (Integer) r.get("month");
long t = ((Number) r.get("total")).longValue();
outMonthList.set(m - 1, t);
});
// 4. 当月按天库存快照
int days = ym.lengthOfMonth();
List<Long> snapList = new ArrayList<>(days);
for (int d = 1; d <= days; d++) {
LocalDate date = LocalDate.of(year, month, d);
snapList.add(baseMapper.selectInventorySnapshot(date));
}
// 5. 封装返回
MonthlyStatsDTO dto = new MonthlyStatsDTO();
dto.setInData(Collections.singletonMap("", inMonthList));
dto.setOutData(Collections.singletonMap("", outMonthList));
dto.setDataMap(Collections.singletonMap("", snapList));
return dto;
}
/**
* 计算环比prev = 0 则返回 0
*/
private double ratio(double curr, double prev) {
if (prev == 0) return 0.0;
return (curr - prev) / prev * 100;
}
/**
* 四舍五入到 1 位小数
*/
private double round(double v) {
return BigDecimal.valueOf(v)
.setScale(1, RoundingMode.HALF_UP)
.doubleValue();
}
}

View File

@@ -8,11 +8,20 @@ import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.oa.domain.SysOaWarehouse;
import com.ruoyi.oa.domain.SysOaWarehouseDetail;
import com.ruoyi.oa.domain.SysOaWarehouseMaster;
import com.ruoyi.oa.domain.bo.SysOaWarehouseDetailBo;
import com.ruoyi.oa.domain.bo.SysOaWarehouseMasterBo;
import com.ruoyi.oa.domain.vo.SysOaWarehouseDetailVo;
import com.ruoyi.oa.domain.vo.SysOaWarehouseMasterVo;
import com.ruoyi.oa.domain.vo.SysOaWarehouseVo;
import com.ruoyi.oa.mapper.SysOaWarehouseMapper;
import com.ruoyi.oa.mapper.SysOaWarehouseMasterMapper;
import com.ruoyi.oa.service.ISysOaWarehouseDetailService;
import com.ruoyi.oa.service.ISysOaWarehouseMasterService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.SysOaWarehouseTaskBo;
import com.ruoyi.oa.domain.vo.SysOaWarehouseTaskVo;
@@ -36,11 +45,17 @@ public class SysOaWarehouseTaskServiceImpl implements ISysOaWarehouseTaskService
private final SysOaWarehouseMasterMapper masterMapper;
@Autowired
private ISysOaWarehouseDetailService detailService;
@Autowired
private SysOaWarehouseMapper wareMapper;
/**
* 查询采购计划
*/
@Override
public SysOaWarehouseTaskVo queryById(Long taskId){
public SysOaWarehouseTaskVo queryById(Long taskId) {
return baseMapper.selectVoById(taskId);
}
@@ -102,7 +117,7 @@ public class SysOaWarehouseTaskServiceImpl implements ISysOaWarehouseTaskService
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(SysOaWarehouseTask entity){
private void validEntityBeforeSave(SysOaWarehouseTask entity) {
//TODO 做一些数据校验,如唯一约束
}
@@ -111,7 +126,7 @@ public class SysOaWarehouseTaskServiceImpl implements ISysOaWarehouseTaskService
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
@@ -132,7 +147,7 @@ public class SysOaWarehouseTaskServiceImpl implements ISysOaWarehouseTaskService
sysOaWarehouseMaster.setStatus(0L);
sysOaWarehouseMaster.setMasterNum(UUID.randomUUID().toString());
sysOaWarehouseMaster.setSignUser(LoginHelper.getNickName());
Boolean flag = masterMapper.insert(sysOaWarehouseMaster)>0;
Boolean flag = masterMapper.insert(sysOaWarehouseMaster) > 0;
Long masterId = sysOaWarehouseMaster.getMasterId();
for (SysOaWarehouseTaskBo sysOaWarehouseTaskBo : boList) {
sysOaWarehouseTaskBo.setMasterId(masterId);
@@ -142,4 +157,98 @@ public class SysOaWarehouseTaskServiceImpl implements ISysOaWarehouseTaskService
return flag;
}
@Override
public int updateByBoBatch(List<SysOaWarehouseTaskBo> boList) {
List<SysOaWarehouseTask> sysOaWarehouseTasks = BeanUtil.copyToList(boList, SysOaWarehouseTask.class);
return baseMapper.updateBatchById(sysOaWarehouseTasks) ? 1 : 0;
}
@Override
public int updateToWare(SysOaWarehouseTaskBo bo) {
System.out.println(bo);
// 判断是否为此物料完成状态
if (bo.getTaskStatus() == 2) {
Long masterId;
// 首先判断是否有此采购单对应的入库单
SysOaWarehouseDetailBo sysOaWarehouseDetailBo = new SysOaWarehouseDetailBo();
sysOaWarehouseDetailBo.setFatherId(bo.getMasterId());
List<SysOaWarehouseDetailVo> sysOaWarehouseDetailVos = detailService.queryList(sysOaWarehouseDetailBo);
if (sysOaWarehouseDetailVos.isEmpty()) {
// 如果为空代表此task 为首次入库则创建入库单
SysOaWarehouseMaster sysOaWarehouseMaster = new SysOaWarehouseMaster();
sysOaWarehouseMaster.setType(1L);
sysOaWarehouseMaster.setMasterNum(UUID.randomUUID().toString());
sysOaWarehouseMaster.setSignUser(LoginHelper.getNickName());
masterMapper.insert(sysOaWarehouseMaster);
// 此masterId就是新的入库单id
masterId = sysOaWarehouseMaster.getMasterId();
} else {
// 另外一种情况是已经存在了此采购单的入库单 这个时候就要在此入库单中进行新增
SysOaWarehouseDetailVo sysOaWarehouseDetailVo = sysOaWarehouseDetailVos.get(0);
masterId = sysOaWarehouseDetailVo.getMasterId();
}
toWareOne(masterId, bo, sysOaWarehouseDetailBo);
// 最终将判断此master是否还存在0||1的
// 如果不存在则将此采购单的完成情况置1
LambdaQueryWrapper<SysOaWarehouseTask> taskLambdaQueryWrapper = new LambdaQueryWrapper<>();
taskLambdaQueryWrapper.eq(SysOaWarehouseTask::getDelFlag, 0)
.eq(SysOaWarehouseTask::getMasterId, bo.getMasterId())
.in(SysOaWarehouseTask::getTaskStatus, Arrays.asList(0, 1));
List<SysOaWarehouseTask> sysOaWarehouseTasks = baseMapper.selectList(taskLambdaQueryWrapper);
System.out.println(sysOaWarehouseTasks);
if (sysOaWarehouseTasks.isEmpty()) {
SysOaWarehouseMasterVo sysOaWarehouseMasterVo = masterMapper.selectVoById(bo.getMasterId());
System.out.println("184513807548012740712308470812");
// 如果为空代表了所有都结束了 将采购单状态置1
sysOaWarehouseMasterVo.setStatus(1L);
masterMapper.updateById(BeanUtil.toBean(sysOaWarehouseMasterVo, SysOaWarehouseMaster.class));
}
return 1;
}
SysOaWarehouseTask task = BeanUtil.copyProperties(bo, SysOaWarehouseTask.class);
return baseMapper.updateById(task);
}
private int toWareOne(Long masterId, SysOaWarehouseTaskBo bo, SysOaWarehouseDetailBo sysOaWarehouseDetailBo) {
// 进行入库操作 (因为存在一种情况是此为全新物料是没有物料id的)
SysOaWarehouse sysOaWarehouse = new SysOaWarehouse();
Long warehouseId = 0L;
SysOaWarehouseVo sysOaWarehouseVo = wareMapper.selectVoById(bo.getWarehouseId());
if (Objects.isNull(sysOaWarehouseVo)) {
sysOaWarehouse.setPrice(bo.getPrice());
sysOaWarehouse.setInventory(bo.getTaskInventory());
sysOaWarehouse.setBrand(bo.getBrand());
sysOaWarehouse.setModel(bo.getModel());
sysOaWarehouse.setSpecifications(bo.getSpecifications());
sysOaWarehouse.setName(bo.getName());
sysOaWarehouse.setRemark(bo.getRemark());
sysOaWarehouse.setUnit("");
wareMapper.insert(sysOaWarehouse);
warehouseId = sysOaWarehouse.getId();
} else {
warehouseId = bo.getWarehouseId();
sysOaWarehouse = wareMapper.selectById(warehouseId);
sysOaWarehouse.setPrice((sysOaWarehouse.getPrice() * sysOaWarehouse.getInventory() + bo.getPrice() * bo.getTaskInventory()) / (sysOaWarehouse.getInventory() + bo.getTaskInventory()));
sysOaWarehouse.setInventory(sysOaWarehouse.getInventory() + bo.getTaskInventory());
System.out.println(sysOaWarehouse);
wareMapper.updateById(sysOaWarehouse);
}
// 接下来拿到masterId后开始将采购单数据写入入库单
sysOaWarehouseDetailBo.setMasterId(masterId);
sysOaWarehouseDetailBo.setWarehouseId(bo.getWarehouseId());
sysOaWarehouseDetailBo.setAmount(bo.getTaskInventory());
sysOaWarehouseDetailBo.setSignPrice(bo.getPrice());
sysOaWarehouseDetailBo.setWarehouseId(warehouseId);
sysOaWarehouseDetailBo.setType(1L);
detailService.insertByBo(sysOaWarehouseDetailBo);
SysOaWarehouseTask bean = BeanUtil.toBean(bo, SysOaWarehouseTask.class);
// 最后将此物料更新为完成入库
return baseMapper.updateById(bean);
}
}