feat(sip): 更新订单与项目信息服务及权限控制

- 修改 ExternalController 中调用的服务类名称,统一使用 projectOrderInfoService 和 deliveryService- HomepageQueryDto 增加 authSql 字段用于权限过滤
- 库存页面(index.html)调整查询条件和按钮显示逻辑,更新状态描述和字段展示
- OmsStockInfo 实体增加 notifierPhone、notifierAddress 和 notifier 字段- 各 Mapper XML 文件添加相应字段映射
- OrderInfoServiceImpl、ProjectInfoServiceImpl 和 ProjectOrderInfoServiceImpl 增加基于部门的权限控制逻辑
- ProjectOrderInfoServiceImpl 中增加邮件通知处理逻辑及模板配置
- 邮件模板 rejectTemplate.html 添加董事长驳回订单审批的通知内容- 更新导出订单信息时的字段顺序和内容处理逻辑
dev_1.0.0
chenhao 2025-10-20 10:33:03 +08:00
parent f92d540d2b
commit 7eccaeaebc
13 changed files with 188 additions and 52 deletions

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
</head>
<style>
tr td,th{
text-align: center;
border: 1px solid black;
padding: 5px 10px;
}
p{
margin-top: 20px;
}
</style>
<body>
<div>
<p>您好!</p>
<p>OMS系统中订单号[<span>[[${projectOrder.orderCode}]]</span>][[${projectOrder.projectName}]]的订单审批流程在[[${currentDate}]]已被董事长驳回,请及时处理</p>
<div style="margin-top:50px">
<img src="cid:signature" style="width: 200px; height: auto;" />
<p>紫光汇智信息技术有限公司</p>
</div>
</div>
</body>
</html>

View File

@ -61,33 +61,18 @@
<label>合同编号:</label>
<input type="text" name="orderCode" placeholder="合同编号"/>
</li>
<li>
<label>最终客户:</label>
<input type="text" name="customerName" placeholder="最终客户"/>
</li>
<li>
<label>订单状态:</label>
<select name="orderStatus" class="form-control"
th:with="type=${@dict.getType('order_status')}">
<label>备货状态:</label>
<select name="stockStatus" class="form-control"
>
<option value="">请选择</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}"
th:value="${dict.dictValue}"></option>
<option value="0">待备货</option>
<option value="1">已备货</option>
</select>
</li>
<li>
<label>代表处:</label>
<input type="text" name="agentName" placeholder="代表处"/>
</li>
<li>
<label>汇智负责人:</label>
<input type="text" name="dutyName" placeholder="项目负责人"/>
</li>
<li>
<label>进货商:</label>
<input type="text" name="partnerName" placeholder="进货商"/>
</li>
<li class="timeSearch">
<!-- <div>-->
<!-- <label>时间选择:</label>-->
@ -123,19 +108,19 @@
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success" onclick="$.operate.addFull()" shiro:hasPermission="project:order:add">
<i class="fa fa-plus"></i> 添加
</a>
<!-- <div class="btn-group-sm" id="toolbar" role="group">-->
<!-- <a class="btn btn-success" onclick="$.operate.addFull()" shiro:hasPermission="project:order:add">-->
<!-- <i class="fa fa-plus"></i> 添加-->
<!-- </a>-->
<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()"
shiro:hasPermission="project:order:remove">
<i class="fa fa-remove"></i> 删除
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="project:order:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<!-- <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()"-->
<!-- shiro:hasPermission="project:order:remove">-->
<!-- <i class="fa fa-remove"></i> 删除-->
<!-- </a>-->
<!-- <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="project:order:export">-->
<!-- <i class="fa fa-download"></i> 导出-->
<!-- </a>-->
<!-- </div>-->
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
@ -146,8 +131,6 @@
<th:block th:include="include :: jquery-cxselect-js"/>
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('project:order:edit')}]];
var removeFlag = [[${@permission.hasPermi('project:order:remove')}]];
var prefix = ctx + "stock";
function initSrot() {
@ -277,9 +260,9 @@
{
field: 'stockStatus',
title: '备货状态',
width: 200,
width: 100,
formatter: function (value, row, index) {
return value === '0' ? '备货' : '已备货'
return value === '0' ? '备货' : '已备货'
}
},
@ -288,6 +271,21 @@
title: '数量',
width: 100
},
{
field: 'notifierAddress',
title: '备货地址',
width: 300
},
{
field: 'notifier',
title: '联系人',
width: 100
},
{
field: 'notifierPhone',
title: '联系电话',
width: 100
},
{
field: 'deliveryTime',
@ -307,10 +305,12 @@
width: 200,
formatter: function (value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="updateStatus(\'' + row.id + '\')"><i class="fa fa-edit"></i>开始备货</a> ');
if (row.stockStatus === '0') {
actions.push('<a class="btn btn-success btn-xs " href="javascript:void(0)" onclick="updateStatus(\'' + row.id + '\')"><i class="fa fa-edit"></i>开始备货</a> ');
} else {
actions.push('<a class="btn btn-danger btn-xs" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
}
// actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="viewDetail(\'' + row.id + '\')"><i class="fa fa-edit"></i>详情</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}

View File

@ -85,6 +85,7 @@ public class TemplateMailUtil {
ORDER_DELIVERY("mailOrderDeliveryTemplate.html","供应商通知发货单"),
ORDER_PARTNER("mailPartnerTemplate.html","代理商商通知"),
PASSWORD_RESET("passwordTemplate.html", "密码重置"),
REJECT_EMAIL("rejectTemplate.html", "董事长驳回订单审批流程"),
;

View File

@ -54,7 +54,7 @@ public class ExternalController {
if (!API_KEY.equals(apiKey)) {
return AjaxResult.error("鉴权失败");
}
return AjaxResult.success(orderInfoService.getOrderInfo(dto));
return AjaxResult.success(projectOrderInfoService.getOrderInfo(dto));
}
@GetMapping("/v1/number/info")
@ -66,6 +66,6 @@ public class ExternalController {
if (!API_KEY.equals(apiKey)){
return AjaxResult.error("鉴权失败");
}
return AjaxResult.success(deliveryListService.getNumberInfo(dto));
return AjaxResult.success(deliveryService.getNumberInfo(dto));
}
}

View File

@ -32,6 +32,13 @@ public class OmsStockInfo {
private Date deliveryTime;
private Date deliveryTimeStart;
private Date deliveryTimeEnd;
private String notifierPhone;
private String notifierAddress;
private String notifier;
private String projectName;
private String projectCode;
private Long projectId;

View File

@ -20,4 +20,5 @@ import lombok.Data;
public class HomepageQueryDto {
private Integer day;
private Integer month;
private String authSql;
}

View File

@ -11,6 +11,7 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Dict;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
@ -389,6 +390,26 @@ public class OrderInfoServiceImpl implements IOrderInfoService
if (dto.getMonth() == null) {
throw new ServiceException("请选择月份");
}
SysUser sysUser = ShiroUtils.getSysUser();
if (sysUser.getDept() != null && sysUser.getDept().getAncestors().startsWith("0,100,200")) {
StringBuilder authSql = new StringBuilder();
//只查看已审批
authSql.append(StringUtils.format(" and t1.order_status in ('{}','{}')"
,ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode(),ProjectOrderInfo.OrderStatus.WAIT_APPROVE.getCode()));
if ("总代".equals(sysUser.getDept().getDeptName())) {
//总代
authSql.append(" and ( ");
authSql.append(" t1.order_channel = 1 ");
authSql.append(" )");
} else {
authSql.append(" and t1.partner_code in (");
authSql.append(" select partner_code from partner_info where system_user_id = ").append(sysUser.getUserId());
authSql.append(" )");
}
dto.setAuthSql(authSql.toString());
}else{
dto.setAuthSql(null);
}
List<StatisticsDetailDto> orderList = orderInfoMapper.homePageData(dto);
Map<String, StatisticsDetailDto> orderMap = orderList.stream().collect(Collectors.toMap(StatisticsDetailDto::getStatisticsStr, Function.identity(), (a, b) -> a));
LocalDate endDate = LocalDate.now();

View File

@ -532,6 +532,29 @@ public class ProjectInfoServiceImpl implements IProjectInfoService {
@Override
public StatisticsDto homePageData(HomepageQueryDto dto) {
SysUser sysUser = ShiroUtils.getSysUser();
if (sysUser.getDept() != null && sysUser.getDept().getAncestors().startsWith("0,100,200")) {
StringBuilder authSql = new StringBuilder();
authSql.append(" and t1.id in (select project_id from project_order_info where ");
authSql.append(StringUtils.format(" order_status in ('{}','{}')"
,ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode(),ProjectOrderInfo.OrderStatus.WAIT_APPROVE.getCode()));
if ("总代".equals(sysUser.getDept().getDeptName())) {
//总代
authSql.append(" and ( ");
authSql.append(" order_channel = 1 ");
authSql.append(" )");
} else {
authSql.append(" and partner_code in (");
authSql.append(" select partner_code from partner_info where system_user_id = ").append(sysUser.getUserId());
authSql.append(" )");
}
authSql.append(" ) ");
dto.setAuthSql(authSql.toString());
}else{
dto.setAuthSql(null);
}
List<StatisticsDetailDto> projectDetailList = projectInfoMapper.listHomePageData(dto);
Map<String, StatisticsDetailDto> staticsMap = projectDetailList.stream().collect(Collectors.toMap(StatisticsDetailDto::getStatisticsStr, Function.identity(), (a, b) -> a));
LocalDate endDate = LocalDate.now();

View File

@ -118,6 +118,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
private static final List<String> CSS_EMAIL_LIST = Arrays.asList("wangxiaojun@pcitech.com", "huiwang@pcitech.com", "zhaoqian1@pcitech.com", "pci-ict@pcitech.com");
private static final List<String> REJECT_EMAIL_LIST = Arrays.asList("li.junjie@unisinsight.com", "chen.shenggang@unisinsight.com");
@Autowired
private OmsStockInfoMapper omsStockInfoMapper;
@ -239,7 +240,8 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
if (sysUser.getDept() != null && sysUser.getDept().getAncestors().startsWith("0,100,200")) {
StringBuilder authSql = new StringBuilder();
//只查看已审批
authSql.append(" and t1.order_status = '").append(ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode()).append("'");
authSql.append(StringUtils.format(" and t1.order_status in ('{}','{}')"
,ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode(),ProjectOrderInfo.OrderStatus.WAIT_APPROVE.getCode()));
if ("总代".equals(sysUser.getDept().getDeptName())) {
//总代
authSql.append(" and ( ");
@ -535,6 +537,26 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
@Override
public List<StatisticsDetailDto> listHomePageData(HomepageQueryDto dto) {
SysUser sysUser = ShiroUtils.getSysUser();
if (sysUser.getDept() != null && sysUser.getDept().getAncestors().startsWith("0,100,200")) {
StringBuilder authSql = new StringBuilder();
//只查看已审批
authSql.append(StringUtils.format(" and t1.order_status in ('{}','{}')"
,ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode(),ProjectOrderInfo.OrderStatus.WAIT_APPROVE.getCode()));
if ("总代".equals(sysUser.getDept().getDeptName())) {
//总代
authSql.append(" and ( ");
authSql.append(" t1.order_channel = 1 ");
authSql.append(" )");
} else {
authSql.append(" and t1.partner_code in (");
authSql.append(" select partner_code from partner_info where system_user_id = ").append(sysUser.getUserId());
authSql.append(" )");
}
dto.setAuthSql(authSql.toString());
}else{
dto.setAuthSql(null);
}
List<StatisticsDetailDto> statisticsDetailDtos = projectOrderInfoMapper.listHomePageData(dto);
Map<String, StatisticsDetailDto> staticsMap = statisticsDetailDtos.stream().collect(Collectors.toMap(StatisticsDetailDto::getStatisticsStr, Function.identity(), (a, b) -> a));
LocalDate endDate = LocalDate.now();
@ -750,6 +772,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
headerList.add(Collections.singletonList("代表处"));
headerList.add(Collections.singletonList("汇智责任人"));
headerList.add(Collections.singletonList("下单通路"));
headerList.add(Collections.singletonList("供货商"));
headerList.add(Collections.singletonList("最终客户"));
headerList.add(Collections.singletonList("BG"));
headerList.add(Collections.singletonList("行业"));
@ -762,7 +785,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
headerList.add(Collections.singletonList("币种"));
// headerList.add(Collections.singletonList("执行单有效截止时间"));
//
// headerList.add(Collections.singletonList("要求到货时间"));
// headerList.add(Collections.singletonList("公司直发"));
@ -778,6 +801,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
headerList.add(Collections.singletonList("联系方式"));
// headerList.add(Collections.singletonList("其他特别说明"));
// headerList.add(Collections.singletonList("订单状态"));
headerList.add(Collections.singletonList("执行单截至时间"));
headerList.add(Collections.singletonList("WS瘦授权软件数量-3130A6LC"));
headerList.add(Collections.singletonList("WS瘦授权软件金额"));
headerList.add(Collections.singletonList("WS瘦授权软件税率"));
@ -921,7 +945,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
totalPrice = processProducts(deployList, maxDeployService, row, totalPrice);
//添加维保
totalPrice = processProducts(maintenanceList, maxMaintenanceService, row, totalPrice);
int insertIndex=18;
int insertIndex=20;
row.add(insertIndex++, wssDto.getQuantity().toString());
row.add(insertIndex++, wssDto.getAllPrice().toString());
row.add(insertIndex++, wssDto.getTaxRate());
@ -973,6 +997,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
row.add(info.getDutyName());
row.add(StringUtils.isEmpty(info.getOrderChannel()) ? "" :
ProjectOrderInfo.OrderChannelEnum.TOTAL_GENERATION.getCode().equals(info.getOrderChannel()) ? "总代" : "直签");
row.add(info.getSupplier());
row.add(info.getCustomerName());
row.add(DictUtils.getDictLabel("bg_type", info.getBgProperty()));
@ -1000,6 +1025,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
row.add(info.getPartnerUserName());
// row.add(info.getPartnerEmail());
row.add(info.getPartnerPhone());
row.add(DateUtil.format(info.getOrderEndTime(), "yyyy-MM-dd"));
// row.add(info.getRemark());
// row.add(DictUtils.getDictLabel("order_status", info.getOrderStatus()));
}
@ -1173,7 +1199,28 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
if ("公司领导".equals(taskName)) {
projectOrderInfo.setVersionCode("add");
//todo 陈鹏驳回需要单独处理 现有流程为 陈鹏黄雪秋并行审批 但黄雪秋审批完成流程已经下行 陈鹏驳回时如黄雪秋已审批通过时需要特殊处理
//陈鹏驳回需要单独处理 现有流程为 陈鹏黄雪秋并行审批 但黄雪秋审批完成流程已经下行 陈鹏驳回时如黄雪秋已审批通过时需要特殊处理
if (ShiroUtils.getUserId().equals(133L)){
ProjectOrderInfo dbProjectOrderInfo = projectOrderInfoMapper.selectProjectOrderInfoByCode(businessKey);
//判断黄雪秋是否审核
if (dbProjectOrderInfo.getOrderStatus().equals(ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode())){
//通知人员
ArrayList<String> emailList = new ArrayList<>(REJECT_EMAIL_LIST);
List<SysUser> sysUsers = userService.listByRoleId(businessRoleId);
emailList.addAll(sysUsers.stream()
.map(SysUser::getEmail)
.filter(StringUtils::isNotEmpty)
.collect(Collectors.toList()));
String templateTile="{}-紫光汇智云桌面-{}-董事长驳回订单审批";
String title = StringUtils.format(templateTile, dbProjectOrderInfo.getOrderCode(), dbProjectOrderInfo.getProjectName());
Dict dict = Dict.create();
dict.put("projectOrder",dbProjectOrderInfo);
dict.put("currentDate",DateUtil.now());
TemplateMailUtil.sendTemplateMail(emailList,title,
TemplateMailUtil.MailTemplate.REJECT_EMAIL,dict);
return;
}
}
}
handleRejectOrder(businessKey);
projectOrderInfoMapper.updateProjectOrderInfoByCode(projectOrderInfo);

View File

@ -282,10 +282,11 @@
<if test="id != null">and id != #{id}</if>
</select>
<select id="homePageData" resultType="com.ruoyi.sip.dto.StatisticsDetailDto">
select count(1) value, date_format(order_date, '%Y-%m') statistics_str
from order_info
where order_date >=DATE_SUB(CURDATE(), INTERVAL ${month} MONTH)
group by date_format(order_date, '%Y-%m')
select count(1) value, date_format(create_time, '%Y-%m') statistics_str
from project_order_info t1
where create_time >=DATE_SUB(CURDATE(), INTERVAL ${month} MONTH)
${authSql}
group by date_format(create_time, '%Y-%m')
</select>
<insert id="insertOrderInfo" parameterType="OrderInfo" useGeneratedKeys="true" keyProperty="id">

View File

@ -21,6 +21,9 @@
t2.project_id,
t2.id as order_id,
t2.delivery_time,
t2.notifier_address,
t2.notifier,
t2.notifier_phone,
t3.project_name,
t3.project_code ,
t4.all_quantity

View File

@ -193,7 +193,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="listHomePageData" resultType="com.ruoyi.sip.dto.StatisticsDetailDto">
select count(1) value,date_format(create_time,'%Y-%m-%d') statistics_str
from project_info where create_time <![CDATA[ >= ]]> DATE_SUB(CURDATE(), INTERVAL ${day} DAY)
from project_info t1 where create_time <![CDATA[ >= ]]> DATE_SUB(CURDATE(), INTERVAL ${day} DAY)
${authSql}
group by date_format(create_time,'%Y-%m-%d')

View File

@ -237,8 +237,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
limit 1
</select>
<select id="listHomePageData" resultType="com.ruoyi.sip.dto.StatisticsDetailDto">
select count(1) value,date_format(create_time,'%Y-%m-%d') statistics_str from project_order_info
select count(1) value,date_format(create_time,'%Y-%m-%d') statistics_str from project_order_info t1
where create_time >=DATE_SUB(CURDATE(), INTERVAL ${day} DAY)
${authSql}
group by date_format(create_time,'%Y-%m-%d')
</select>
<select id="selectProjectOrderInfoByCode" resultType="com.ruoyi.sip.domain.ProjectOrderInfo">