Compare commits
91 Commits
98f23e2c02
...
prod
| Author | SHA1 | Date | |
|---|---|---|---|
| dbc09a62ea | |||
| f3fa78475c | |||
| c565771283 | |||
| bac8488244 | |||
| a5f661b558 | |||
| ceecec97c7 | |||
| c6ae8a4c00 | |||
| 37d0c776c0 | |||
| f8eea0f63f | |||
| 59c749ab2a | |||
| eeeba2bf4b | |||
| a9ce42101f | |||
| 13de88265f | |||
| a464a1236d | |||
| fce5d0e7fc | |||
| 66ba43d030 | |||
| 1aa77e5eda | |||
| 037016fc13 | |||
| 99f0026552 | |||
| 535262d721 | |||
| fbcb9ca3f2 | |||
| 2a7a20b966 | |||
| 98fdab0dba | |||
| bd71335ae6 | |||
| 7f746fc250 | |||
| 901c8785fe | |||
| e4e9718acb | |||
| 738101f374 | |||
| a7befd7278 | |||
| 52e968c313 | |||
| de9d7d34d6 | |||
| 9f0105d88a | |||
| 80ec8ff86d | |||
| f3473fe5d5 | |||
| 856f3f334b | |||
| 0b216a4101 | |||
| c7338b45ad | |||
| c93b1b752e | |||
| e38074bb25 | |||
| be0f425e14 | |||
| f24e33b1c7 | |||
| 48ea20581c | |||
| e7fa22e573 | |||
| 83b7b32035 | |||
| 6a0be071b8 | |||
| 7bdf8f53b9 | |||
| 03b249afe7 | |||
| 2e5e42fd84 | |||
| f9d9785536 | |||
| a06511e0bf | |||
| 31aa56d34b | |||
| 2b4517760f | |||
| c318d0b10b | |||
| ec54b4ff52 | |||
| 965a0cc90e | |||
| ebddc5c51f | |||
| a323844440 | |||
| 6bcddf50da | |||
| c72275859f | |||
| 9561ee9323 | |||
| b7a52de2d2 | |||
| bfc3ea60fd | |||
| 1acc676b0f | |||
| d6a378f711 | |||
| b4f56b6c79 | |||
| b5d2b3df06 | |||
| 4042b4a441 | |||
| 1fd3da3e2a | |||
| 0d84c49ca4 | |||
| cecfb60e71 | |||
| aec8667edc | |||
| e930cd3b7c | |||
| 373906bde7 | |||
| bca9745e60 | |||
| 6808057111 | |||
| 9f1da9e6c0 | |||
| d8838f8e01 | |||
| d92d37c646 | |||
| 6398a28974 | |||
| cce9ef98d8 | |||
| 467a972a6d | |||
| 00e5f5ede6 | |||
| 1b590bbcbd | |||
| 40d53dffba | |||
| db3af72d5f | |||
| 9604cab4d6 | |||
| 536b25d773 | |||
| e87cbce77a | |||
| f34afd962d | |||
| aab0a5e0b8 | |||
| f9d1a7a489 |
@ -92,7 +92,7 @@ public class SysRegisterService {
|
||||
// if (!isValid) {
|
||||
// throw new UserException("注册失败,密码需满足8–18位,包含大小写字母、数字、特殊字符中的至少三种组合");
|
||||
// }
|
||||
// 验证码开关
|
||||
|
||||
SysUserBo sysUser = new SysUserBo();
|
||||
sysUser.setUserName(username);
|
||||
sysUser.setNickName(username);
|
||||
@ -101,6 +101,13 @@ public class SysRegisterService {
|
||||
sysUser.setUserType(userType);
|
||||
sysUser.setEmail(registerBody.getEmail());
|
||||
|
||||
SysUser sysUserByPhonenumber = userMapper.selectDefFlagUser(username);
|
||||
if(sysUserByPhonenumber != null){
|
||||
sysUser.setUserId(sysUserByPhonenumber.getUserId());
|
||||
userMapper.updateDefFlag(sysUser);
|
||||
userMapper.updateConstructionUser(sysUserByPhonenumber.getUserId());
|
||||
}else {
|
||||
|
||||
boolean exist = TenantHelper.dynamic(tenantId, () -> {
|
||||
return userMapper.exists(new LambdaQueryWrapper<SysUser>()
|
||||
.eq(SysUser::getPhonenumber, sysUser.getPhonenumber()));
|
||||
@ -112,6 +119,7 @@ public class SysRegisterService {
|
||||
if (!regFlag) {
|
||||
throw new UserException("user.register.error");
|
||||
}
|
||||
}
|
||||
|
||||
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
|
||||
}
|
||||
|
||||
@ -52,6 +52,9 @@ spring:
|
||||
url: jdbc:mysql://192.168.110.2:13386/xinnengyuandev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: xinnengyuandev
|
||||
password: StRWCZdZirysNSs2
|
||||
# url: jdbc:mysql://192.168.110.2:13386/xinnengyuan?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
# username: xinnengyuan
|
||||
# password: mEZPC5Sdf3r2HENi
|
||||
# 从库数据源
|
||||
slave:
|
||||
lazy: true
|
||||
@ -71,9 +74,16 @@ spring:
|
||||
lazy: true
|
||||
type: ${spring.datasource.type}
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://192.168.110.2:13386/zmkgdev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
username: zmkgdev
|
||||
password: JhYxREf25AXdy3h8
|
||||
url: jdbc:mysql://192.168.110.2:13386/zmkgc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
username: zmkgc
|
||||
password: nWKDKRNRT48tFBdh
|
||||
# slave:
|
||||
# lazy: true
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://192.168.110.2:13386/zmkgprod?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
# username: zmkgprod
|
||||
# password: MaY8nehwWkJriWPm
|
||||
# oracle:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: oracle.jdbc.OracleDriver
|
||||
@ -116,7 +126,7 @@ spring.data:
|
||||
# 端口,默认为6379
|
||||
port: 9287
|
||||
# 数据库索引
|
||||
database: 10
|
||||
database: 16
|
||||
# redis 密码必须配置
|
||||
password: syar23rdsaagdrsa
|
||||
# 连接超时时间
|
||||
@ -175,7 +185,7 @@ sms:
|
||||
# 配置源类型用于标定配置来源(interface,yaml)
|
||||
config-type: yaml
|
||||
# 用于标定yml中的配置是否开启短信拦截,接口配置不受此限制
|
||||
restricted: true
|
||||
restricted: false
|
||||
# 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效
|
||||
minute-max: 1
|
||||
# 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效
|
||||
@ -324,6 +334,7 @@ ys7:
|
||||
app-secret: 09e29c70ae1161fbc3ce2030fc09ba2e
|
||||
job:
|
||||
capture-enabled: false # 控制是否启用萤石抓拍任务
|
||||
device-sync-enabled: false # 控制是否同步萤石设备
|
||||
#ys7:
|
||||
# app-key: 081b0d6d5f7f4de8bc5c7fa350fb26ec
|
||||
# app-secret: caa37b9f60ef02deb57e563bc190e6db
|
||||
|
||||
@ -55,21 +55,21 @@ spring:
|
||||
url: jdbc:mysql://192.168.110.2:13386/xinnengyuan?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
username: xinnengyuan
|
||||
password: mEZPC5Sdf3r2HENi
|
||||
# 从库数据源
|
||||
slave:
|
||||
lazy: true
|
||||
type: ${spring.datasource.type}
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://192.168.110.2:13386/zmkgc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
username: zmkgc
|
||||
password: nWKDKRNRT48tFBdh
|
||||
slave1:
|
||||
lazy: true
|
||||
type: ${spring.datasource.type}
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://192.168.110.2:13386/zmkgprod?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
username: zmkgprod
|
||||
password: MaY8nehwWkJriWPm
|
||||
# # 从库数据源
|
||||
# slave:
|
||||
# lazy: true
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://192.168.110.2:13386/zmkgc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
# username: zmkgc
|
||||
# password: nWKDKRNRT48tFBdh
|
||||
# slave1:
|
||||
# lazy: true
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://192.168.110.2:13386/zmkgprod?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
# username: zmkgprod
|
||||
# password: MaY8nehwWkJriWPm
|
||||
# # 从库数据源
|
||||
# slave:
|
||||
# lazy: true
|
||||
@ -321,12 +321,13 @@ weather:
|
||||
api-host: n35rk53njv.re.qweatherapi.com
|
||||
# dxf转 geojson 执行文件名
|
||||
dxf2GeoJson:
|
||||
file-name: main.exe
|
||||
file-name: main
|
||||
ys7:
|
||||
app-key: 3acf9f1a43dc4209841e0893003db0a2
|
||||
app-secret: 4bbf3e9394f55d3af6e3af27b2d3db36
|
||||
app-secret: 09e29c70ae1161fbc3ce2030fc09ba2e
|
||||
job:
|
||||
capture-enabled: false # 控制是否启用萤石抓拍任务
|
||||
device-sync-enabled: true # 控制是否同步萤石设备
|
||||
# 斯巴达算法
|
||||
sparta:
|
||||
url: http://119.3.204.120:8040
|
||||
|
||||
@ -253,6 +253,8 @@ springdoc:
|
||||
packages-to-scan: org.dromara.design
|
||||
- group: 13.工作流模块
|
||||
packages-to-scan: org.dromara.workflow
|
||||
- group: 14.合同模块
|
||||
packages-to-scan: org.dromara.ctr
|
||||
- group: 15.无人机模块
|
||||
packages-to-scan: org.dromara.drone
|
||||
- group: 20.代码生成模块
|
||||
@ -275,8 +277,10 @@ springdoc:
|
||||
packages-to-scan: org.dromara.gps
|
||||
- group: 24.招标模块
|
||||
packages-to-scan: org.dromara.tender
|
||||
- group: 25.app版本模块
|
||||
packages-to-scan: org.dromara.app
|
||||
# - group: 25.app版本模块
|
||||
# packages-to-scan: org.dromara.app
|
||||
- group: 25.数据迁移模块
|
||||
packages-to-scan: org.dromara.transferData
|
||||
- group: 26.netty消息模块
|
||||
packages-to-scan: org.dromara.websocket
|
||||
- group: 27.新中大模块
|
||||
|
||||
@ -5,7 +5,6 @@ import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.IdcardUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
@ -129,7 +128,7 @@ public class DemoTest {
|
||||
log.info("执行定时任务:同步 {}至{} 计划详情到施工产值", lastMonday, lastSunday);
|
||||
Boolean synced = progressPlanDetailService.syncPlanDetail2ConstructionValue(lastMonday, lastSunday, null);*/
|
||||
LocalDate start = LocalDate.of(2024, 1, 1); // 起始时间(2024-01-01)
|
||||
LocalDate end = LocalDate.of(2025, 10, 13); // 截止时间(2025-09-15)
|
||||
LocalDate end = LocalDate.of(2025, 10, 20); // 截止时间(2025-09-15)
|
||||
|
||||
// 如果起始不是周一,调整到当周的周一
|
||||
if (start.getDayOfWeek() != DayOfWeek.MONDAY) {
|
||||
@ -149,7 +148,7 @@ public class DemoTest {
|
||||
.ge(PgsProgressPlanDetail::getDate, monday)
|
||||
.le(PgsProgressPlanDetail::getDate, sunday)
|
||||
.ne(PgsProgressPlanDetail::getFinishedNumber, BigDecimal.ZERO)
|
||||
.eq(PgsProgressPlanDetail::getStatus, "1")
|
||||
// .eq(PgsProgressPlanDetail::getStatus, "1")
|
||||
.list();
|
||||
if (CollUtil.isEmpty(planDetailList)) {
|
||||
// 下一周
|
||||
@ -244,8 +243,8 @@ public class DemoTest {
|
||||
value.setOutValue(constructionValue);
|
||||
value.setOwnerValue(ownerValue);
|
||||
// 统计总产值
|
||||
allConstructionValue = allConstructionValue.add(constructionValue).setScale(4, RoundingMode.HALF_UP);
|
||||
allOwnerValue = allOwnerValue.add(ownerValue).setScale(4, RoundingMode.HALF_UP);
|
||||
allConstructionValue = allConstructionValue.add(constructionValue);
|
||||
allOwnerValue = allOwnerValue.add(ownerValue);
|
||||
// 添加需要修改状态的计划详情
|
||||
PgsProgressPlanDetail update = new PgsProgressPlanDetail();
|
||||
update.setId(planDetail.getId());
|
||||
@ -253,8 +252,8 @@ public class DemoTest {
|
||||
updateList.add(update);
|
||||
saveList.add(value);
|
||||
}
|
||||
range.setOutValue(allConstructionValue);
|
||||
range.setOwnerValue(allOwnerValue);
|
||||
range.setOutValue(allConstructionValue.setScale(4, RoundingMode.HALF_UP));
|
||||
range.setOwnerValue(allOwnerValue.setScale(4, RoundingMode.HALF_UP));
|
||||
// 如果产值都为0,则不保存
|
||||
if (allConstructionValue.compareTo(BigDecimal.ZERO) == 0 && allOwnerValue.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return null;
|
||||
|
||||
@ -77,7 +77,7 @@ public class RedisUtils {
|
||||
public static <T> void publish(String channelKey, T msg, Consumer<T> consumer) {
|
||||
RTopic topic = CLIENT.getTopic(channelKey);
|
||||
topic.publish(msg);
|
||||
System.out.println("发布通道消息---------"+msg.toString());
|
||||
// System.out.println("发布通道消息---------"+msg.toString());
|
||||
consumer.accept(msg);
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ import org.springframework.web.socket.WebSocketHandler;
|
||||
import org.springframework.web.socket.config.annotation.EnableWebSocket;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
|
||||
import org.springframework.web.socket.server.HandshakeInterceptor;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
|
||||
/**
|
||||
* WebSocket 配置
|
||||
|
||||
@ -69,8 +69,8 @@ public class WebSocketUtils {
|
||||
broadcastMessage.setMessage(webSocketMessage.getMessage());
|
||||
broadcastMessage.setSessionKeys(unsentSessionKeys);
|
||||
RedisUtils.publish(WEB_SOCKET_TOPIC, broadcastMessage, consumer -> {
|
||||
log.info(" WebSocket发送主题订阅消息topic:{} session keys:{} message:{}",
|
||||
WEB_SOCKET_TOPIC, unsentSessionKeys, webSocketMessage.getMessage());
|
||||
// log.info(" WebSocket发送主题订阅消息topic:{} session keys:{} message:{}",
|
||||
// WEB_SOCKET_TOPIC, unsentSessionKeys, webSocketMessage.getMessage());
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -84,7 +84,7 @@ public class WebSocketUtils {
|
||||
WebSocketMessageDto broadcastMessage = new WebSocketMessageDto();
|
||||
broadcastMessage.setMessage(message);
|
||||
RedisUtils.publish(WEB_SOCKET_TOPIC, broadcastMessage, consumer -> {
|
||||
log.info("WebSocket发送主题订阅消息topic:{} message:{}", WEB_SOCKET_TOPIC, message);
|
||||
// log.info("WebSocket发送主题订阅消息topic:{} message:{}", WEB_SOCKET_TOPIC, message);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -19,11 +19,21 @@
|
||||
<dependencies>
|
||||
|
||||
<!-- Java WebSocket 标准API -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>javax.websocket</groupId>-->
|
||||
<!-- <artifactId>javax.websocket-api</artifactId>-->
|
||||
<!-- <version>1.1</version>-->
|
||||
<!-- <scope>provided</scope>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>javax.websocket</groupId>
|
||||
<artifactId>javax.websocket-api</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>provided</scope>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>-->
|
||||
@ -270,6 +280,13 @@
|
||||
<artifactId>netty-all</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.15</version> <!-- 最新版本可自行调整 -->
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package org.dromara.bigscreen.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -62,7 +61,7 @@ public class MoneyBigScreenController {
|
||||
/**
|
||||
* 查询项目位置列表
|
||||
*/
|
||||
@SaCheckPermission("money:bigScreen:projectGis")
|
||||
// @SaCheckPermission("money:bigScreen:projectGis")
|
||||
@GetMapping("/project/gis")
|
||||
public R<List<BusProjectGisVo>> getProjectGis() {
|
||||
return R.ok(moneyBigScreenService.getProjectGis());
|
||||
@ -545,7 +544,7 @@ public class MoneyBigScreenController {
|
||||
/**
|
||||
* 查询项目天气
|
||||
*/
|
||||
@SaCheckPermission("project:bigScreen:weather")
|
||||
// @SaCheckPermission("project:bigScreen:weather")
|
||||
@GetMapping("/weather/{projectId}")
|
||||
public R<List<WeatherVo>> getProjectWeather(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long projectId) {
|
||||
@ -555,7 +554,7 @@ public class MoneyBigScreenController {
|
||||
/**
|
||||
* 查询项目安全天数
|
||||
*/
|
||||
@SaCheckPermission("project:bigScreen:safetyDay")
|
||||
// @SaCheckPermission("project:bigScreen:safetyDay")
|
||||
@GetMapping("/safetyDay/{projectId}")
|
||||
public R<BusProjectSafetyDayVo> getProjectSafetyDay(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long projectId) {
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
package org.dromara.bigscreen.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.bigscreen.domain.dto.ProjectUpdateDto;
|
||||
import org.dromara.bigscreen.domain.dto.TanchuangInfoReq;
|
||||
import org.dromara.bigscreen.domain.dto.Ys7DeviceUpdateReq;
|
||||
import org.dromara.bigscreen.domain.vo.ProjectImageProgressVo;
|
||||
@ -185,14 +185,6 @@ public class ProjectBigScreenController extends BaseController {
|
||||
@GetMapping("/news/{projectId}")
|
||||
public R<List<BusProjectNewsVo>> getProjectNews(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long projectId) {
|
||||
// List<BusCorporateEvents> busCorporateEvents = projectBigScreenMapper.getBusCorporateEvents();
|
||||
// return R.ok(busCorporateEvents.stream().map(event -> {
|
||||
// BusProjectNewsVo vo = new BusProjectNewsVo();
|
||||
// vo.setId(event.getId());
|
||||
// vo.setTitle(event.getHeadline());
|
||||
// vo.setContent(event.getContent());
|
||||
// return vo;
|
||||
// }).toList());
|
||||
return R.ok(projectBigScreenService.getProjectNews(projectId));
|
||||
}
|
||||
|
||||
@ -203,23 +195,6 @@ public class ProjectBigScreenController extends BaseController {
|
||||
@GetMapping("/safetyInspection/{projectId}")
|
||||
public R<List<ProjectSafetyInspectionVo>> getProjectSafetyInspection(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long projectId) {
|
||||
/* BusProject project = projectService.getById(projectId);
|
||||
projectId = project.getGoId();
|
||||
String pic;
|
||||
if (projectId == 60) {
|
||||
pic = "http://xny.yj-3d.com:7464";
|
||||
} else {
|
||||
pic = "http://xny.yj-3d.com:7363";
|
||||
}
|
||||
List<BusTour> busTours = projectBigScreenMapper.selectTourByProjectId(projectId);
|
||||
return R.ok(busTours.stream().map(tour -> {
|
||||
ProjectSafetyInspectionVo vo = new ProjectSafetyInspectionVo();
|
||||
vo.setId(tour.getId());
|
||||
vo.setViolationType(tour.getTourType());
|
||||
vo.setPicture(pic + tour.getPicture());
|
||||
vo.setCreateTime(tour.getCreatedAt());
|
||||
return vo;
|
||||
}).toList());*/
|
||||
return R.ok(projectBigScreenService.getProjectSafetyInspection(projectId));
|
||||
}
|
||||
|
||||
@ -230,51 +205,6 @@ public class ProjectBigScreenController extends BaseController {
|
||||
@GetMapping("/people/{projectId}")
|
||||
public R<ProjectPeopleVo> getProjectPeople(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long projectId) {
|
||||
// BusProject project = projectService.getById(projectId);
|
||||
// projectId = project.getGoId();
|
||||
// Integer projectUserCount = projectBigScreenMapper.getProjectUserCount(projectId);
|
||||
// ProjectPeopleVo vo = new ProjectPeopleVo();
|
||||
// vo.setPeopleCount(BigDecimal.valueOf(projectUserCount));
|
||||
// Integer attendanceCount = projectBigScreenMapper.getAttendanceCount(projectId, DateUtils.getDate());
|
||||
// vo.setAttendanceCount(BigDecimal.valueOf(attendanceCount));
|
||||
// vo.setAttendanceRate(BigDecimalUtil.toPercentage(BigDecimal.valueOf(attendanceCount), BigDecimal.valueOf(projectUserCount)));
|
||||
// List<BusConstructionUser> projectUserList = projectBigScreenMapper.getProjectUserList(projectId);
|
||||
// List<BusProjectTeamByGo> teamList = projectBigScreenMapper.getTeamList(projectId);
|
||||
//
|
||||
// List<ProjectTeamAttendanceVo> teamAttendanceList = new ArrayList<>();
|
||||
// String punchRange = project.getPunchRange();
|
||||
// String punchTime = "";
|
||||
// if (punchRange != null) {
|
||||
// String start = punchRange.split(",")[0];
|
||||
// punchTime = LocalDate.now() + " " + start;
|
||||
// }
|
||||
// if (projectUserList != null && teamList != null) {
|
||||
// projectUserList = projectUserList.stream().filter(user -> user.getTeamId() != null).toList();
|
||||
// Map<Long, List<BusConstructionUser>> userMap = projectUserList.stream()
|
||||
// .collect(Collectors.groupingBy(BusConstructionUser::getTeamId));
|
||||
// for (BusProjectTeamByGo team : teamList) {
|
||||
// ProjectTeamAttendanceVo vo1 = new ProjectTeamAttendanceVo();
|
||||
// vo1.setId(team.getId());
|
||||
// vo1.setTeamName(team.getName());
|
||||
// vo1.setAttendanceTime(punchTime);
|
||||
// vo1.setAttendanceNumber(BigDecimal.ZERO);
|
||||
// List<BusConstructionUser> userList = userMap.get(team.getId());
|
||||
// if (CollUtil.isNotEmpty(userList)) {
|
||||
// List<String> list = userList.stream().map(BusConstructionUser::getOpenid).distinct().toList();
|
||||
// Integer aCount = projectBigScreenMapper.getAttendanceCountByOpenIds(list, LocalDate.now());
|
||||
// vo1.setAttendanceNumber(BigDecimal.valueOf(aCount));
|
||||
// }
|
||||
// vo1.setAllNumber(BigDecimal.valueOf(userMap.getOrDefault(team.getId(), List.of()).size()));
|
||||
// if (vo1.getAttendanceNumber() != null && vo1.getAllNumber() != null && vo1.getAllNumber().compareTo(BigDecimal.ZERO) != 0) {
|
||||
// vo1.setAttendanceRate(BigDecimalUtil.toPercentage(vo1.getAttendanceNumber(), vo1.getAllNumber()));
|
||||
// } else {
|
||||
// vo1.setAttendanceRate(BigDecimal.ZERO);
|
||||
// }
|
||||
// teamAttendanceList.add(vo1);
|
||||
// }
|
||||
// }
|
||||
// vo.setTeamAttendanceList(teamAttendanceList);
|
||||
// return R.ok(vo);
|
||||
return R.ok(projectBigScreenService.getProjectPeople(projectId));
|
||||
}
|
||||
|
||||
@ -295,18 +225,7 @@ public class ProjectBigScreenController extends BaseController {
|
||||
@GetMapping("/generalize/{projectId}")
|
||||
public R<String> getProjectGeneralize(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long projectId) {
|
||||
// BusProject project = projectService.getById(projectId);
|
||||
// if (project != null) {
|
||||
// Long goId = project.getGoId();
|
||||
// if (goId != null) {
|
||||
// List<SysProjectIntroduce> sysProjectIntroduces = projectBigScreenMapper.selectByProjectId(goId);
|
||||
// if (CollUtil.isNotEmpty(sysProjectIntroduces)) {
|
||||
// return R.ok(sysProjectIntroduces.getFirst().getRichText());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return R.ok(projectBigScreenService.getProjectGeneralize(projectId));
|
||||
// return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -346,11 +265,15 @@ public class ProjectBigScreenController extends BaseController {
|
||||
if (count > 0) {
|
||||
throw new ServiceException("已存在同名萤石摄像头", HttpStatus.CONFLICT);
|
||||
}
|
||||
// todo 更新云端名称
|
||||
/* Boolean result = ys7Manager.updateDeviceName(one.getDeviceSerial(), deviceName);
|
||||
// 更新云端名称
|
||||
Boolean result = ys7Manager.updateDeviceName(one.getDeviceSerial(), deviceName);
|
||||
if (!result) {
|
||||
throw new ServiceException("更新云端萤石摄像头名称异常", HttpStatus.ERROR);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
if (req.getLatitude() != null && req.getLongitude() != null) {
|
||||
ys7Device.setLatitude(req.getLatitude());
|
||||
ys7Device.setLongitude(req.getLongitude());
|
||||
}
|
||||
return toAjax(othYs7DeviceService.updateById(ys7Device));
|
||||
}
|
||||
@ -376,7 +299,7 @@ public class ProjectBigScreenController extends BaseController {
|
||||
/**
|
||||
* 查询GPS设备用户列表
|
||||
*/
|
||||
@SaCheckPermission("project:big:screen")
|
||||
// @SaCheckPermission("project:big:screen")
|
||||
@GetMapping("/getList")
|
||||
public R<List<String>> getList(Long projectId) {
|
||||
return R.ok(projectBigScreenService.getList(projectId));
|
||||
@ -396,12 +319,21 @@ public class ProjectBigScreenController extends BaseController {
|
||||
/**
|
||||
* 查询地图项目分类
|
||||
*/
|
||||
@SaCheckPermission("project:big:screen")
|
||||
// @SaCheckPermission("project:big:screen")
|
||||
@GetMapping("/getProjectMapList")
|
||||
public R<Map<String, Map<String, Map<String, String>>>> getProjectMapList() {
|
||||
return R.ok(projectService.getProjectMapList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询地图项目分类
|
||||
*/
|
||||
// @SaCheckPermission("project:big:screen")
|
||||
@PostMapping("/updatePosition")
|
||||
public R<Void> updatePosition(@RequestBody ProjectUpdateDto dto) {
|
||||
return toAjax(projectService.updatePosition(dto));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询项目地域分散图
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
package org.dromara.bigscreen.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class ProjectUpdateDto implements Serializable {
|
||||
|
||||
|
||||
private Long projectId; // 项目id
|
||||
|
||||
private String position; // 图片
|
||||
|
||||
}
|
||||
@ -5,6 +5,7 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
@ -37,4 +38,13 @@ public class Ys7DeviceUpdateReq implements Serializable {
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 纬度(精确到6位小数)
|
||||
*/
|
||||
private BigDecimal latitude;
|
||||
/**
|
||||
* 经度(精确到6位小数)
|
||||
*/
|
||||
private BigDecimal longitude;
|
||||
|
||||
}
|
||||
|
||||
@ -80,12 +80,12 @@ public class RedisMessageListener implements MessageListener {
|
||||
private String buildPushMessage(String key, String message, Long projectId) {
|
||||
JSONObject messageObj = new JSONObject();
|
||||
messageObj.put("type", "wrj_DATA_UPDATE");
|
||||
messageObj.put("projectId",projectId);
|
||||
messageObj.put("projectId",projectId.toString());
|
||||
messageObj.put("clientId",key);
|
||||
// 位置信息
|
||||
JSONObject locationObj = new JSONObject();
|
||||
locationObj.put("latitude", JSONUtil.parseObj(message).getJSONObject("data").get("latitude")); // 纬度
|
||||
locationObj.put("longitude", JSONUtil.parseObj(message).getJSONObject("data").get("longitude")); // 经度
|
||||
locationObj.put("latitude", JSONUtil.parseObj(message).getJSONObject("data").get("latitude").toString()); // 纬度
|
||||
locationObj.put("longitude", JSONUtil.parseObj(message).getJSONObject("data").get("longitude").toString()); // 经度
|
||||
messageObj.put("location", locationObj);
|
||||
return messageObj.toString();
|
||||
}
|
||||
|
||||
@ -505,7 +505,7 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
|
||||
gps.put("id", item.getClientId());
|
||||
gps.put("userId", item.getUserId());
|
||||
gps.put("label", item.getClientId());
|
||||
gps.put("name", item.getDeviceName());
|
||||
gps.put("name", item.getUserId() != null ? item.getUserName() : item.getClientId());
|
||||
gps.put("type", "gps");
|
||||
gps.put("lat", item.getLocLatitude());
|
||||
gps.put("lng", item.getLocLongitude());
|
||||
|
||||
@ -211,6 +211,11 @@ public class BusPurchaseDocServiceImpl extends ServiceImpl<BusPurchaseDocMapper,
|
||||
public void validNum(List<BusPlanDocAssociationBo> associationList, Long supplierId) {
|
||||
|
||||
for (BusPlanDocAssociationBo association : associationList) {
|
||||
|
||||
if(association.getDemandQuantity() == null){
|
||||
throw new ServiceException("请填写需求数量");
|
||||
}
|
||||
|
||||
//获取批次需求计划
|
||||
BusMaterialbatchdemandplan byId = materialbatchdemandplanService.getById(association.getPlanId());
|
||||
List<String> statuss = new ArrayList<>();
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
package org.dromara.common.enums;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Getter
|
||||
public enum AppUserTypeEnum {
|
||||
|
||||
|
||||
SG("0", "施工人员", 2L),
|
||||
BZZ("0", "施工人员(班组长)", 3L),
|
||||
GL("1", "管理", 4L),
|
||||
FB("2", "分包", 5L),
|
||||
;
|
||||
|
||||
private final String type;
|
||||
|
||||
private final String value;
|
||||
|
||||
private final Long roleId;
|
||||
|
||||
AppUserTypeEnum(String type, String value,Long roleId) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
|
||||
public static final List<Long> ROLE_ID_LIST = Arrays.asList(SG.roleId, BZZ.roleId, FB.roleId, GL.roleId);
|
||||
|
||||
/**
|
||||
* roleId获取枚举
|
||||
*
|
||||
* @param roleId 角色
|
||||
* @return 枚举
|
||||
*/
|
||||
public static AppUserTypeEnum getByRoleId(Long roleId) {
|
||||
for (AppUserTypeEnum value : AppUserTypeEnum.values()) {
|
||||
if (value.getRoleId().equals(roleId)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* type获取枚举
|
||||
*
|
||||
* @param type 类型
|
||||
* @return 枚举
|
||||
*/
|
||||
public static AppUserTypeEnum getByType(String type) {
|
||||
for (AppUserTypeEnum value : AppUserTypeEnum.values()) {
|
||||
if (value.getType().equals(type)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package org.dromara.common.utils.attendance;
|
||||
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class FaceUtil {
|
||||
|
||||
private static final String FACE_URL = "http://192.168.110.5:1224";
|
||||
|
||||
/**
|
||||
* 创建人脸记录 post
|
||||
* @param name 姓名
|
||||
* @param card 身份证
|
||||
* @param path 人脸图片HTTP地址(需可公开访问)
|
||||
*/
|
||||
public static void createFaceRecord(String name, String card, String path) {
|
||||
String url = FACE_URL+"/api/faces";
|
||||
|
||||
HashMap<String, Object> param = new HashMap<>() {{
|
||||
put("name", name);
|
||||
put("card", card);
|
||||
put("path", path);
|
||||
}};
|
||||
HttpUtil.post(url, param);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 人脸检测
|
||||
* @param path 图片HTTP地址(需可公开访问)
|
||||
*/
|
||||
public static Map<String, String> faceDetect(String path) {
|
||||
String url = FACE_URL+"/api/faces/detect";
|
||||
|
||||
HashMap<String, Object> param = new HashMap<>() {{
|
||||
put("path", path);
|
||||
put("similarity_threshold", 0.8);
|
||||
}};
|
||||
//转成json
|
||||
|
||||
String post = HttpUtil.post(url, param);
|
||||
Map<String, String> map = new HashMap<>();
|
||||
// 遍历检测到的人脸数据
|
||||
try {
|
||||
// 解析返回的JSON数据
|
||||
JSONObject response = JSON.parseObject(post);
|
||||
JSONObject data = response.getJSONObject("data");
|
||||
JSONArray detectedFaces = data.getJSONArray("detected_faces");
|
||||
|
||||
for (int i = 0; i < detectedFaces.size(); i++) {
|
||||
JSONObject face = detectedFaces.getJSONObject(i);
|
||||
JSONObject matchInfo = face.getJSONObject("match_info");
|
||||
|
||||
// 检查相似度是否大于等于阈值
|
||||
double similarity = matchInfo.getDoubleValue("similarity");
|
||||
double threshold = matchInfo.getDoubleValue("threshold");
|
||||
|
||||
if (similarity >= threshold) {
|
||||
// 提取用户信息
|
||||
JSONObject userInfo = face.getJSONObject("user_info");
|
||||
String name = userInfo.getString("name");
|
||||
String idCard = userInfo.getString("id_card");
|
||||
map.put(idCard, name);
|
||||
}
|
||||
}
|
||||
}catch (Exception e){
|
||||
log.error("人脸检测失败",e);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Map<String, String> map = faceDetect("http://xny.yj-3d.com:9000/xinnengyuan-dev/2025/10/12/9688ce2474ad47e7bf59c641848cdf8f.jpg");
|
||||
// System.out.println(map);
|
||||
// createFaceRecord("石志强","513022111145632652","http://xny.yj-3d.com:9000/xinnengyuan-dev/2025/10/12/9688ce2474ad47e7bf59c641848cdf8f.jpg");
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package org.dromara.contractor.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@ -204,4 +205,10 @@ public class SubConstructionUser extends BaseEntity {
|
||||
private Long goId;
|
||||
|
||||
private String goOpenid;
|
||||
|
||||
/**
|
||||
* 删除标志(0代表存在 1代表删除)
|
||||
*/
|
||||
@TableLogic
|
||||
private String delFlag;
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ 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.enums.AppUserTypeEnum;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.oss.core.OssClient;
|
||||
@ -276,7 +277,7 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
|
||||
userRoleMapper.delete(Wrappers.<SysUserRole>lambdaQuery()
|
||||
.eq(SysUserRole::getUserId, constructionUser.getSysUserId())
|
||||
.eq(SysUserRole::getProjectId, dto.getProjectId())
|
||||
.in(SysUserRole::getRoleId, Arrays.asList(2L, 3L))
|
||||
.in(SysUserRole::getRoleId, AppUserTypeEnum.ROLE_ID_LIST)
|
||||
);
|
||||
//再添加分配角色
|
||||
Long roleId = "0".equals(dto.getPostId()) ? 2L : 3L;
|
||||
@ -1517,6 +1518,7 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
|
||||
lqw.eq(SubConstructionUser::getUserRole, "0");
|
||||
if (req.getProjectId() == null) {
|
||||
lqw.isNull(SubConstructionUser::getProjectId);
|
||||
lqw.apply("exists (select 1 from sys_user where user_id = sys_user_id and dept_id is null)");
|
||||
} else {
|
||||
lqw.eq(SubConstructionUser::getProjectId, req.getProjectId());
|
||||
}
|
||||
|
||||
@ -0,0 +1,116 @@
|
||||
package org.dromara.ctr.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
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.web.core.BaseController;
|
||||
import org.dromara.ctr.domain.bo.CtrContractProgressSettlementBo;
|
||||
import org.dromara.ctr.domain.dto.CtrContractProgressSettlementCreateReq;
|
||||
import org.dromara.ctr.domain.dto.CtrContractProgressSettlementUpdateReq;
|
||||
import org.dromara.ctr.domain.vo.CtrContractProgressSettlementTotalVo;
|
||||
import org.dromara.ctr.domain.vo.CtrContractProgressSettlementVo;
|
||||
import org.dromara.ctr.service.ICtrContractProgressSettlementService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/ctr/contractProgressSettlement")
|
||||
public class CtrContractProgressSettlementController extends BaseController {
|
||||
|
||||
private final ICtrContractProgressSettlementService ctrContractProgressSettlementService;
|
||||
|
||||
/**
|
||||
* 查询承包合同进度结算列表
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlement:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<CtrContractProgressSettlementVo> list(CtrContractProgressSettlementBo bo, PageQuery pageQuery) {
|
||||
return ctrContractProgressSettlementService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出承包合同进度结算列表
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlement:export")
|
||||
@Log(title = "承包合同进度结算", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(CtrContractProgressSettlementBo bo, HttpServletResponse response) {
|
||||
List<CtrContractProgressSettlementVo> list = ctrContractProgressSettlementService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "承包合同进度结算", CtrContractProgressSettlementVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取承包合同进度结算详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlement:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<CtrContractProgressSettlementVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(ctrContractProgressSettlementService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增承包合同进度结算
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlement:add")
|
||||
@Log(title = "承包合同进度结算", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated @RequestBody CtrContractProgressSettlementCreateReq req) {
|
||||
return toAjax(ctrContractProgressSettlementService.insertByBo(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改承包合同进度结算
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlement:edit")
|
||||
@Log(title = "承包合同进度结算", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated @RequestBody CtrContractProgressSettlementUpdateReq req) {
|
||||
return toAjax(ctrContractProgressSettlementService.updateByBo(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询金额合计
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlement:query")
|
||||
@GetMapping("/queryMoneyTotal")
|
||||
public R<CtrContractProgressSettlementTotalVo> queryMoneyTotal(CtrContractProgressSettlementBo bo) {
|
||||
return R.ok(ctrContractProgressSettlementService.queryMoneyTotal(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除承包合同进度结算
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlement:remove")
|
||||
@Log(title = "承包合同进度结算", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(ctrContractProgressSettlementService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
package org.dromara.ctr.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.ctr.domain.vo.CtrContractProgressSettlementItemVo;
|
||||
import org.dromara.ctr.domain.bo.CtrContractProgressSettlementItemBo;
|
||||
import org.dromara.ctr.service.ICtrContractProgressSettlementItemService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算清单
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/ctr/contractProgressSettlementItem")
|
||||
public class CtrContractProgressSettlementItemController extends BaseController {
|
||||
|
||||
private final ICtrContractProgressSettlementItemService ctrContractProgressSettlementItemService;
|
||||
|
||||
/**
|
||||
* 查询承包合同进度结算清单列表
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlementItem:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<CtrContractProgressSettlementItemVo> list(CtrContractProgressSettlementItemBo bo, PageQuery pageQuery) {
|
||||
return ctrContractProgressSettlementItemService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出承包合同进度结算清单列表
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlementItem:export")
|
||||
@Log(title = "承包合同进度结算清单", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(CtrContractProgressSettlementItemBo bo, HttpServletResponse response) {
|
||||
List<CtrContractProgressSettlementItemVo> list = ctrContractProgressSettlementItemService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "承包合同进度结算清单", CtrContractProgressSettlementItemVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取承包合同进度结算清单详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlementItem:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<CtrContractProgressSettlementItemVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(ctrContractProgressSettlementItemService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增承包合同进度结算清单
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlementItem:add")
|
||||
@Log(title = "承包合同进度结算清单", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody CtrContractProgressSettlementItemBo bo) {
|
||||
return toAjax(ctrContractProgressSettlementItemService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改承包合同进度结算清单
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlementItem:edit")
|
||||
@Log(title = "承包合同进度结算清单", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CtrContractProgressSettlementItemBo bo) {
|
||||
return toAjax(ctrContractProgressSettlementItemService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除承包合同进度结算清单
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("ctr:contractProgressSettlementItem:remove")
|
||||
@Log(title = "承包合同进度结算清单", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(ctrContractProgressSettlementItemService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,106 @@
|
||||
package org.dromara.ctr.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
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.web.core.BaseController;
|
||||
import org.dromara.ctr.domain.bo.CtrSubcontractProgressSettlementBo;
|
||||
import org.dromara.ctr.domain.dto.CtrSubcontractProgressSettlementCreateReq;
|
||||
import org.dromara.ctr.domain.dto.CtrSubcontractProgressSettlementUpdateReq;
|
||||
import org.dromara.ctr.domain.vo.CtrSubcontractProgressSettlementVo;
|
||||
import org.dromara.ctr.service.ICtrSubcontractProgressSettlementService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分包合同进度结算
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/ctr/subcontractProgressSettlement")
|
||||
public class CtrSubcontractProgressSettlementController extends BaseController {
|
||||
|
||||
private final ICtrSubcontractProgressSettlementService ctrSubcontractProgressSettlementService;
|
||||
|
||||
/**
|
||||
* 查询分包合同进度结算列表
|
||||
*/
|
||||
@SaCheckPermission("ctr:subcontractProgressSettlement:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<CtrSubcontractProgressSettlementVo> list(CtrSubcontractProgressSettlementBo bo, PageQuery pageQuery) {
|
||||
return ctrSubcontractProgressSettlementService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出分包合同进度结算列表
|
||||
*/
|
||||
@SaCheckPermission("ctr:subcontractProgressSettlement:export")
|
||||
@Log(title = "分包合同进度结算", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(CtrSubcontractProgressSettlementBo bo, HttpServletResponse response) {
|
||||
List<CtrSubcontractProgressSettlementVo> list = ctrSubcontractProgressSettlementService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "分包合同进度结算", CtrSubcontractProgressSettlementVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分包合同进度结算详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("ctr:subcontractProgressSettlement:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<CtrSubcontractProgressSettlementVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(ctrSubcontractProgressSettlementService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增分包合同进度结算
|
||||
*/
|
||||
@SaCheckPermission("ctr:subcontractProgressSettlement:add")
|
||||
@Log(title = "分包合同进度结算", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated @RequestBody CtrSubcontractProgressSettlementCreateReq req) {
|
||||
return toAjax(ctrSubcontractProgressSettlementService.insertByBo(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改分包合同进度结算
|
||||
*/
|
||||
@SaCheckPermission("ctr:subcontractProgressSettlement:edit")
|
||||
@Log(title = "分包合同进度结算", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated @RequestBody CtrSubcontractProgressSettlementUpdateReq req) {
|
||||
return toAjax(ctrSubcontractProgressSettlementService.updateByBo(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除分包合同进度结算
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("ctr:subcontractProgressSettlement:remove")
|
||||
@Log(title = "分包合同进度结算", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(ctrSubcontractProgressSettlementService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
package org.dromara.ctr.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.ctr.domain.vo.CtrSubcontractProgressSettlementItemVo;
|
||||
import org.dromara.ctr.domain.bo.CtrSubcontractProgressSettlementItemBo;
|
||||
import org.dromara.ctr.service.ICtrSubcontractProgressSettlementItemService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 分包合同进度结算清单
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/ctr/subcontractProgressSettlementItem")
|
||||
public class CtrSubcontractProgressSettlementItemController extends BaseController {
|
||||
|
||||
private final ICtrSubcontractProgressSettlementItemService ctrSubcontractProgressSettlementItemService;
|
||||
|
||||
/**
|
||||
* 查询分包合同进度结算清单列表
|
||||
*/
|
||||
@SaCheckPermission("ctr:subcontractProgressSettlementItem:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<CtrSubcontractProgressSettlementItemVo> list(CtrSubcontractProgressSettlementItemBo bo, PageQuery pageQuery) {
|
||||
return ctrSubcontractProgressSettlementItemService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出分包合同进度结算清单列表
|
||||
*/
|
||||
@SaCheckPermission("ctr:subcontractProgressSettlementItem:export")
|
||||
@Log(title = "分包合同进度结算清单", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(CtrSubcontractProgressSettlementItemBo bo, HttpServletResponse response) {
|
||||
List<CtrSubcontractProgressSettlementItemVo> list = ctrSubcontractProgressSettlementItemService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "分包合同进度结算清单", CtrSubcontractProgressSettlementItemVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分包合同进度结算清单详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("ctr:subcontractProgressSettlementItem:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<CtrSubcontractProgressSettlementItemVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(ctrSubcontractProgressSettlementItemService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增分包合同进度结算清单
|
||||
*/
|
||||
@SaCheckPermission("ctr:subcontractProgressSettlementItem:add")
|
||||
@Log(title = "分包合同进度结算清单", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody CtrSubcontractProgressSettlementItemBo bo) {
|
||||
return toAjax(ctrSubcontractProgressSettlementItemService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改分包合同进度结算清单
|
||||
*/
|
||||
@SaCheckPermission("ctr:subcontractProgressSettlementItem:edit")
|
||||
@Log(title = "分包合同进度结算清单", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CtrSubcontractProgressSettlementItemBo bo) {
|
||||
return toAjax(ctrSubcontractProgressSettlementItemService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除分包合同进度结算清单
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("ctr:subcontractProgressSettlementItem:remove")
|
||||
@Log(title = "分包合同进度结算清单", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(ctrSubcontractProgressSettlementItemService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,139 @@
|
||||
package org.dromara.ctr.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算对象 ctr_contract_progress_settlement
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("ctr_contract_progress_settlement")
|
||||
public class CtrContractProgressSettlement extends BaseEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 所属部门
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 单据编码
|
||||
*/
|
||||
private String documentCode;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 结算日期
|
||||
*/
|
||||
private LocalDate settlementDate;
|
||||
|
||||
/**
|
||||
* 合同编码
|
||||
*/
|
||||
private String contractCode;
|
||||
|
||||
/**
|
||||
* 合同名称
|
||||
*/
|
||||
private String contractName;
|
||||
|
||||
/**
|
||||
* 统计周期
|
||||
*/
|
||||
private String contractProgress;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 审批金额
|
||||
*/
|
||||
private BigDecimal approvalAmount;
|
||||
|
||||
/**
|
||||
* 计量开始日期
|
||||
*/
|
||||
private LocalDate measureDateBegin;
|
||||
|
||||
/**
|
||||
* 计量结束日期
|
||||
*/
|
||||
private LocalDate measureDateEnd;
|
||||
|
||||
/**
|
||||
* 结算单位(客户)
|
||||
*/
|
||||
private Long settlementUnit;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
private BigDecimal settlementMoney;
|
||||
|
||||
/**
|
||||
* 本期扣款金额
|
||||
*/
|
||||
private BigDecimal deductionMoney;
|
||||
|
||||
/**
|
||||
* 本期奖励金额
|
||||
*/
|
||||
private BigDecimal bonus;
|
||||
|
||||
/**
|
||||
* 合同金额
|
||||
*/
|
||||
private BigDecimal contractAmount;
|
||||
|
||||
/**
|
||||
* 本次结算比例
|
||||
*/
|
||||
private BigDecimal thisSettlementRatio;
|
||||
|
||||
/**
|
||||
* 支付条款
|
||||
*/
|
||||
private Long paymentTerms;
|
||||
|
||||
/**
|
||||
* 多文件逗号分隔
|
||||
*/
|
||||
private String fileId;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
package org.dromara.ctr.domain;
|
||||
|
||||
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.io.Serial;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算清单对象 ctr_contract_progress_settlement_item
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("ctr_contract_progress_settlement_item")
|
||||
public class CtrContractProgressSettlementItem extends BaseEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 结算单ID
|
||||
*/
|
||||
private Long settlementId;
|
||||
|
||||
/**
|
||||
* 类型(1合同内清单 2变更增加清单 3合同外清单)
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 合同清单名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 含税单价
|
||||
*/
|
||||
private BigDecimal taxUnitPrice;
|
||||
|
||||
/**
|
||||
* 本期结算数量
|
||||
*/
|
||||
private BigDecimal currentQty;
|
||||
|
||||
/**
|
||||
* 本期结算百分比
|
||||
*/
|
||||
private BigDecimal currentRate;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
private BigDecimal currentAmount;
|
||||
|
||||
/**
|
||||
* 本期结算不含税金额
|
||||
*/
|
||||
private BigDecimal currentNoAmount;
|
||||
|
||||
/**
|
||||
* 本期审批数量
|
||||
*/
|
||||
private BigDecimal currentApprovedQty;
|
||||
|
||||
/**
|
||||
* 本期审批金额
|
||||
*/
|
||||
private BigDecimal currentApprovedAmount;
|
||||
|
||||
/**
|
||||
* 税率(%)
|
||||
*/
|
||||
private String taxRate;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,123 @@
|
||||
package org.dromara.ctr.domain;
|
||||
|
||||
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.io.Serial;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 分包合同进度结算对象 ctr_subcontract_progress_settlement
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("ctr_subcontract_progress_settlement")
|
||||
public class CtrSubcontractProgressSettlement extends BaseEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 所属部门
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 单据编码
|
||||
*/
|
||||
private String documentCode;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 单据日期
|
||||
*/
|
||||
private LocalDate documentDate;
|
||||
|
||||
/**
|
||||
* 合同编码
|
||||
*/
|
||||
private String contractCode;
|
||||
|
||||
/**
|
||||
* 合同名称
|
||||
*/
|
||||
private String contractName;
|
||||
|
||||
/**
|
||||
* 统计周期
|
||||
*/
|
||||
private String contractProgress;
|
||||
|
||||
/**
|
||||
* 计量开始日期
|
||||
*/
|
||||
private LocalDate measureDateBegin;
|
||||
|
||||
/**
|
||||
* 计量结束日期
|
||||
*/
|
||||
private LocalDate measureDateEnd;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 审批金额
|
||||
*/
|
||||
private BigDecimal approvalAmount;
|
||||
|
||||
/**
|
||||
* 结算单位
|
||||
*/
|
||||
private Long settlementUnit;
|
||||
|
||||
/**
|
||||
* 合同金额
|
||||
*/
|
||||
private BigDecimal contractAmount;
|
||||
|
||||
/**
|
||||
* 本次结算比例
|
||||
*/
|
||||
private BigDecimal currentSettlementRate;
|
||||
|
||||
/**
|
||||
* 文件ID
|
||||
*/
|
||||
private String fileId;
|
||||
|
||||
/**
|
||||
* 审核状态
|
||||
*/
|
||||
private String auditStatus;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,130 @@
|
||||
package org.dromara.ctr.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 分包合同进度结算清单对象 ctr_subcontract_progress_settlement_item
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@TableName("ctr_subcontract_progress_settlement_item")
|
||||
public class CtrSubcontractProgressSettlementItem implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 结算单ID
|
||||
*/
|
||||
private Long settlementId;
|
||||
|
||||
/**
|
||||
* 类型(1合同内清单 2变更增加清单 3合同外清单)
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 合同清单名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 含税单价
|
||||
*/
|
||||
private BigDecimal taxUnitPrice;
|
||||
|
||||
/**
|
||||
* 本期结算数量
|
||||
*/
|
||||
private BigDecimal currentQty;
|
||||
|
||||
/**
|
||||
* 本期结算百分比
|
||||
*/
|
||||
private BigDecimal currentRate;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
private BigDecimal currentAmount;
|
||||
|
||||
/**
|
||||
* 本期结算不含税金额
|
||||
*/
|
||||
private BigDecimal currentNoAmount;
|
||||
|
||||
/**
|
||||
* 本期审批数量
|
||||
*/
|
||||
private BigDecimal currentApprovedQty;
|
||||
|
||||
/**
|
||||
* 本期审批金额
|
||||
*/
|
||||
private BigDecimal currentApprovedAmount;
|
||||
|
||||
/**
|
||||
* 税率(%)
|
||||
*/
|
||||
private String taxRate;
|
||||
|
||||
/**
|
||||
* 税额
|
||||
*/
|
||||
private String tax;
|
||||
|
||||
/**
|
||||
* WBS工作分解结构
|
||||
*/
|
||||
private String wbs;
|
||||
|
||||
/**
|
||||
* CBS成本分解结构
|
||||
*/
|
||||
private String cbs;
|
||||
|
||||
/**
|
||||
* CBS预算总额
|
||||
*/
|
||||
private BigDecimal cbsBudgetTotal;
|
||||
|
||||
/**
|
||||
* CBS余额
|
||||
*/
|
||||
private BigDecimal cbsBalance;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@ -0,0 +1,150 @@
|
||||
package org.dromara.ctr.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.ctr.domain.CtrContractProgressSettlement;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算业务对象 ctr_contract_progress_settlement
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = CtrContractProgressSettlement.class, reverseConvertGenerate = false)
|
||||
public class CtrContractProgressSettlementBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = {EditGroup.class})
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 所属部门
|
||||
*/
|
||||
@NotNull(message = "所属部门不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 单据编码
|
||||
*/
|
||||
@NotBlank(message = "单据编码不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String documentCode;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@NotBlank(message = "标题不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 结算日期
|
||||
*/
|
||||
@NotNull(message = "结算日期不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private LocalDate settlementDate;
|
||||
|
||||
/**
|
||||
* 合同编码
|
||||
*/
|
||||
@NotBlank(message = "合同编码不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String contractCode;
|
||||
|
||||
/**
|
||||
* 类型(1付款 2收款)
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 合同名称
|
||||
*/
|
||||
private String contractName;
|
||||
|
||||
/**
|
||||
* 统计周期
|
||||
*/
|
||||
private String contractProgress;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 审批金额
|
||||
*/
|
||||
@NotNull(message = "审批金额不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private BigDecimal approvalAmount;
|
||||
|
||||
/**
|
||||
* 计量开始日期
|
||||
*/
|
||||
private LocalDate measureDateBegin;
|
||||
|
||||
/**
|
||||
* 计量结束日期
|
||||
*/
|
||||
private LocalDate measureDateEnd;
|
||||
|
||||
/**
|
||||
* 结算单位(客户)
|
||||
*/
|
||||
private Long settlementUnit;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
private BigDecimal settlementMoney;
|
||||
|
||||
/**
|
||||
* 本期扣款金额
|
||||
*/
|
||||
private BigDecimal deductionMoney;
|
||||
|
||||
/**
|
||||
* 本期奖励金额
|
||||
*/
|
||||
private BigDecimal bonus;
|
||||
|
||||
/**
|
||||
* 合同金额
|
||||
*/
|
||||
private BigDecimal contractAmount;
|
||||
|
||||
/**
|
||||
* 本次结算比例
|
||||
*/
|
||||
private BigDecimal thisSettlementRatio;
|
||||
|
||||
/**
|
||||
* 支付条款
|
||||
*/
|
||||
private Long paymentTerms;
|
||||
|
||||
/**
|
||||
* 多文件逗号分隔
|
||||
*/
|
||||
private String fileId;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,110 @@
|
||||
package org.dromara.ctr.domain.bo;
|
||||
|
||||
import org.dromara.ctr.domain.CtrContractProgressSettlementItem;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算清单业务对象 ctr_contract_progress_settlement_item
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = CtrContractProgressSettlementItem.class, reverseConvertGenerate = false)
|
||||
public class CtrContractProgressSettlementItemBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 结算单ID
|
||||
*/
|
||||
@NotNull(message = "结算单ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long settlementId;
|
||||
|
||||
/**
|
||||
* 类型(1合同内清单 2变更增加清单 3合同外清单)
|
||||
*/
|
||||
@NotBlank(message = "类型(1合同内清单 2变更增加清单 3合同外清单)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
@NotBlank(message = "编码不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 合同清单名称
|
||||
*/
|
||||
@NotBlank(message = "合同清单名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
*/
|
||||
@NotBlank(message = "计量单位不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 含税单价
|
||||
*/
|
||||
private BigDecimal taxUnitPrice;
|
||||
|
||||
/**
|
||||
* 本期结算数量
|
||||
*/
|
||||
private BigDecimal currentQty;
|
||||
|
||||
/**
|
||||
* 本期结算百分比
|
||||
*/
|
||||
private BigDecimal currentRate;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
private BigDecimal currentAmount;
|
||||
|
||||
/**
|
||||
* 本期结算不含税金额
|
||||
*/
|
||||
private BigDecimal currentNoAmount;
|
||||
|
||||
/**
|
||||
* 本期审批数量
|
||||
*/
|
||||
private BigDecimal currentApprovedQty;
|
||||
|
||||
/**
|
||||
* 本期审批金额
|
||||
*/
|
||||
private BigDecimal currentApprovedAmount;
|
||||
|
||||
/**
|
||||
* 税率(%)
|
||||
*/
|
||||
private String taxRate;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
package org.dromara.ctr.domain.bo;
|
||||
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlement;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 分包合同进度结算业务对象 ctr_subcontract_progress_settlement
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = CtrSubcontractProgressSettlement.class, reverseConvertGenerate = false)
|
||||
public class CtrSubcontractProgressSettlementBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 单据编码
|
||||
*/
|
||||
@NotBlank(message = "单据编码不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String documentCode;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@NotBlank(message = "标题不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 单据日期
|
||||
*/
|
||||
@NotNull(message = "单据日期不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private LocalDate documentDate;
|
||||
|
||||
/**
|
||||
* 合同编码
|
||||
*/
|
||||
@NotBlank(message = "合同编码不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String contractCode;
|
||||
|
||||
/**
|
||||
* 合同名称
|
||||
*/
|
||||
private String contractName;
|
||||
|
||||
/**
|
||||
* 统计周期
|
||||
*/
|
||||
private String contractProgress;
|
||||
|
||||
/**
|
||||
* 计量开始日期
|
||||
*/
|
||||
private LocalDate measureDateBegin;
|
||||
|
||||
/**
|
||||
* 计量结束日期
|
||||
*/
|
||||
private LocalDate measureDateEnd;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 审批金额
|
||||
*/
|
||||
@NotNull(message = "审批金额不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private BigDecimal approvalAmount;
|
||||
|
||||
/**
|
||||
* 结算单位
|
||||
*/
|
||||
private Long settlementUnit;
|
||||
|
||||
/**
|
||||
* 合同金额
|
||||
*/
|
||||
private BigDecimal contractAmount;
|
||||
|
||||
/**
|
||||
* 本次结算比例
|
||||
*/
|
||||
private BigDecimal currentSettlementRate;
|
||||
|
||||
/**
|
||||
* 文件ID
|
||||
*/
|
||||
private String fileId;
|
||||
|
||||
/**
|
||||
* 审核状态
|
||||
*/
|
||||
private String auditStatus;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
package org.dromara.ctr.domain.bo;
|
||||
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlementItem;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 分包合同进度结算清单业务对象 ctr_subcontract_progress_settlement_item
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = CtrSubcontractProgressSettlementItem.class, reverseConvertGenerate = false)
|
||||
public class CtrSubcontractProgressSettlementItemBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 结算单ID
|
||||
*/
|
||||
@NotNull(message = "结算单ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long settlementId;
|
||||
|
||||
/**
|
||||
* 类型(1合同内清单 2变更增加清单 3合同外清单)
|
||||
*/
|
||||
@NotBlank(message = "类型(1合同内清单 2变更增加清单 3合同外清单)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
@NotBlank(message = "编码不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 合同清单名称
|
||||
*/
|
||||
@NotBlank(message = "合同清单名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
*/
|
||||
@NotBlank(message = "计量单位不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 含税单价
|
||||
*/
|
||||
private BigDecimal taxUnitPrice;
|
||||
|
||||
/**
|
||||
* 本期结算数量
|
||||
*/
|
||||
private BigDecimal currentQty;
|
||||
|
||||
/**
|
||||
* 本期结算百分比
|
||||
*/
|
||||
private BigDecimal currentRate;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
private BigDecimal currentAmount;
|
||||
|
||||
/**
|
||||
* 本期结算不含税金额
|
||||
*/
|
||||
private BigDecimal currentNoAmount;
|
||||
|
||||
/**
|
||||
* 本期审批数量
|
||||
*/
|
||||
private BigDecimal currentApprovedQty;
|
||||
|
||||
/**
|
||||
* 本期审批金额
|
||||
*/
|
||||
private BigDecimal currentApprovedAmount;
|
||||
|
||||
/**
|
||||
* 税率(%)
|
||||
*/
|
||||
private String taxRate;
|
||||
|
||||
/**
|
||||
* 税额
|
||||
*/
|
||||
private String tax;
|
||||
|
||||
/**
|
||||
* WBS工作分解结构
|
||||
*/
|
||||
private String wbs;
|
||||
|
||||
/**
|
||||
* CBS成本分解结构
|
||||
*/
|
||||
private String cbs;
|
||||
|
||||
/**
|
||||
* CBS预算总额
|
||||
*/
|
||||
private BigDecimal cbsBudgetTotal;
|
||||
|
||||
/**
|
||||
* CBS余额
|
||||
*/
|
||||
private BigDecimal cbsBalance;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,148 @@
|
||||
package org.dromara.ctr.domain.dto;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.dromara.ctr.domain.CtrContractProgressSettlement;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算业务对象 ctr_contract_progress_settlement
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@AutoMapper(target = CtrContractProgressSettlement.class, reverseConvertGenerate = false)
|
||||
public class CtrContractProgressSettlementCreateReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -7707258738219359278L;
|
||||
|
||||
/**
|
||||
* 所属部门
|
||||
*/
|
||||
@NotNull(message = "所属部门不能为空")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@NotBlank(message = "标题不能为空")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 结算日期
|
||||
*/
|
||||
@NotNull(message = "结算日期不能为空")
|
||||
private LocalDate settlementDate;
|
||||
|
||||
/**
|
||||
* 合同编码
|
||||
*/
|
||||
@NotBlank(message = "合同编码不能为空")
|
||||
private String contractCode;
|
||||
|
||||
/**
|
||||
* 合同名称
|
||||
*/
|
||||
private String contractName;
|
||||
|
||||
/**
|
||||
* 统计周期
|
||||
*/
|
||||
private String contractProgress;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 审批金额
|
||||
*/
|
||||
@NotNull(message = "审批金额不能为空")
|
||||
private BigDecimal approvalAmount;
|
||||
|
||||
/**
|
||||
* 计量开始日期
|
||||
*/
|
||||
private LocalDate measureDateBegin;
|
||||
|
||||
/**
|
||||
* 计量结束日期
|
||||
*/
|
||||
private LocalDate measureDateEnd;
|
||||
|
||||
/**
|
||||
* 结算单位(客户)
|
||||
*/
|
||||
private Long settlementUnit;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
private BigDecimal settlementMoney;
|
||||
|
||||
/**
|
||||
* 本期扣款金额
|
||||
*/
|
||||
private BigDecimal deductionMoney;
|
||||
|
||||
/**
|
||||
* 本期奖励金额
|
||||
*/
|
||||
private BigDecimal bonus;
|
||||
|
||||
/**
|
||||
* 合同金额
|
||||
*/
|
||||
private BigDecimal contractAmount;
|
||||
|
||||
/**
|
||||
* 本次结算比例
|
||||
*/
|
||||
private BigDecimal thisSettlementRatio;
|
||||
|
||||
/**
|
||||
* 支付条款
|
||||
*/
|
||||
private Long paymentTerms;
|
||||
|
||||
/**
|
||||
* 多文件逗号分隔
|
||||
*/
|
||||
private String fileId;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 合同内清单
|
||||
*/
|
||||
private List<CtrContractProgressSettlementItemCreateReq> inInventory;
|
||||
|
||||
/**
|
||||
* 变更增加清单
|
||||
*/
|
||||
private List<CtrContractProgressSettlementItemCreateReq> changeInventory;
|
||||
|
||||
/**
|
||||
* 合同外清单
|
||||
*/
|
||||
private List<CtrContractProgressSettlementItemCreateReq> outInventory;
|
||||
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
package org.dromara.ctr.domain.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-10-18 17:05
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CtrContractProgressSettlementItemCreateReq {
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
@NotBlank(message = "编码不能为空")
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 合同清单名称
|
||||
*/
|
||||
@NotBlank(message = "合同清单名称不能为空")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
*/
|
||||
@NotBlank(message = "计量单位不能为空")
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 含税单价
|
||||
*/
|
||||
private BigDecimal taxUnitPrice;
|
||||
|
||||
/**
|
||||
* 本期结算数量
|
||||
*/
|
||||
private BigDecimal currentQty;
|
||||
|
||||
/**
|
||||
* 本期结算百分比
|
||||
*/
|
||||
private BigDecimal currentRate;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
private BigDecimal currentAmount;
|
||||
|
||||
/**
|
||||
* 本期结算不含税金额
|
||||
*/
|
||||
private BigDecimal currentNoAmount;
|
||||
|
||||
/**
|
||||
* 本期审批数量
|
||||
*/
|
||||
private BigDecimal currentApprovedQty;
|
||||
|
||||
/**
|
||||
* 本期审批金额
|
||||
*/
|
||||
private BigDecimal currentApprovedAmount;
|
||||
|
||||
/**
|
||||
* 税率(%)
|
||||
*/
|
||||
private String taxRate;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
package org.dromara.ctr.domain.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-10-18 17:39
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CtrContractProgressSettlementItemUpdateReq {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
@NotBlank(message = "编码不能为空")
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 合同清单名称
|
||||
*/
|
||||
@NotBlank(message = "合同清单名称不能为空")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
*/
|
||||
@NotBlank(message = "计量单位不能为空")
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 含税单价
|
||||
*/
|
||||
private BigDecimal taxUnitPrice;
|
||||
|
||||
/**
|
||||
* 本期结算数量
|
||||
*/
|
||||
private BigDecimal currentQty;
|
||||
|
||||
/**
|
||||
* 本期结算百分比
|
||||
*/
|
||||
private BigDecimal currentRate;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
private BigDecimal currentAmount;
|
||||
|
||||
/**
|
||||
* 本期结算不含税金额
|
||||
*/
|
||||
private BigDecimal currentNoAmount;
|
||||
|
||||
/**
|
||||
* 本期审批数量
|
||||
*/
|
||||
private BigDecimal currentApprovedQty;
|
||||
|
||||
/**
|
||||
* 本期审批金额
|
||||
*/
|
||||
private BigDecimal currentApprovedAmount;
|
||||
|
||||
/**
|
||||
* 税率(%)
|
||||
*/
|
||||
private String taxRate;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
}
|
||||
@ -0,0 +1,157 @@
|
||||
package org.dromara.ctr.domain.dto;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.dromara.ctr.domain.CtrContractProgressSettlement;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-10-18 17:30
|
||||
*/
|
||||
@Data
|
||||
@AutoMapper(target = CtrContractProgressSettlement.class, reverseConvertGenerate = false)
|
||||
public class CtrContractProgressSettlementUpdateReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -105855005415297131L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 所属部门
|
||||
*/
|
||||
@NotNull(message = "所属部门不能为空")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 单据编码
|
||||
*/
|
||||
@NotBlank(message = "单据编码不能为空")
|
||||
private String documentCode;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@NotBlank(message = "标题不能为空")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 结算日期
|
||||
*/
|
||||
@NotNull(message = "结算日期不能为空")
|
||||
private LocalDate settlementDate;
|
||||
|
||||
/**
|
||||
* 合同编码
|
||||
*/
|
||||
@NotBlank(message = "合同编码不能为空")
|
||||
private String contractCode;
|
||||
|
||||
/**
|
||||
* 合同名称
|
||||
*/
|
||||
private String contractName;
|
||||
|
||||
/**
|
||||
* 统计周期
|
||||
*/
|
||||
private String contractProgress;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 审批金额
|
||||
*/
|
||||
@NotNull(message = "审批金额不能为空")
|
||||
private BigDecimal approvalAmount;
|
||||
|
||||
/**
|
||||
* 计量开始日期
|
||||
*/
|
||||
private LocalDate measureDateBegin;
|
||||
|
||||
/**
|
||||
* 计量结束日期
|
||||
*/
|
||||
private LocalDate measureDateEnd;
|
||||
|
||||
/**
|
||||
* 结算单位(客户)
|
||||
*/
|
||||
private Long settlementUnit;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
private BigDecimal settlementMoney;
|
||||
|
||||
/**
|
||||
* 本期扣款金额
|
||||
*/
|
||||
private BigDecimal deductionMoney;
|
||||
|
||||
/**
|
||||
* 本期奖励金额
|
||||
*/
|
||||
private BigDecimal bonus;
|
||||
|
||||
/**
|
||||
* 合同金额
|
||||
*/
|
||||
private BigDecimal contractAmount;
|
||||
|
||||
/**
|
||||
* 本次结算比例
|
||||
*/
|
||||
private BigDecimal thisSettlementRatio;
|
||||
|
||||
/**
|
||||
* 支付条款
|
||||
*/
|
||||
private Long paymentTerms;
|
||||
|
||||
/**
|
||||
* 多文件逗号分隔
|
||||
*/
|
||||
private String fileId;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 合同内清单
|
||||
*/
|
||||
private List<CtrContractProgressSettlementItemUpdateReq> inInventory;
|
||||
|
||||
/**
|
||||
* 变更增加清单
|
||||
*/
|
||||
private List<CtrContractProgressSettlementItemUpdateReq> changeInventory;
|
||||
|
||||
/**
|
||||
* 合同外清单
|
||||
*/
|
||||
private List<CtrContractProgressSettlementItemUpdateReq> outInventory;
|
||||
}
|
||||
@ -0,0 +1,129 @@
|
||||
package org.dromara.ctr.domain.dto;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlement;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-10-18 19:14
|
||||
*/
|
||||
@Data
|
||||
@AutoMapper(target = CtrSubcontractProgressSettlement.class, reverseConvertGenerate = false)
|
||||
public class CtrSubcontractProgressSettlementCreateReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 770553999547826460L;
|
||||
|
||||
/**
|
||||
* 所属部门
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@NotBlank(message = "标题不能为空")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 单据日期
|
||||
*/
|
||||
@NotNull(message = "单据日期不能为空")
|
||||
private LocalDate documentDate;
|
||||
|
||||
/**
|
||||
* 合同编码
|
||||
*/
|
||||
@NotBlank(message = "合同编码不能为空")
|
||||
private String contractCode;
|
||||
|
||||
/**
|
||||
* 合同名称
|
||||
*/
|
||||
private String contractName;
|
||||
|
||||
/**
|
||||
* 统计周期
|
||||
*/
|
||||
private String contractProgress;
|
||||
|
||||
/**
|
||||
* 计量开始日期
|
||||
*/
|
||||
private LocalDate measureDateBegin;
|
||||
|
||||
/**
|
||||
* 计量结束日期
|
||||
*/
|
||||
private LocalDate measureDateEnd;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 审批金额
|
||||
*/
|
||||
@NotNull(message = "审批金额不能为空")
|
||||
private BigDecimal approvalAmount;
|
||||
|
||||
/**
|
||||
* 结算单位
|
||||
*/
|
||||
private Long settlementUnit;
|
||||
|
||||
/**
|
||||
* 合同金额
|
||||
*/
|
||||
private BigDecimal contractAmount;
|
||||
|
||||
/**
|
||||
* 本次结算比例
|
||||
*/
|
||||
private BigDecimal currentSettlementRate;
|
||||
|
||||
/**
|
||||
* 文件ID
|
||||
*/
|
||||
private String fileId;
|
||||
|
||||
/**
|
||||
* 审核状态
|
||||
*/
|
||||
private String auditStatus;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 合同内清单
|
||||
*/
|
||||
private List<CtrSubcontractProgressSettlementItemCreateReq> inInventory;
|
||||
|
||||
/**
|
||||
* 变更增加清单
|
||||
*/
|
||||
private List<CtrSubcontractProgressSettlementItemCreateReq> changeInventory;
|
||||
|
||||
/**
|
||||
* 合同外清单
|
||||
*/
|
||||
private List<CtrSubcontractProgressSettlementItemCreateReq> outInventory;
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
package org.dromara.ctr.domain.dto;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlementItem;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-10-18 19:17
|
||||
*/
|
||||
@Data
|
||||
@AutoMapper(target = CtrSubcontractProgressSettlementItem.class, reverseConvertGenerate = false)
|
||||
public class CtrSubcontractProgressSettlementItemCreateReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -7720839036718185218L;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
@NotBlank(message = "编码不能为空")
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 合同清单名称
|
||||
*/
|
||||
@NotBlank(message = "合同清单名称不能为空")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
*/
|
||||
@NotBlank(message = "计量单位不能为空")
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 含税单价
|
||||
*/
|
||||
private BigDecimal taxUnitPrice;
|
||||
|
||||
/**
|
||||
* 本期结算数量
|
||||
*/
|
||||
private BigDecimal currentQty;
|
||||
|
||||
/**
|
||||
* 本期结算百分比
|
||||
*/
|
||||
private BigDecimal currentRate;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
private BigDecimal currentAmount;
|
||||
|
||||
/**
|
||||
* 本期结算不含税金额
|
||||
*/
|
||||
private BigDecimal currentNoAmount;
|
||||
|
||||
/**
|
||||
* 本期审批数量
|
||||
*/
|
||||
private BigDecimal currentApprovedQty;
|
||||
|
||||
/**
|
||||
* 本期审批金额
|
||||
*/
|
||||
private BigDecimal currentApprovedAmount;
|
||||
|
||||
/**
|
||||
* 税率(%)
|
||||
*/
|
||||
private String taxRate;
|
||||
|
||||
/**
|
||||
* 税额
|
||||
*/
|
||||
private String tax;
|
||||
|
||||
/**
|
||||
* WBS工作分解结构
|
||||
*/
|
||||
private String wbs;
|
||||
|
||||
/**
|
||||
* CBS成本分解结构
|
||||
*/
|
||||
private String cbs;
|
||||
|
||||
/**
|
||||
* CBS预算总额
|
||||
*/
|
||||
private BigDecimal cbsBudgetTotal;
|
||||
|
||||
/**
|
||||
* CBS余额
|
||||
*/
|
||||
private BigDecimal cbsBalance;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
}
|
||||
@ -0,0 +1,123 @@
|
||||
package org.dromara.ctr.domain.dto;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlementItem;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-10-18 19:21
|
||||
*/
|
||||
@Data
|
||||
@AutoMapper(target = CtrSubcontractProgressSettlementItem.class, reverseConvertGenerate = false)
|
||||
public class CtrSubcontractProgressSettlementItemUpdateReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 4319471696029509036L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
@NotBlank(message = "编码不能为空")
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 合同清单名称
|
||||
*/
|
||||
@NotBlank(message = "合同清单名称不能为空")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
*/
|
||||
@NotBlank(message = "计量单位不能为空")
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 含税单价
|
||||
*/
|
||||
private BigDecimal taxUnitPrice;
|
||||
|
||||
/**
|
||||
* 本期结算数量
|
||||
*/
|
||||
private BigDecimal currentQty;
|
||||
|
||||
/**
|
||||
* 本期结算百分比
|
||||
*/
|
||||
private BigDecimal currentRate;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
private BigDecimal currentAmount;
|
||||
|
||||
/**
|
||||
* 本期结算不含税金额
|
||||
*/
|
||||
private BigDecimal currentNoAmount;
|
||||
|
||||
/**
|
||||
* 本期审批数量
|
||||
*/
|
||||
private BigDecimal currentApprovedQty;
|
||||
|
||||
/**
|
||||
* 本期审批金额
|
||||
*/
|
||||
private BigDecimal currentApprovedAmount;
|
||||
|
||||
/**
|
||||
* 税率(%)
|
||||
*/
|
||||
private String taxRate;
|
||||
|
||||
/**
|
||||
* 税额
|
||||
*/
|
||||
private String tax;
|
||||
|
||||
/**
|
||||
* WBS工作分解结构
|
||||
*/
|
||||
private String wbs;
|
||||
|
||||
/**
|
||||
* CBS成本分解结构
|
||||
*/
|
||||
private String cbs;
|
||||
|
||||
/**
|
||||
* CBS预算总额
|
||||
*/
|
||||
private BigDecimal cbsBudgetTotal;
|
||||
|
||||
/**
|
||||
* CBS余额
|
||||
*/
|
||||
private BigDecimal cbsBalance;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
package org.dromara.ctr.domain.dto;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlement;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-10-18 19:20
|
||||
*/
|
||||
@Data
|
||||
@AutoMapper(target = CtrSubcontractProgressSettlement.class, reverseConvertGenerate = false)
|
||||
public class CtrSubcontractProgressSettlementUpdateReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -7099475527833822253L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 单据编码
|
||||
*/
|
||||
@NotBlank(message = "单据编码不能为空")
|
||||
private String documentCode;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@NotBlank(message = "标题不能为空")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 单据日期
|
||||
*/
|
||||
@NotNull(message = "单据日期不能为空")
|
||||
private LocalDate documentDate;
|
||||
|
||||
/**
|
||||
* 合同编码
|
||||
*/
|
||||
@NotBlank(message = "合同编码不能为空")
|
||||
private String contractCode;
|
||||
|
||||
/**
|
||||
* 合同名称
|
||||
*/
|
||||
private String contractName;
|
||||
|
||||
/**
|
||||
* 统计周期
|
||||
*/
|
||||
private String contractProgress;
|
||||
|
||||
/**
|
||||
* 计量开始日期
|
||||
*/
|
||||
private LocalDate measureDateBegin;
|
||||
|
||||
/**
|
||||
* 计量结束日期
|
||||
*/
|
||||
private LocalDate measureDateEnd;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 审批金额
|
||||
*/
|
||||
@NotNull(message = "审批金额不能为空")
|
||||
private BigDecimal approvalAmount;
|
||||
|
||||
/**
|
||||
* 结算单位
|
||||
*/
|
||||
private Long settlementUnit;
|
||||
|
||||
/**
|
||||
* 合同金额
|
||||
*/
|
||||
private BigDecimal contractAmount;
|
||||
|
||||
/**
|
||||
* 本次结算比例
|
||||
*/
|
||||
private BigDecimal currentSettlementRate;
|
||||
|
||||
/**
|
||||
* 文件ID
|
||||
*/
|
||||
private String fileId;
|
||||
|
||||
/**
|
||||
* 审核状态
|
||||
*/
|
||||
private String auditStatus;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 合同内清单
|
||||
*/
|
||||
private List<CtrSubcontractProgressSettlementItemUpdateReq> inInventory;
|
||||
|
||||
/**
|
||||
* 变更增加清单
|
||||
*/
|
||||
private List<CtrSubcontractProgressSettlementItemUpdateReq> changeInventory;
|
||||
|
||||
/**
|
||||
* 合同外清单
|
||||
*/
|
||||
private List<CtrSubcontractProgressSettlementItemUpdateReq> outInventory;
|
||||
}
|
||||
@ -0,0 +1,130 @@
|
||||
package org.dromara.ctr.domain.vo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import org.dromara.ctr.domain.CtrContractProgressSettlementItem;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 承包合同进度结算清单视图对象 ctr_contract_progress_settlement_item
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = CtrContractProgressSettlementItem.class)
|
||||
public class CtrContractProgressSettlementItemVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 结算单ID
|
||||
*/
|
||||
@ExcelProperty(value = "结算单ID")
|
||||
private Long settlementId;
|
||||
|
||||
/**
|
||||
* 类型(1合同内清单 2变更增加清单 3合同外清单)
|
||||
*/
|
||||
@ExcelProperty(value = "类型(1合同内清单 2变更增加清单 3合同外清单)")
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
@ExcelProperty(value = "编码")
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 合同清单名称
|
||||
*/
|
||||
@ExcelProperty(value = "合同清单名称")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
*/
|
||||
@ExcelProperty(value = "计量单位")
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
@ExcelProperty(value = "单价")
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 含税单价
|
||||
*/
|
||||
@ExcelProperty(value = "含税单价")
|
||||
private BigDecimal taxUnitPrice;
|
||||
|
||||
/**
|
||||
* 本期结算数量
|
||||
*/
|
||||
@ExcelProperty(value = "本期结算数量")
|
||||
private BigDecimal currentQty;
|
||||
|
||||
/**
|
||||
* 本期结算百分比
|
||||
*/
|
||||
@ExcelProperty(value = "本期结算百分比")
|
||||
private BigDecimal currentRate;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
@ExcelProperty(value = "本期结算金额")
|
||||
private BigDecimal currentAmount;
|
||||
|
||||
/**
|
||||
* 本期结算不含税金额
|
||||
*/
|
||||
@ExcelProperty(value = "本期结算不含税金额")
|
||||
private BigDecimal currentNoAmount;
|
||||
|
||||
/**
|
||||
* 本期审批数量
|
||||
*/
|
||||
@ExcelProperty(value = "本期审批数量")
|
||||
private BigDecimal currentApprovedQty;
|
||||
|
||||
/**
|
||||
* 本期审批金额
|
||||
*/
|
||||
@ExcelProperty(value = "本期审批金额")
|
||||
private BigDecimal currentApprovedAmount;
|
||||
|
||||
/**
|
||||
* 税率(%)
|
||||
*/
|
||||
@ExcelProperty(value = "税率", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "xzd_tax_rate")
|
||||
private String taxRate;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package org.dromara.ctr.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-10-21 11:01
|
||||
*/
|
||||
@Data
|
||||
public class CtrContractProgressSettlementTotalVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1537548228169684228L;
|
||||
|
||||
/**
|
||||
* 总金额
|
||||
*/
|
||||
private BigDecimal moneyTotal;
|
||||
}
|
||||
@ -0,0 +1,192 @@
|
||||
package org.dromara.ctr.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.translation.annotation.Translation;
|
||||
import org.dromara.common.translation.constant.TransConstant;
|
||||
import org.dromara.ctr.domain.CtrContractProgressSettlement;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 承包合同进度结算视图对象 ctr_contract_progress_settlement
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = CtrContractProgressSettlement.class)
|
||||
public class CtrContractProgressSettlementVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 所属部门
|
||||
*/
|
||||
@ExcelProperty(value = "所属部门")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
@Translation(type = TransConstant.DEPT_ID_TO_NAME, mapper = "deptId")
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 单据编码
|
||||
*/
|
||||
@ExcelProperty(value = "单据编码")
|
||||
private String documentCode;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@ExcelProperty(value = "标题")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 结算日期
|
||||
*/
|
||||
@ExcelProperty(value = "结算日期")
|
||||
private LocalDate settlementDate;
|
||||
|
||||
/**
|
||||
* 合同编码
|
||||
*/
|
||||
@ExcelProperty(value = "合同编码")
|
||||
private String contractCode;
|
||||
|
||||
/**
|
||||
* 合同名称
|
||||
*/
|
||||
@ExcelProperty(value = "合同名称")
|
||||
private String contractName;
|
||||
|
||||
/**
|
||||
* 统计周期
|
||||
*/
|
||||
@ExcelProperty(value = "统计周期")
|
||||
private String contractProgress;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
@ExcelProperty(value = "项目ID")
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
@ExcelProperty(value = "项目名称")
|
||||
@Translation(type = TransConstant.PROJECT_ID_TO_NAME, mapper = "projectId")
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 审批金额
|
||||
*/
|
||||
@ExcelProperty(value = "审批金额")
|
||||
private BigDecimal approvalAmount;
|
||||
|
||||
/**
|
||||
* 计量开始日期
|
||||
*/
|
||||
@ExcelProperty(value = "计量开始日期")
|
||||
private LocalDate measureDateBegin;
|
||||
|
||||
/**
|
||||
* 计量结束日期
|
||||
*/
|
||||
@ExcelProperty(value = "计量结束日期")
|
||||
private LocalDate measureDateEnd;
|
||||
|
||||
/**
|
||||
* 结算单位(客户)
|
||||
*/
|
||||
@ExcelProperty(value = "结算单位(客户)")
|
||||
private Long settlementUnit;
|
||||
|
||||
/**
|
||||
* 结算单位名称
|
||||
*/
|
||||
@Translation(type = TransConstant.DEPT_ID_TO_NAME, mapper = "settlementUnit")
|
||||
private String settlementUnitName;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
@ExcelProperty(value = "本期结算金额")
|
||||
private BigDecimal settlementMoney;
|
||||
|
||||
/**
|
||||
* 本期扣款金额
|
||||
*/
|
||||
@ExcelProperty(value = "本期扣款金额")
|
||||
private BigDecimal deductionMoney;
|
||||
|
||||
/**
|
||||
* 本期奖励金额
|
||||
*/
|
||||
@ExcelProperty(value = "本期奖励金额")
|
||||
private BigDecimal bonus;
|
||||
|
||||
/**
|
||||
* 合同金额
|
||||
*/
|
||||
@ExcelProperty(value = "合同金额")
|
||||
private BigDecimal contractAmount;
|
||||
|
||||
/**
|
||||
* 本次结算比例
|
||||
*/
|
||||
@ExcelProperty(value = "本次结算比例")
|
||||
private BigDecimal thisSettlementRatio;
|
||||
|
||||
/**
|
||||
* 支付条款
|
||||
*/
|
||||
@ExcelProperty(value = "支付条款")
|
||||
private Long paymentTerms;
|
||||
|
||||
/**
|
||||
* 多文件逗号分隔
|
||||
*/
|
||||
@ExcelProperty(value = "多文件逗号分隔")
|
||||
private String fileId;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 合同内清单
|
||||
*/
|
||||
private List<CtrContractProgressSettlementItemVo> inInventory;
|
||||
|
||||
/**
|
||||
* 变更增加清单
|
||||
*/
|
||||
private List<CtrContractProgressSettlementItemVo> changeInventory;
|
||||
|
||||
/**
|
||||
* 合同外清单
|
||||
*/
|
||||
private List<CtrContractProgressSettlementItemVo> outInventory;
|
||||
|
||||
}
|
||||
@ -0,0 +1,160 @@
|
||||
package org.dromara.ctr.domain.vo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlementItem;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 分包合同进度结算清单视图对象 ctr_subcontract_progress_settlement_item
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = CtrSubcontractProgressSettlementItem.class)
|
||||
public class CtrSubcontractProgressSettlementItemVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 结算单ID
|
||||
*/
|
||||
@ExcelProperty(value = "结算单ID")
|
||||
private Long settlementId;
|
||||
|
||||
/**
|
||||
* 类型(1合同内清单 2变更增加清单 3合同外清单)
|
||||
*/
|
||||
@ExcelProperty(value = "类型(1合同内清单 2变更增加清单 3合同外清单)")
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
@ExcelProperty(value = "编码")
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 合同清单名称
|
||||
*/
|
||||
@ExcelProperty(value = "合同清单名称")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
*/
|
||||
@ExcelProperty(value = "计量单位")
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
@ExcelProperty(value = "单价")
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/**
|
||||
* 含税单价
|
||||
*/
|
||||
@ExcelProperty(value = "含税单价")
|
||||
private BigDecimal taxUnitPrice;
|
||||
|
||||
/**
|
||||
* 本期结算数量
|
||||
*/
|
||||
@ExcelProperty(value = "本期结算数量")
|
||||
private BigDecimal currentQty;
|
||||
|
||||
/**
|
||||
* 本期结算百分比
|
||||
*/
|
||||
@ExcelProperty(value = "本期结算百分比")
|
||||
private BigDecimal currentRate;
|
||||
|
||||
/**
|
||||
* 本期结算金额
|
||||
*/
|
||||
@ExcelProperty(value = "本期结算金额")
|
||||
private BigDecimal currentAmount;
|
||||
|
||||
/**
|
||||
* 本期结算不含税金额
|
||||
*/
|
||||
@ExcelProperty(value = "本期结算不含税金额")
|
||||
private BigDecimal currentNoAmount;
|
||||
|
||||
/**
|
||||
* 本期审批数量
|
||||
*/
|
||||
@ExcelProperty(value = "本期审批数量")
|
||||
private BigDecimal currentApprovedQty;
|
||||
|
||||
/**
|
||||
* 本期审批金额
|
||||
*/
|
||||
@ExcelProperty(value = "本期审批金额")
|
||||
private BigDecimal currentApprovedAmount;
|
||||
|
||||
/**
|
||||
* 税率(%)
|
||||
*/
|
||||
@ExcelProperty(value = "税率", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "xzd_tax_rate")
|
||||
private String taxRate;
|
||||
|
||||
/**
|
||||
* 税额
|
||||
*/
|
||||
@ExcelProperty(value = "税额")
|
||||
private String tax;
|
||||
|
||||
/**
|
||||
* WBS工作分解结构
|
||||
*/
|
||||
@ExcelProperty(value = "WBS工作分解结构")
|
||||
private String wbs;
|
||||
|
||||
/**
|
||||
* CBS成本分解结构
|
||||
*/
|
||||
@ExcelProperty(value = "CBS成本分解结构")
|
||||
private String cbs;
|
||||
|
||||
/**
|
||||
* CBS预算总额
|
||||
*/
|
||||
@ExcelProperty(value = "CBS预算总额")
|
||||
private BigDecimal cbsBudgetTotal;
|
||||
|
||||
/**
|
||||
* CBS余额
|
||||
*/
|
||||
@ExcelProperty(value = "CBS余额")
|
||||
private BigDecimal cbsBalance;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,173 @@
|
||||
package org.dromara.ctr.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.translation.annotation.Translation;
|
||||
import org.dromara.common.translation.constant.TransConstant;
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlement;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 分包合同进度结算视图对象 ctr_subcontract_progress_settlement
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = CtrSubcontractProgressSettlement.class)
|
||||
public class CtrSubcontractProgressSettlementVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 单据编码
|
||||
*/
|
||||
@ExcelProperty(value = "单据编码")
|
||||
private String documentCode;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@ExcelProperty(value = "标题")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 所属部门
|
||||
*/
|
||||
@ExcelProperty(value = "所属部门")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
@Translation(type = TransConstant.DEPT_ID_TO_NAME, mapper = "deptId")
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 单据日期
|
||||
*/
|
||||
@ExcelProperty(value = "单据日期")
|
||||
private LocalDate documentDate;
|
||||
|
||||
/**
|
||||
* 合同编码
|
||||
*/
|
||||
@ExcelProperty(value = "合同编码")
|
||||
private String contractCode;
|
||||
|
||||
/**
|
||||
* 合同名称
|
||||
*/
|
||||
@ExcelProperty(value = "合同名称")
|
||||
private String contractName;
|
||||
|
||||
/**
|
||||
* 统计周期
|
||||
*/
|
||||
@ExcelProperty(value = "统计周期")
|
||||
private String contractProgress;
|
||||
|
||||
/**
|
||||
* 计量开始日期
|
||||
*/
|
||||
@ExcelProperty(value = "计量开始日期")
|
||||
private LocalDate measureDateBegin;
|
||||
|
||||
/**
|
||||
* 计量结束日期
|
||||
*/
|
||||
@ExcelProperty(value = "计量结束日期")
|
||||
private LocalDate measureDateEnd;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
@ExcelProperty(value = "项目ID")
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 项目名称
|
||||
*/
|
||||
@ExcelProperty(value = "项目名称")
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 审批金额
|
||||
*/
|
||||
@ExcelProperty(value = "审批金额")
|
||||
private BigDecimal approvalAmount;
|
||||
|
||||
/**
|
||||
* 结算单位
|
||||
*/
|
||||
@ExcelProperty(value = "结算单位")
|
||||
private Long settlementUnit;
|
||||
|
||||
/**
|
||||
* 结算单位名称
|
||||
*/
|
||||
@Translation(type = TransConstant.DEPT_ID_TO_NAME, mapper = "settlementUnit")
|
||||
private String settlementUnitName;
|
||||
|
||||
/**
|
||||
* 合同金额
|
||||
*/
|
||||
@ExcelProperty(value = "合同金额")
|
||||
private BigDecimal contractAmount;
|
||||
|
||||
/**
|
||||
* 本次结算比例
|
||||
*/
|
||||
@ExcelProperty(value = "本次结算比例")
|
||||
private BigDecimal currentSettlementRate;
|
||||
|
||||
/**
|
||||
* 文件ID
|
||||
*/
|
||||
@ExcelProperty(value = "文件ID")
|
||||
private String fileId;
|
||||
|
||||
/**
|
||||
* 审核状态
|
||||
*/
|
||||
@ExcelProperty(value = "审核状态")
|
||||
private String auditStatus;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 合同内清单
|
||||
*/
|
||||
private List<CtrSubcontractProgressSettlementItemVo> inInventory;
|
||||
|
||||
/**
|
||||
* 变更增加清单
|
||||
*/
|
||||
private List<CtrSubcontractProgressSettlementItemVo> changeInventory;
|
||||
|
||||
/**
|
||||
* 合同外清单
|
||||
*/
|
||||
private List<CtrSubcontractProgressSettlementItemVo> outInventory;
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package org.dromara.ctr.mapper;
|
||||
|
||||
import org.dromara.ctr.domain.CtrContractProgressSettlementItem;
|
||||
import org.dromara.ctr.domain.vo.CtrContractProgressSettlementItemVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算清单Mapper接口
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
public interface CtrContractProgressSettlementItemMapper extends BaseMapperPlus<CtrContractProgressSettlementItem, CtrContractProgressSettlementItemVo> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package org.dromara.ctr.mapper;
|
||||
|
||||
import org.dromara.ctr.domain.CtrContractProgressSettlement;
|
||||
import org.dromara.ctr.domain.vo.CtrContractProgressSettlementVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算Mapper接口
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
public interface CtrContractProgressSettlementMapper extends BaseMapperPlus<CtrContractProgressSettlement, CtrContractProgressSettlementVo> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package org.dromara.ctr.mapper;
|
||||
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlementItem;
|
||||
import org.dromara.ctr.domain.vo.CtrSubcontractProgressSettlementItemVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 分包合同进度结算清单Mapper接口
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
public interface CtrSubcontractProgressSettlementItemMapper extends BaseMapperPlus<CtrSubcontractProgressSettlementItem, CtrSubcontractProgressSettlementItemVo> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package org.dromara.ctr.mapper;
|
||||
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlement;
|
||||
import org.dromara.ctr.domain.vo.CtrSubcontractProgressSettlementVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 分包合同进度结算Mapper接口
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
public interface CtrSubcontractProgressSettlementMapper extends BaseMapperPlus<CtrSubcontractProgressSettlement, CtrSubcontractProgressSettlementVo> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package org.dromara.ctr.service;
|
||||
|
||||
import org.dromara.ctr.domain.vo.CtrContractProgressSettlementItemVo;
|
||||
import org.dromara.ctr.domain.bo.CtrContractProgressSettlementItemBo;
|
||||
import org.dromara.ctr.domain.CtrContractProgressSettlementItem;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算清单Service接口
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
public interface ICtrContractProgressSettlementItemService extends IService<CtrContractProgressSettlementItem>{
|
||||
|
||||
/**
|
||||
* 查询承包合同进度结算清单
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 承包合同进度结算清单
|
||||
*/
|
||||
CtrContractProgressSettlementItemVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 分页查询承包合同进度结算清单列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 承包合同进度结算清单分页列表
|
||||
*/
|
||||
TableDataInfo<CtrContractProgressSettlementItemVo> queryPageList(CtrContractProgressSettlementItemBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的承包合同进度结算清单列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 承包合同进度结算清单列表
|
||||
*/
|
||||
List<CtrContractProgressSettlementItemVo> queryList(CtrContractProgressSettlementItemBo bo);
|
||||
|
||||
/**
|
||||
* 新增承包合同进度结算清单
|
||||
*
|
||||
* @param bo 承包合同进度结算清单
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(CtrContractProgressSettlementItemBo bo);
|
||||
|
||||
/**
|
||||
* 修改承包合同进度结算清单
|
||||
*
|
||||
* @param bo 承包合同进度结算清单
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(CtrContractProgressSettlementItemBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除承包合同进度结算清单信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package org.dromara.ctr.service;
|
||||
|
||||
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.ctr.domain.CtrContractProgressSettlement;
|
||||
import org.dromara.ctr.domain.bo.CtrContractProgressSettlementBo;
|
||||
import org.dromara.ctr.domain.dto.CtrContractProgressSettlementCreateReq;
|
||||
import org.dromara.ctr.domain.dto.CtrContractProgressSettlementUpdateReq;
|
||||
import org.dromara.ctr.domain.vo.CtrContractProgressSettlementTotalVo;
|
||||
import org.dromara.ctr.domain.vo.CtrContractProgressSettlementVo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算Service接口
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
public interface ICtrContractProgressSettlementService extends IService<CtrContractProgressSettlement> {
|
||||
|
||||
/**
|
||||
* 查询承包合同进度结算
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 承包合同进度结算
|
||||
*/
|
||||
CtrContractProgressSettlementVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 分页查询承包合同进度结算列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 承包合同进度结算分页列表
|
||||
*/
|
||||
TableDataInfo<CtrContractProgressSettlementVo> queryPageList(CtrContractProgressSettlementBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的承包合同进度结算列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 承包合同进度结算列表
|
||||
*/
|
||||
List<CtrContractProgressSettlementVo> queryList(CtrContractProgressSettlementBo bo);
|
||||
|
||||
/**
|
||||
* 查询金额统计
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 金额统计
|
||||
*/
|
||||
CtrContractProgressSettlementTotalVo queryMoneyTotal(CtrContractProgressSettlementBo bo);
|
||||
|
||||
/**
|
||||
* 新增承包合同进度结算
|
||||
*
|
||||
* @param req 承包合同进度结算
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(CtrContractProgressSettlementCreateReq req);
|
||||
|
||||
/**
|
||||
* 修改承包合同进度结算
|
||||
*
|
||||
* @param req 承包合同进度结算
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(CtrContractProgressSettlementUpdateReq req);
|
||||
|
||||
/**
|
||||
* 校验并批量删除承包合同进度结算信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package org.dromara.ctr.service;
|
||||
|
||||
import org.dromara.ctr.domain.vo.CtrSubcontractProgressSettlementItemVo;
|
||||
import org.dromara.ctr.domain.bo.CtrSubcontractProgressSettlementItemBo;
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlementItem;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分包合同进度结算清单Service接口
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
public interface ICtrSubcontractProgressSettlementItemService extends IService<CtrSubcontractProgressSettlementItem>{
|
||||
|
||||
/**
|
||||
* 查询分包合同进度结算清单
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 分包合同进度结算清单
|
||||
*/
|
||||
CtrSubcontractProgressSettlementItemVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 分页查询分包合同进度结算清单列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 分包合同进度结算清单分页列表
|
||||
*/
|
||||
TableDataInfo<CtrSubcontractProgressSettlementItemVo> queryPageList(CtrSubcontractProgressSettlementItemBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的分包合同进度结算清单列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 分包合同进度结算清单列表
|
||||
*/
|
||||
List<CtrSubcontractProgressSettlementItemVo> queryList(CtrSubcontractProgressSettlementItemBo bo);
|
||||
|
||||
/**
|
||||
* 新增分包合同进度结算清单
|
||||
*
|
||||
* @param bo 分包合同进度结算清单
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(CtrSubcontractProgressSettlementItemBo bo);
|
||||
|
||||
/**
|
||||
* 修改分包合同进度结算清单
|
||||
*
|
||||
* @param bo 分包合同进度结算清单
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(CtrSubcontractProgressSettlementItemBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除分包合同进度结算清单信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package org.dromara.ctr.service;
|
||||
|
||||
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.ctr.domain.CtrSubcontractProgressSettlement;
|
||||
import org.dromara.ctr.domain.bo.CtrSubcontractProgressSettlementBo;
|
||||
import org.dromara.ctr.domain.dto.CtrSubcontractProgressSettlementCreateReq;
|
||||
import org.dromara.ctr.domain.dto.CtrSubcontractProgressSettlementUpdateReq;
|
||||
import org.dromara.ctr.domain.vo.CtrSubcontractProgressSettlementVo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分包合同进度结算Service接口
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
public interface ICtrSubcontractProgressSettlementService extends IService<CtrSubcontractProgressSettlement> {
|
||||
|
||||
/**
|
||||
* 查询分包合同进度结算
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 分包合同进度结算
|
||||
*/
|
||||
CtrSubcontractProgressSettlementVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 分页查询分包合同进度结算列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 分包合同进度结算分页列表
|
||||
*/
|
||||
TableDataInfo<CtrSubcontractProgressSettlementVo> queryPageList(CtrSubcontractProgressSettlementBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的分包合同进度结算列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 分包合同进度结算列表
|
||||
*/
|
||||
List<CtrSubcontractProgressSettlementVo> queryList(CtrSubcontractProgressSettlementBo bo);
|
||||
|
||||
/**
|
||||
* 新增分包合同进度结算
|
||||
*
|
||||
* @param req 分包合同进度结算
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(CtrSubcontractProgressSettlementCreateReq req);
|
||||
|
||||
/**
|
||||
* 修改分包合同进度结算
|
||||
*
|
||||
* @param req 分包合同进度结算
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(CtrSubcontractProgressSettlementUpdateReq req);
|
||||
|
||||
/**
|
||||
* 校验并批量删除分包合同进度结算信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
@ -0,0 +1,142 @@
|
||||
package org.dromara.ctr.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.ctr.domain.bo.CtrContractProgressSettlementItemBo;
|
||||
import org.dromara.ctr.domain.vo.CtrContractProgressSettlementItemVo;
|
||||
import org.dromara.ctr.domain.CtrContractProgressSettlementItem;
|
||||
import org.dromara.ctr.mapper.CtrContractProgressSettlementItemMapper;
|
||||
import org.dromara.ctr.service.ICtrContractProgressSettlementItemService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算清单Service业务层处理
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class CtrContractProgressSettlementItemServiceImpl extends ServiceImpl<CtrContractProgressSettlementItemMapper, CtrContractProgressSettlementItem> implements ICtrContractProgressSettlementItemService {
|
||||
|
||||
/**
|
||||
* 查询承包合同进度结算清单
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 承包合同进度结算清单
|
||||
*/
|
||||
@Override
|
||||
public CtrContractProgressSettlementItemVo queryById(Long id){
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询承包合同进度结算清单列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 承包合同进度结算清单分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<CtrContractProgressSettlementItemVo> queryPageList(CtrContractProgressSettlementItemBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<CtrContractProgressSettlementItem> lqw = buildQueryWrapper(bo);
|
||||
Page<CtrContractProgressSettlementItemVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的承包合同进度结算清单列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 承包合同进度结算清单列表
|
||||
*/
|
||||
@Override
|
||||
public List<CtrContractProgressSettlementItemVo> queryList(CtrContractProgressSettlementItemBo bo) {
|
||||
LambdaQueryWrapper<CtrContractProgressSettlementItem> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<CtrContractProgressSettlementItem> buildQueryWrapper(CtrContractProgressSettlementItemBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<CtrContractProgressSettlementItem> lqw = Wrappers.lambdaQuery();
|
||||
lqw.orderByDesc(CtrContractProgressSettlementItem::getId);
|
||||
lqw.eq(bo.getSettlementId() != null, CtrContractProgressSettlementItem::getSettlementId, bo.getSettlementId());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getType()), CtrContractProgressSettlementItem::getType, bo.getType());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getCode()), CtrContractProgressSettlementItem::getCode, bo.getCode());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getName()), CtrContractProgressSettlementItem::getName, bo.getName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getUnit()), CtrContractProgressSettlementItem::getUnit, bo.getUnit());
|
||||
lqw.eq(bo.getUnitPrice() != null, CtrContractProgressSettlementItem::getUnitPrice, bo.getUnitPrice());
|
||||
lqw.eq(bo.getTaxUnitPrice() != null, CtrContractProgressSettlementItem::getTaxUnitPrice, bo.getTaxUnitPrice());
|
||||
lqw.eq(bo.getCurrentQty() != null, CtrContractProgressSettlementItem::getCurrentQty, bo.getCurrentQty());
|
||||
lqw.eq(bo.getCurrentRate() != null, CtrContractProgressSettlementItem::getCurrentRate, bo.getCurrentRate());
|
||||
lqw.eq(bo.getCurrentAmount() != null, CtrContractProgressSettlementItem::getCurrentAmount, bo.getCurrentAmount());
|
||||
lqw.eq(bo.getCurrentNoAmount() != null, CtrContractProgressSettlementItem::getCurrentNoAmount, bo.getCurrentNoAmount());
|
||||
lqw.eq(bo.getCurrentApprovedQty() != null, CtrContractProgressSettlementItem::getCurrentApprovedQty, bo.getCurrentApprovedQty());
|
||||
lqw.eq(bo.getCurrentApprovedAmount() != null, CtrContractProgressSettlementItem::getCurrentApprovedAmount, bo.getCurrentApprovedAmount());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getTaxRate()), CtrContractProgressSettlementItem::getTaxRate, bo.getTaxRate());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增承包合同进度结算清单
|
||||
*
|
||||
* @param bo 承包合同进度结算清单
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(CtrContractProgressSettlementItemBo bo) {
|
||||
CtrContractProgressSettlementItem add = MapstructUtils.convert(bo, CtrContractProgressSettlementItem.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改承包合同进度结算清单
|
||||
*
|
||||
* @param bo 承包合同进度结算清单
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(CtrContractProgressSettlementItemBo bo) {
|
||||
CtrContractProgressSettlementItem update = MapstructUtils.convert(bo, CtrContractProgressSettlementItem.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(CtrContractProgressSettlementItem entity){
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除承包合同进度结算清单信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if(isValid){
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,353 @@
|
||||
package org.dromara.ctr.service.impl;
|
||||
|
||||
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 lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
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.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.ctr.domain.CtrContractProgressSettlement;
|
||||
import org.dromara.ctr.domain.CtrContractProgressSettlementItem;
|
||||
import org.dromara.ctr.domain.bo.CtrContractProgressSettlementBo;
|
||||
import org.dromara.ctr.domain.dto.CtrContractProgressSettlementCreateReq;
|
||||
import org.dromara.ctr.domain.dto.CtrContractProgressSettlementItemCreateReq;
|
||||
import org.dromara.ctr.domain.dto.CtrContractProgressSettlementItemUpdateReq;
|
||||
import org.dromara.ctr.domain.dto.CtrContractProgressSettlementUpdateReq;
|
||||
import org.dromara.ctr.domain.vo.CtrContractProgressSettlementItemVo;
|
||||
import org.dromara.ctr.domain.vo.CtrContractProgressSettlementTotalVo;
|
||||
import org.dromara.ctr.domain.vo.CtrContractProgressSettlementVo;
|
||||
import org.dromara.ctr.mapper.CtrContractProgressSettlementMapper;
|
||||
import org.dromara.ctr.service.ICtrContractProgressSettlementItemService;
|
||||
import org.dromara.ctr.service.ICtrContractProgressSettlementService;
|
||||
import org.dromara.system.domain.vo.SysDeptVo;
|
||||
import org.dromara.system.service.ISysDeptService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 承包合同进度结算Service业务层处理
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class CtrContractProgressSettlementServiceImpl extends ServiceImpl<CtrContractProgressSettlementMapper, CtrContractProgressSettlement>
|
||||
implements ICtrContractProgressSettlementService {
|
||||
|
||||
private final ICtrContractProgressSettlementItemService contractProgressSettlementItemService;
|
||||
|
||||
private final ISysDeptService deptService;
|
||||
|
||||
/**
|
||||
* 查询承包合同进度结算
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 承包合同进度结算
|
||||
*/
|
||||
@Override
|
||||
public CtrContractProgressSettlementVo queryById(Long id) {
|
||||
CtrContractProgressSettlementVo vo = baseMapper.selectVoById(id);
|
||||
List<CtrContractProgressSettlementItem> list = contractProgressSettlementItemService.lambdaQuery()
|
||||
.eq(CtrContractProgressSettlementItem::getSettlementId, id)
|
||||
.list();
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
List<CtrContractProgressSettlementItemVo> listVo = list.stream().map(item ->
|
||||
MapstructUtils.convert(item, CtrContractProgressSettlementItemVo.class))
|
||||
.toList();
|
||||
Map<String, List<CtrContractProgressSettlementItemVo>> map = listVo.stream()
|
||||
.collect(Collectors.groupingBy(CtrContractProgressSettlementItemVo::getType));
|
||||
vo.setInInventory(map.getOrDefault("1", new ArrayList<>()));
|
||||
vo.setChangeInventory(map.getOrDefault("2", new ArrayList<>()));
|
||||
vo.setOutInventory(map.getOrDefault("3", new ArrayList<>()));
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询承包合同进度结算列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 承包合同进度结算分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<CtrContractProgressSettlementVo> queryPageList(CtrContractProgressSettlementBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<CtrContractProgressSettlement> lqw = buildQueryWrapper(bo);
|
||||
Page<CtrContractProgressSettlementVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的承包合同进度结算列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 承包合同进度结算列表
|
||||
*/
|
||||
@Override
|
||||
public List<CtrContractProgressSettlementVo> queryList(CtrContractProgressSettlementBo bo) {
|
||||
LambdaQueryWrapper<CtrContractProgressSettlement> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询金额统计
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 金额统计
|
||||
*/
|
||||
@Override
|
||||
public CtrContractProgressSettlementTotalVo queryMoneyTotal(CtrContractProgressSettlementBo bo) {
|
||||
LambdaQueryWrapper<CtrContractProgressSettlement> lqw = Wrappers.lambdaQuery();
|
||||
Long deptId = bo.getDeptId();
|
||||
String type = bo.getType();
|
||||
if (ObjectUtils.isNotEmpty(deptId) && StringUtils.isNotBlank(type) && !LoginHelper.isSuperAdmin()) {
|
||||
SysDeptVo sysDeptVo = deptService.selectDeptById(deptId);
|
||||
List<Long> list = StringUtils.splitTo(sysDeptVo.getAncestors(), Convert::toLong);
|
||||
if (list.size() == 2 && Objects.equals(type, "1")) {
|
||||
lqw.eq(CtrContractProgressSettlement::getDeptId, deptId);
|
||||
} else if (list.size() == 2 && Objects.equals(type, "2")) {
|
||||
lqw.eq(CtrContractProgressSettlement::getSettlementUnit, deptId);
|
||||
} else if (list.size() > 2 && Objects.equals(type, "1")) {
|
||||
lqw.eq(CtrContractProgressSettlement::getDeptId, list.get(2));
|
||||
} else if (list.size() > 2 && Objects.equals(type, "2")) {
|
||||
lqw.eq(CtrContractProgressSettlement::getSettlementUnit, list.get(2));
|
||||
}
|
||||
}
|
||||
List<CtrContractProgressSettlement> settlementList = this.list(lqw);
|
||||
CtrContractProgressSettlementTotalVo vo = new CtrContractProgressSettlementTotalVo();
|
||||
if (CollUtil.isEmpty(settlementList)) {
|
||||
return vo;
|
||||
}
|
||||
if (Objects.equals(type, "1")) {
|
||||
vo.setMoneyTotal(settlementList.stream().map(CtrContractProgressSettlement::getSettlementMoney)
|
||||
.filter(Objects::nonNull)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
} else if (Objects.equals(type, "2")) {
|
||||
vo.setMoneyTotal(settlementList.stream().map(CtrContractProgressSettlement::getDeductionMoney)
|
||||
.filter(Objects::nonNull)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<CtrContractProgressSettlement> buildQueryWrapper(CtrContractProgressSettlementBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<CtrContractProgressSettlement> lqw = Wrappers.lambdaQuery();
|
||||
lqw.orderByDesc(CtrContractProgressSettlement::getId);
|
||||
Long deptId = bo.getDeptId();
|
||||
String type = bo.getType();
|
||||
if (ObjectUtils.isNotEmpty(deptId) && StringUtils.isNotBlank(type) && !LoginHelper.isSuperAdmin()) {
|
||||
SysDeptVo sysDeptVo = deptService.selectDeptById(deptId);
|
||||
List<Long> list = StringUtils.splitTo(sysDeptVo.getAncestors(), Convert::toLong);
|
||||
if (list.size() == 2 && Objects.equals(type, "1")) {
|
||||
lqw.eq(CtrContractProgressSettlement::getDeptId, deptId);
|
||||
} else if (list.size() == 2 && Objects.equals(type, "2")) {
|
||||
lqw.eq(CtrContractProgressSettlement::getSettlementUnit, deptId);
|
||||
} else if (list.size() > 2 && Objects.equals(type, "1")) {
|
||||
lqw.eq(CtrContractProgressSettlement::getDeptId, list.get(2));
|
||||
} else if (list.size() > 2 && Objects.equals(type, "2")) {
|
||||
lqw.eq(CtrContractProgressSettlement::getSettlementUnit, list.get(2));
|
||||
}
|
||||
}
|
||||
lqw.like(StringUtils.isNotBlank(bo.getDocumentCode()), CtrContractProgressSettlement::getDocumentCode, bo.getDocumentCode());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getTitle()), CtrContractProgressSettlement::getTitle, bo.getTitle());
|
||||
lqw.eq(bo.getSettlementDate() != null, CtrContractProgressSettlement::getSettlementDate, bo.getSettlementDate());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getContractCode()), CtrContractProgressSettlement::getContractCode, bo.getContractCode());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getContractName()), CtrContractProgressSettlement::getContractName, bo.getContractName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getContractProgress()), CtrContractProgressSettlement::getContractProgress, bo.getContractProgress());
|
||||
lqw.eq(bo.getProjectId() != null, CtrContractProgressSettlement::getProjectId, bo.getProjectId());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getProjectName()), CtrContractProgressSettlement::getProjectName, bo.getProjectName());
|
||||
lqw.eq(bo.getApprovalAmount() != null, CtrContractProgressSettlement::getApprovalAmount, bo.getApprovalAmount());
|
||||
lqw.eq(bo.getMeasureDateBegin() != null, CtrContractProgressSettlement::getMeasureDateBegin, bo.getMeasureDateBegin());
|
||||
lqw.eq(bo.getMeasureDateEnd() != null, CtrContractProgressSettlement::getMeasureDateEnd, bo.getMeasureDateEnd());
|
||||
lqw.eq(bo.getSettlementUnit() != null, CtrContractProgressSettlement::getSettlementUnit, bo.getSettlementUnit());
|
||||
lqw.eq(bo.getSettlementMoney() != null, CtrContractProgressSettlement::getSettlementMoney, bo.getSettlementMoney());
|
||||
lqw.eq(bo.getDeductionMoney() != null, CtrContractProgressSettlement::getDeductionMoney, bo.getDeductionMoney());
|
||||
lqw.eq(bo.getBonus() != null, CtrContractProgressSettlement::getBonus, bo.getBonus());
|
||||
lqw.eq(bo.getContractAmount() != null, CtrContractProgressSettlement::getContractAmount, bo.getContractAmount());
|
||||
lqw.eq(bo.getThisSettlementRatio() != null, CtrContractProgressSettlement::getThisSettlementRatio, bo.getThisSettlementRatio());
|
||||
lqw.eq(bo.getPaymentTerms() != null, CtrContractProgressSettlement::getPaymentTerms, bo.getPaymentTerms());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getFileId()), CtrContractProgressSettlement::getFileId, bo.getFileId());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增承包合同进度结算
|
||||
*
|
||||
* @param req 承包合同进度结算
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean insertByBo(CtrContractProgressSettlementCreateReq req) {
|
||||
CtrContractProgressSettlement add = MapstructUtils.convert(req, CtrContractProgressSettlement.class);
|
||||
if (Objects.equals(req.getDeptId(), req.getSettlementUnit())) {
|
||||
throw new ServiceException("结算单位不能与收款单位相同");
|
||||
}
|
||||
// 生成唯一编号
|
||||
LocalDate today = LocalDate.now();
|
||||
Long userId = LoginHelper.getUserId();
|
||||
boolean flag;
|
||||
synchronized (userId.toString().intern()) {
|
||||
LocalDateTime startOfDay = today.atStartOfDay();
|
||||
LocalDateTime endOfDay = today.plusDays(1).atStartOfDay().minusNanos(1);
|
||||
// 获取当天的最大编号
|
||||
Long count = this.lambdaQuery()
|
||||
.between(CtrContractProgressSettlement::getCreateTime, startOfDay, endOfDay)
|
||||
.count();
|
||||
String result = String.format("%03d", count + 1); // 3表示长度,0表示补0
|
||||
add.setDocumentCode(today.format(DateTimeFormatter.BASIC_ISO_DATE) + "-" + result);
|
||||
validEntityBeforeSave(add);
|
||||
flag = baseMapper.insert(add) > 0;
|
||||
}
|
||||
if (flag) {
|
||||
Long id = add.getId();
|
||||
List<CtrContractProgressSettlementItemCreateReq> inInventory = req.getInInventory();
|
||||
List<CtrContractProgressSettlementItemCreateReq> changeInventory = req.getChangeInventory();
|
||||
List<CtrContractProgressSettlementItemCreateReq> outInventory = req.getOutInventory();
|
||||
List<CtrContractProgressSettlementItem> itemList = new ArrayList<>();
|
||||
itemList.addAll(inInventory.stream().map(r -> {
|
||||
CtrContractProgressSettlementItem item = new CtrContractProgressSettlementItem();
|
||||
item.setSettlementId(id);
|
||||
item.setType("1");
|
||||
BeanUtils.copyProperties(r, item);
|
||||
return item;
|
||||
}).toList());
|
||||
itemList.addAll(changeInventory.stream().map(r -> {
|
||||
CtrContractProgressSettlementItem item = new CtrContractProgressSettlementItem();
|
||||
item.setSettlementId(id);
|
||||
item.setType("2");
|
||||
BeanUtils.copyProperties(r, item);
|
||||
return item;
|
||||
}).toList());
|
||||
itemList.addAll(outInventory.stream().map(r -> {
|
||||
CtrContractProgressSettlementItem item = new CtrContractProgressSettlementItem();
|
||||
item.setSettlementId(id);
|
||||
item.setType("3");
|
||||
BeanUtils.copyProperties(r, item);
|
||||
return item;
|
||||
}).toList());
|
||||
if (CollUtil.isNotEmpty(itemList)) {
|
||||
boolean saveBatch = contractProgressSettlementItemService.saveBatch(itemList);
|
||||
if (!saveBatch) {
|
||||
throw new ServiceException("保存承包合同进度结算明细失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改承包合同进度结算
|
||||
*
|
||||
* @param req 承包合同进度结算
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean updateByBo(CtrContractProgressSettlementUpdateReq req) {
|
||||
CtrContractProgressSettlement update = MapstructUtils.convert(req, CtrContractProgressSettlement.class);
|
||||
validEntityBeforeSave(update);
|
||||
if (Objects.equals(req.getDeptId(), req.getSettlementUnit())) {
|
||||
throw new ServiceException("结算单位不能与收款单位相同");
|
||||
}
|
||||
Long id = req.getId();
|
||||
// 删除旧数据
|
||||
List<CtrContractProgressSettlementItem> oldList = contractProgressSettlementItemService.lambdaQuery()
|
||||
.eq(CtrContractProgressSettlementItem::getSettlementId, id)
|
||||
.list();
|
||||
if (CollUtil.isNotEmpty(oldList)) {
|
||||
boolean deleteBatch = contractProgressSettlementItemService.removeByIds(oldList);
|
||||
if (!deleteBatch) {
|
||||
throw new ServiceException("删除承包合同进度结算明细失败");
|
||||
}
|
||||
}
|
||||
// 新增子数据
|
||||
List<CtrContractProgressSettlementItemUpdateReq> inInventory = req.getInInventory();
|
||||
List<CtrContractProgressSettlementItemUpdateReq> changeInventory = req.getChangeInventory();
|
||||
List<CtrContractProgressSettlementItemUpdateReq> outInventory = req.getOutInventory();
|
||||
List<CtrContractProgressSettlementItem> itemList = new ArrayList<>();
|
||||
itemList.addAll(inInventory.stream().map(r -> {
|
||||
CtrContractProgressSettlementItem item = new CtrContractProgressSettlementItem();
|
||||
item.setSettlementId(id);
|
||||
item.setType("1");
|
||||
BeanUtils.copyProperties(r, item);
|
||||
return item;
|
||||
}).toList());
|
||||
itemList.addAll(changeInventory.stream().map(r -> {
|
||||
CtrContractProgressSettlementItem item = new CtrContractProgressSettlementItem();
|
||||
item.setSettlementId(id);
|
||||
item.setType("2");
|
||||
BeanUtils.copyProperties(r, item);
|
||||
return item;
|
||||
}).toList());
|
||||
itemList.addAll(outInventory.stream().map(r -> {
|
||||
CtrContractProgressSettlementItem item = new CtrContractProgressSettlementItem();
|
||||
item.setSettlementId(id);
|
||||
item.setType("3");
|
||||
BeanUtils.copyProperties(r, item);
|
||||
return item;
|
||||
}).toList());
|
||||
if (CollUtil.isNotEmpty(itemList)) {
|
||||
boolean saveBatch = contractProgressSettlementItemService.saveBatch(itemList);
|
||||
if (!saveBatch) {
|
||||
throw new ServiceException("保存承包合同进度结算明细失败");
|
||||
}
|
||||
}
|
||||
// 保存主数据
|
||||
boolean b = baseMapper.updateById(update) > 0;
|
||||
if (!b) {
|
||||
throw new ServiceException("修改承包合同进度结算失败");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(CtrContractProgressSettlement entity) {
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除承包合同进度结算信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
// 删除关联数据
|
||||
List<CtrContractProgressSettlementItem> list = contractProgressSettlementItemService.lambdaQuery()
|
||||
.in(CtrContractProgressSettlementItem::getSettlementId, ids)
|
||||
.list();
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
boolean deleteBatch = contractProgressSettlementItemService.removeByIds(list);
|
||||
if (!deleteBatch) {
|
||||
throw new ServiceException("删除承包合同进度结算明细失败");
|
||||
}
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,150 @@
|
||||
package org.dromara.ctr.service.impl;
|
||||
|
||||
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 lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
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.ctr.domain.CtrSubcontractProgressSettlementItem;
|
||||
import org.dromara.ctr.domain.bo.CtrSubcontractProgressSettlementItemBo;
|
||||
import org.dromara.ctr.domain.vo.CtrSubcontractProgressSettlementItemVo;
|
||||
import org.dromara.ctr.mapper.CtrSubcontractProgressSettlementItemMapper;
|
||||
import org.dromara.ctr.service.ICtrSubcontractProgressSettlementItemService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 分包合同进度结算清单Service业务层处理
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class CtrSubcontractProgressSettlementItemServiceImpl extends ServiceImpl<CtrSubcontractProgressSettlementItemMapper, CtrSubcontractProgressSettlementItem>
|
||||
implements ICtrSubcontractProgressSettlementItemService {
|
||||
|
||||
private final CtrSubcontractProgressSettlementItemMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询分包合同进度结算清单
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 分包合同进度结算清单
|
||||
*/
|
||||
@Override
|
||||
public CtrSubcontractProgressSettlementItemVo queryById(Long id) {
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询分包合同进度结算清单列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 分包合同进度结算清单分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<CtrSubcontractProgressSettlementItemVo> queryPageList(CtrSubcontractProgressSettlementItemBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<CtrSubcontractProgressSettlementItem> lqw = buildQueryWrapper(bo);
|
||||
Page<CtrSubcontractProgressSettlementItemVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的分包合同进度结算清单列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 分包合同进度结算清单列表
|
||||
*/
|
||||
@Override
|
||||
public List<CtrSubcontractProgressSettlementItemVo> queryList(CtrSubcontractProgressSettlementItemBo bo) {
|
||||
LambdaQueryWrapper<CtrSubcontractProgressSettlementItem> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<CtrSubcontractProgressSettlementItem> buildQueryWrapper(CtrSubcontractProgressSettlementItemBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<CtrSubcontractProgressSettlementItem> lqw = Wrappers.lambdaQuery();
|
||||
lqw.orderByDesc(CtrSubcontractProgressSettlementItem::getId);
|
||||
lqw.eq(bo.getSettlementId() != null, CtrSubcontractProgressSettlementItem::getSettlementId, bo.getSettlementId());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getType()), CtrSubcontractProgressSettlementItem::getType, bo.getType());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getCode()), CtrSubcontractProgressSettlementItem::getCode, bo.getCode());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getName()), CtrSubcontractProgressSettlementItem::getName, bo.getName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getUnit()), CtrSubcontractProgressSettlementItem::getUnit, bo.getUnit());
|
||||
lqw.eq(bo.getUnitPrice() != null, CtrSubcontractProgressSettlementItem::getUnitPrice, bo.getUnitPrice());
|
||||
lqw.eq(bo.getTaxUnitPrice() != null, CtrSubcontractProgressSettlementItem::getTaxUnitPrice, bo.getTaxUnitPrice());
|
||||
lqw.eq(bo.getCurrentQty() != null, CtrSubcontractProgressSettlementItem::getCurrentQty, bo.getCurrentQty());
|
||||
lqw.eq(bo.getCurrentRate() != null, CtrSubcontractProgressSettlementItem::getCurrentRate, bo.getCurrentRate());
|
||||
lqw.eq(bo.getCurrentAmount() != null, CtrSubcontractProgressSettlementItem::getCurrentAmount, bo.getCurrentAmount());
|
||||
lqw.eq(bo.getCurrentNoAmount() != null, CtrSubcontractProgressSettlementItem::getCurrentNoAmount, bo.getCurrentNoAmount());
|
||||
lqw.eq(bo.getCurrentApprovedQty() != null, CtrSubcontractProgressSettlementItem::getCurrentApprovedQty, bo.getCurrentApprovedQty());
|
||||
lqw.eq(bo.getCurrentApprovedAmount() != null, CtrSubcontractProgressSettlementItem::getCurrentApprovedAmount, bo.getCurrentApprovedAmount());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getTaxRate()), CtrSubcontractProgressSettlementItem::getTaxRate, bo.getTaxRate());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getTax()), CtrSubcontractProgressSettlementItem::getTax, bo.getTax());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getWbs()), CtrSubcontractProgressSettlementItem::getWbs, bo.getWbs());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getCbs()), CtrSubcontractProgressSettlementItem::getCbs, bo.getCbs());
|
||||
lqw.eq(bo.getCbsBudgetTotal() != null, CtrSubcontractProgressSettlementItem::getCbsBudgetTotal, bo.getCbsBudgetTotal());
|
||||
lqw.eq(bo.getCbsBalance() != null, CtrSubcontractProgressSettlementItem::getCbsBalance, bo.getCbsBalance());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增分包合同进度结算清单
|
||||
*
|
||||
* @param bo 分包合同进度结算清单
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(CtrSubcontractProgressSettlementItemBo bo) {
|
||||
CtrSubcontractProgressSettlementItem add = MapstructUtils.convert(bo, CtrSubcontractProgressSettlementItem.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改分包合同进度结算清单
|
||||
*
|
||||
* @param bo 分包合同进度结算清单
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(CtrSubcontractProgressSettlementItemBo bo) {
|
||||
CtrSubcontractProgressSettlementItem update = MapstructUtils.convert(bo, CtrSubcontractProgressSettlementItem.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(CtrSubcontractProgressSettlementItem entity) {
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除分包合同进度结算清单信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,280 @@
|
||||
package org.dromara.ctr.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
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 lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
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.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlement;
|
||||
import org.dromara.ctr.domain.CtrSubcontractProgressSettlementItem;
|
||||
import org.dromara.ctr.domain.bo.CtrSubcontractProgressSettlementBo;
|
||||
import org.dromara.ctr.domain.dto.CtrSubcontractProgressSettlementCreateReq;
|
||||
import org.dromara.ctr.domain.dto.CtrSubcontractProgressSettlementItemCreateReq;
|
||||
import org.dromara.ctr.domain.dto.CtrSubcontractProgressSettlementItemUpdateReq;
|
||||
import org.dromara.ctr.domain.dto.CtrSubcontractProgressSettlementUpdateReq;
|
||||
import org.dromara.ctr.domain.vo.CtrSubcontractProgressSettlementItemVo;
|
||||
import org.dromara.ctr.domain.vo.CtrSubcontractProgressSettlementVo;
|
||||
import org.dromara.ctr.mapper.CtrSubcontractProgressSettlementMapper;
|
||||
import org.dromara.ctr.service.ICtrSubcontractProgressSettlementItemService;
|
||||
import org.dromara.ctr.service.ICtrSubcontractProgressSettlementService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 分包合同进度结算Service业务层处理
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-18
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class CtrSubcontractProgressSettlementServiceImpl extends ServiceImpl<CtrSubcontractProgressSettlementMapper, CtrSubcontractProgressSettlement>
|
||||
implements ICtrSubcontractProgressSettlementService {
|
||||
|
||||
private final ICtrSubcontractProgressSettlementItemService subcontractProgressSettlementItemService;
|
||||
|
||||
/**
|
||||
* 查询分包合同进度结算
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 分包合同进度结算
|
||||
*/
|
||||
@Override
|
||||
public CtrSubcontractProgressSettlementVo queryById(Long id) {
|
||||
CtrSubcontractProgressSettlementVo vo = baseMapper.selectVoById(id);
|
||||
List<CtrSubcontractProgressSettlementItem> list = subcontractProgressSettlementItemService.lambdaQuery()
|
||||
.eq(CtrSubcontractProgressSettlementItem::getSettlementId, id)
|
||||
.list();
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
List<CtrSubcontractProgressSettlementItemVo> listVo = list.stream().map(item ->
|
||||
MapstructUtils.convert(item, CtrSubcontractProgressSettlementItemVo.class))
|
||||
.toList();
|
||||
Map<String, List<CtrSubcontractProgressSettlementItemVo>> map = listVo.stream()
|
||||
.collect(Collectors.groupingBy(CtrSubcontractProgressSettlementItemVo::getType));
|
||||
vo.setInInventory(map.getOrDefault("1", new ArrayList<>()));
|
||||
vo.setChangeInventory(map.getOrDefault("2", new ArrayList<>()));
|
||||
vo.setOutInventory(map.getOrDefault("3", new ArrayList<>()));
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询分包合同进度结算列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 分包合同进度结算分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<CtrSubcontractProgressSettlementVo> queryPageList(CtrSubcontractProgressSettlementBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<CtrSubcontractProgressSettlement> lqw = buildQueryWrapper(bo);
|
||||
Page<CtrSubcontractProgressSettlementVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的分包合同进度结算列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 分包合同进度结算列表
|
||||
*/
|
||||
@Override
|
||||
public List<CtrSubcontractProgressSettlementVo> queryList(CtrSubcontractProgressSettlementBo bo) {
|
||||
LambdaQueryWrapper<CtrSubcontractProgressSettlement> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<CtrSubcontractProgressSettlement> buildQueryWrapper(CtrSubcontractProgressSettlementBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<CtrSubcontractProgressSettlement> lqw = Wrappers.lambdaQuery();
|
||||
lqw.orderByDesc(CtrSubcontractProgressSettlement::getId);
|
||||
lqw.like(StringUtils.isNotBlank(bo.getDocumentCode()), CtrSubcontractProgressSettlement::getDocumentCode, bo.getDocumentCode());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getTitle()), CtrSubcontractProgressSettlement::getTitle, bo.getTitle());
|
||||
lqw.eq(bo.getDocumentDate() != null, CtrSubcontractProgressSettlement::getDocumentDate, bo.getDocumentDate());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getContractCode()), CtrSubcontractProgressSettlement::getContractCode, bo.getContractCode());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getContractName()), CtrSubcontractProgressSettlement::getContractName, bo.getContractName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getContractProgress()), CtrSubcontractProgressSettlement::getContractProgress, bo.getContractProgress());
|
||||
lqw.eq(bo.getMeasureDateBegin() != null, CtrSubcontractProgressSettlement::getMeasureDateBegin, bo.getMeasureDateBegin());
|
||||
lqw.eq(bo.getMeasureDateEnd() != null, CtrSubcontractProgressSettlement::getMeasureDateEnd, bo.getMeasureDateEnd());
|
||||
lqw.eq(bo.getProjectId() != null, CtrSubcontractProgressSettlement::getProjectId, bo.getProjectId());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getProjectName()), CtrSubcontractProgressSettlement::getProjectName, bo.getProjectName());
|
||||
lqw.eq(bo.getApprovalAmount() != null, CtrSubcontractProgressSettlement::getApprovalAmount, bo.getApprovalAmount());
|
||||
lqw.eq(bo.getSettlementUnit() != null, CtrSubcontractProgressSettlement::getSettlementUnit, bo.getSettlementUnit());
|
||||
lqw.eq(bo.getContractAmount() != null, CtrSubcontractProgressSettlement::getContractAmount, bo.getContractAmount());
|
||||
lqw.eq(bo.getCurrentSettlementRate() != null, CtrSubcontractProgressSettlement::getCurrentSettlementRate, bo.getCurrentSettlementRate());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getFileId()), CtrSubcontractProgressSettlement::getFileId, bo.getFileId());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getAuditStatus()), CtrSubcontractProgressSettlement::getAuditStatus, bo.getAuditStatus());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增分包合同进度结算
|
||||
*
|
||||
* @param req 分包合同进度结算
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(CtrSubcontractProgressSettlementCreateReq req) {
|
||||
CtrSubcontractProgressSettlement add = MapstructUtils.convert(req, CtrSubcontractProgressSettlement.class);
|
||||
// 生成唯一编号
|
||||
LocalDate today = LocalDate.now();
|
||||
Long userId = LoginHelper.getUserId();
|
||||
boolean flag;
|
||||
synchronized (userId.toString().intern()) {
|
||||
LocalDateTime startOfDay = today.atStartOfDay();
|
||||
LocalDateTime endOfDay = today.plusDays(1).atStartOfDay().minusNanos(1);
|
||||
// 获取当天的最大编号
|
||||
Long count = this.lambdaQuery()
|
||||
.between(CtrSubcontractProgressSettlement::getCreateTime, startOfDay, endOfDay)
|
||||
.count();
|
||||
String result = String.format("%03d", count + 1); // 3表示长度,0表示补0
|
||||
add.setDocumentCode(today.format(DateTimeFormatter.BASIC_ISO_DATE) + "-" + result);
|
||||
validEntityBeforeSave(add);
|
||||
flag = baseMapper.insert(add) > 0;
|
||||
}
|
||||
if (flag) {
|
||||
Long id = add.getId();
|
||||
List<CtrSubcontractProgressSettlementItemCreateReq> inInventory = req.getInInventory();
|
||||
List<CtrSubcontractProgressSettlementItemCreateReq> changeInventory = req.getChangeInventory();
|
||||
List<CtrSubcontractProgressSettlementItemCreateReq> outInventory = req.getOutInventory();
|
||||
List<CtrSubcontractProgressSettlementItem> itemList = new ArrayList<>();
|
||||
itemList.addAll(inInventory.stream().map(r -> {
|
||||
CtrSubcontractProgressSettlementItem item = new CtrSubcontractProgressSettlementItem();
|
||||
item.setSettlementId(id);
|
||||
item.setType("1");
|
||||
BeanUtils.copyProperties(r, item);
|
||||
return item;
|
||||
}).toList());
|
||||
itemList.addAll(changeInventory.stream().map(r -> {
|
||||
CtrSubcontractProgressSettlementItem item = new CtrSubcontractProgressSettlementItem();
|
||||
item.setSettlementId(id);
|
||||
item.setType("2");
|
||||
BeanUtils.copyProperties(r, item);
|
||||
return item;
|
||||
}).toList());
|
||||
itemList.addAll(outInventory.stream().map(r -> {
|
||||
CtrSubcontractProgressSettlementItem item = new CtrSubcontractProgressSettlementItem();
|
||||
item.setSettlementId(id);
|
||||
item.setType("3");
|
||||
BeanUtils.copyProperties(r, item);
|
||||
return item;
|
||||
}).toList());
|
||||
if (CollUtil.isNotEmpty(itemList)) {
|
||||
boolean saveBatch = subcontractProgressSettlementItemService.saveBatch(itemList);
|
||||
if (!saveBatch) {
|
||||
throw new ServiceException("保存分包合同进度结算明细失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改分包合同进度结算
|
||||
*
|
||||
* @param req 分包合同进度结算
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(CtrSubcontractProgressSettlementUpdateReq req) {
|
||||
CtrSubcontractProgressSettlement update = MapstructUtils.convert(req, CtrSubcontractProgressSettlement.class);
|
||||
validEntityBeforeSave(update);
|
||||
Long id = req.getId();
|
||||
// 删除旧数据
|
||||
List<CtrSubcontractProgressSettlementItem> oldList = subcontractProgressSettlementItemService.lambdaQuery()
|
||||
.eq(CtrSubcontractProgressSettlementItem::getSettlementId, id)
|
||||
.list();
|
||||
if (CollUtil.isNotEmpty(oldList)) {
|
||||
boolean deleteBatch = subcontractProgressSettlementItemService.removeByIds(oldList);
|
||||
if (!deleteBatch) {
|
||||
throw new ServiceException("删除分包合同进度结算明细失败");
|
||||
}
|
||||
}
|
||||
// 新增子数据
|
||||
List<CtrSubcontractProgressSettlementItemUpdateReq> inInventory = req.getInInventory();
|
||||
List<CtrSubcontractProgressSettlementItemUpdateReq> changeInventory = req.getChangeInventory();
|
||||
List<CtrSubcontractProgressSettlementItemUpdateReq> outInventory = req.getOutInventory();
|
||||
List<CtrSubcontractProgressSettlementItem> itemList = new ArrayList<>();
|
||||
itemList.addAll(inInventory.stream().map(r -> {
|
||||
CtrSubcontractProgressSettlementItem item = new CtrSubcontractProgressSettlementItem();
|
||||
item.setSettlementId(id);
|
||||
item.setType("1");
|
||||
BeanUtils.copyProperties(r, item);
|
||||
return item;
|
||||
}).toList());
|
||||
itemList.addAll(changeInventory.stream().map(r -> {
|
||||
CtrSubcontractProgressSettlementItem item = new CtrSubcontractProgressSettlementItem();
|
||||
item.setSettlementId(id);
|
||||
item.setType("2");
|
||||
BeanUtils.copyProperties(r, item);
|
||||
return item;
|
||||
}).toList());
|
||||
itemList.addAll(outInventory.stream().map(r -> {
|
||||
CtrSubcontractProgressSettlementItem item = new CtrSubcontractProgressSettlementItem();
|
||||
item.setSettlementId(id);
|
||||
item.setType("3");
|
||||
BeanUtils.copyProperties(r, item);
|
||||
return item;
|
||||
}).toList());
|
||||
if (CollUtil.isNotEmpty(itemList)) {
|
||||
boolean saveBatch = subcontractProgressSettlementItemService.saveBatch(itemList);
|
||||
if (!saveBatch) {
|
||||
throw new ServiceException("保存承包合同进度结算明细失败");
|
||||
}
|
||||
}
|
||||
// 保存主数据
|
||||
boolean b = baseMapper.updateById(update) > 0;
|
||||
if (!b) {
|
||||
throw new ServiceException("修改分包合同进度结算失败");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(CtrSubcontractProgressSettlement entity) {
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除分包合同进度结算信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
// 删除关联数据
|
||||
List<CtrSubcontractProgressSettlementItem> list = subcontractProgressSettlementItemService.lambdaQuery()
|
||||
.in(CtrSubcontractProgressSettlementItem::getSettlementId, ids)
|
||||
.list();
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
boolean deleteBatch = subcontractProgressSettlementItemService.removeByIds(list);
|
||||
if (!deleteBatch) {
|
||||
throw new ServiceException("删除分包合同进度结算明细失败");
|
||||
}
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,146 @@
|
||||
package org.dromara.design.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
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.web.core.BaseController;
|
||||
import org.dromara.design.domain.DesConstructionSchedulePlan;
|
||||
import org.dromara.design.domain.dto.constructionscheduleplan.*;
|
||||
import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo;
|
||||
import org.dromara.design.service.IDesConstructionSchedulePlanService;
|
||||
|
||||
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 设计计划
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-08-01
|
||||
*/
|
||||
@Validated
|
||||
@RestController
|
||||
@RequestMapping("/design/constructionSchedulePlan")
|
||||
public class DesConstructionSchedulePlanController extends BaseController {
|
||||
|
||||
@Resource
|
||||
private IDesConstructionSchedulePlanService desConstructionSchedulePlanService;
|
||||
|
||||
/**
|
||||
* 查询设计计划列表
|
||||
*/
|
||||
@SaCheckPermission("design:constructionSchedulePlan:list")
|
||||
@GetMapping("/list")
|
||||
public R<List<DesConstructionSchedulePlanVo>> list(DesConstructionSchedulePlanQueryReq req) {
|
||||
List<DesConstructionSchedulePlanVo> list = desConstructionSchedulePlanService.queryList(req);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出设计计划列表
|
||||
*/
|
||||
@SaCheckPermission("design:constructionSchedulePlan:export")
|
||||
@Log(title = "施工进度计划", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(DesConstructionSchedulePlanQueryReq req, HttpServletResponse response) {
|
||||
List<DesConstructionSchedulePlanVo> list = desConstructionSchedulePlanService.queryList(req);
|
||||
ExcelUtil.exportExcel(list, "施工进度计划", DesConstructionSchedulePlanVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据项目id导出设计计划模版
|
||||
*/
|
||||
@SaCheckPermission("design:constructionSchedulePlan:exportTemplate")
|
||||
@Log(title = "施工进度计划", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/exportTemplate/{projectId}")
|
||||
public void exportExcelByProjectId(@NotNull(message = "项目id不能为空")
|
||||
@PathVariable Long projectId, HttpServletResponse response) {
|
||||
desConstructionSchedulePlanService.exportExcelByProjectId(projectId, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取设计计划模版
|
||||
*/
|
||||
@SaCheckPermission("design:constructionSchedulePlan:readTemplate")
|
||||
@Log(title = "施工进度计划", businessType = BusinessType.IMPORT)
|
||||
@PostMapping("/readTemplate")
|
||||
public R<Void> readExcel(@RequestParam("file") MultipartFile file, Long projectId) {
|
||||
List<DesConstructionSchedulePlanExcelDto> list = desConstructionSchedulePlanService.readExcel(file, projectId);
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
List<DesConstructionSchedulePlan> planList = desConstructionSchedulePlanService.convertToEntities(list);
|
||||
return toAjax(desConstructionSchedulePlanService.saveBatch(planList));
|
||||
}
|
||||
return toAjax(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设计计划详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("design:constructionSchedulePlan:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<DesConstructionSchedulePlanVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(desConstructionSchedulePlanService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增设计计划
|
||||
*/
|
||||
@SaCheckPermission("design:constructionSchedulePlan:add")
|
||||
@Log(title = "施工进度计划", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<DesConstructionSchedulePlanVo> add(@Validated @RequestBody DesConstructionSchedulePlanCreateReq req) {
|
||||
return R.ok(desConstructionSchedulePlanService.insertByBo(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改设计计划
|
||||
*/
|
||||
@SaCheckPermission("design:constructionSchedulePlan:edit")
|
||||
@Log(title = "施工进度计划", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated @RequestBody DesConstructionSchedulePlanUpdateReq req) {
|
||||
return toAjax(desConstructionSchedulePlanService.updateByBo(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改设计计划为完成状态
|
||||
*
|
||||
*/
|
||||
@SaCheckPermission("design:constructionSchedulePlan:editFinish")
|
||||
@Log(title = "施工进度计划", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping("/finish")
|
||||
public R<Void> editFinish(@Validated @RequestBody DesConstructionSchedulePlanFinishReq req) {
|
||||
return toAjax(desConstructionSchedulePlanService.updateFinish(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除设计计划
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("design:constructionSchedulePlan:remove")
|
||||
@Log(title = "施工进度计划", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(desConstructionSchedulePlanService.deleteByIds(List.of(ids)));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package org.dromara.design.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 施工进度计划对象 pgs_construction_schedule_plan
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-08-01
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("des_construction_schedule_plan")
|
||||
public class DesConstructionSchedulePlan extends BaseEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 父ID
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 对应项目结构
|
||||
*/
|
||||
private Long projectStructure;
|
||||
|
||||
/**
|
||||
* 对应项目结构名称
|
||||
*/
|
||||
private String projectStructureName;
|
||||
|
||||
/**
|
||||
* 预计开始时间
|
||||
*/
|
||||
private LocalDate planStartDate;
|
||||
|
||||
/**
|
||||
* 预计结束时间
|
||||
*/
|
||||
private LocalDate planEndDate;
|
||||
|
||||
/**
|
||||
* 实际开始时间
|
||||
*/
|
||||
private LocalDate practicalStartDate;
|
||||
|
||||
/**
|
||||
* 实际结束时间
|
||||
*/
|
||||
private LocalDate practicalEndDate;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package org.dromara.design.domain.dto.constructionscheduleplan;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-08-01 14:05
|
||||
*/
|
||||
@Data
|
||||
public class DesConstructionSchedulePlanCreateReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 4060838737379600701L;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
@NotNull(message = "项目ID不能为空")
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 父ID
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
@NotBlank(message = "节点名称不能为空")
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 对应项目结构
|
||||
*/
|
||||
private Long projectStructure;
|
||||
|
||||
/**
|
||||
* 对应项目结构名称
|
||||
*/
|
||||
private String projectStructureName;
|
||||
|
||||
/**
|
||||
* 预计开始时间
|
||||
*/
|
||||
private LocalDate planStartDate;
|
||||
|
||||
/**
|
||||
* 预计结束时间
|
||||
*/
|
||||
private LocalDate planEndDate;
|
||||
|
||||
/**
|
||||
* 实际开始时间
|
||||
*/
|
||||
private LocalDate practicalStartDate;
|
||||
|
||||
/**
|
||||
* 实际结束时间
|
||||
*/
|
||||
private LocalDate practicalEndDate;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
package org.dromara.design.domain.dto.constructionscheduleplan;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-09-06 17:12
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class DesConstructionSchedulePlanExcelDto {
|
||||
|
||||
/**
|
||||
* 编号(1, 1.1, 1.1.1)
|
||||
*/
|
||||
private String number;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 对应项目结构
|
||||
*/
|
||||
private Long projectStructure;
|
||||
|
||||
/**
|
||||
* 对应项目结构名称
|
||||
*/
|
||||
private String projectStructureName;
|
||||
|
||||
/**
|
||||
* 预计开始时间
|
||||
*/
|
||||
private LocalDate planStartDate;
|
||||
|
||||
/**
|
||||
* 预计结束时间
|
||||
*/
|
||||
private LocalDate planEndDate;
|
||||
|
||||
/**
|
||||
* 实际开始时间
|
||||
*/
|
||||
private LocalDate practicalStartDate;
|
||||
|
||||
/**
|
||||
* 实际结束时间
|
||||
*/
|
||||
private LocalDate practicalEndDate;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package org.dromara.design.domain.dto.constructionscheduleplan;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-09-17 10:15
|
||||
*/
|
||||
@Data
|
||||
public class DesConstructionSchedulePlanFinishReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 8139653508791280689L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@NotNull(message = "主键不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 完成时间
|
||||
*/
|
||||
@NotNull(message = "完成时间不能为空")
|
||||
private LocalDate finishDate;
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package org.dromara.design.domain.dto.constructionscheduleplan;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-08-01 14:05
|
||||
*/
|
||||
@Data
|
||||
public class DesConstructionSchedulePlanQueryReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 9021370369055688811L;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 对应项目结构名称
|
||||
*/
|
||||
private String projectStructureName;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package org.dromara.design.domain.dto.constructionscheduleplan;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-08-01 14:06
|
||||
*/
|
||||
@Data
|
||||
public class DesConstructionSchedulePlanUpdateReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 6955873817030428268L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 父ID
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 对应项目结构
|
||||
*/
|
||||
private Long projectStructure;
|
||||
|
||||
/**
|
||||
* 对应项目结构名称
|
||||
*/
|
||||
private String projectStructureName;
|
||||
|
||||
/**
|
||||
* 预计开始时间
|
||||
*/
|
||||
private LocalDate planStartDate;
|
||||
|
||||
/**
|
||||
* 预计结束时间
|
||||
*/
|
||||
private LocalDate planEndDate;
|
||||
|
||||
/**
|
||||
* 实际开始时间
|
||||
*/
|
||||
private LocalDate practicalStartDate;
|
||||
|
||||
/**
|
||||
* 实际结束时间
|
||||
*/
|
||||
private LocalDate practicalEndDate;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
package org.dromara.design.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.progress.domain.PgsConstructionSchedulePlan;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
|
||||
|
||||
/**
|
||||
* 施工进度计划视图对象 pgs_construction_schedule_plan
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-08-01
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = PgsConstructionSchedulePlan.class)
|
||||
public class DesConstructionSchedulePlanVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 项目ID
|
||||
*/
|
||||
@ExcelProperty(value = "项目ID")
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 父ID
|
||||
*/
|
||||
@ExcelProperty(value = "父ID")
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
*/
|
||||
@ExcelProperty(value = "节点名称")
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 对应项目结构
|
||||
*/
|
||||
@ExcelProperty(value = "对应项目结构")
|
||||
private Long projectStructure;
|
||||
|
||||
/**
|
||||
* 对应项目结构名称
|
||||
*/
|
||||
@ExcelProperty(value = "对应项目结构名称")
|
||||
private String projectStructureName;
|
||||
|
||||
/**
|
||||
* 预计开始时间
|
||||
*/
|
||||
@ExcelProperty(value = "预计开始时间")
|
||||
private LocalDate planStartDate;
|
||||
|
||||
/**
|
||||
* 预计结束时间
|
||||
*/
|
||||
@ExcelProperty(value = "预计结束时间")
|
||||
private LocalDate planEndDate;
|
||||
|
||||
/**
|
||||
* 实际开始时间
|
||||
*/
|
||||
@ExcelProperty(value = "实际开始时间")
|
||||
private LocalDate practicalStartDate;
|
||||
|
||||
/**
|
||||
* 实际结束时间
|
||||
*/
|
||||
@ExcelProperty(value = "实际结束时间")
|
||||
private LocalDate practicalEndDate;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "project_construction_status")
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package org.dromara.design.mapper;
|
||||
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.dromara.design.domain.DesConstructionSchedulePlan;
|
||||
import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo;
|
||||
import org.dromara.progress.domain.PgsConstructionSchedulePlan;
|
||||
import org.dromara.progress.domain.vo.constructionscheduleplan.PgsConstructionSchedulePlanVo;
|
||||
|
||||
/**
|
||||
* 施工进度计划Mapper接口
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-08-01
|
||||
*/
|
||||
public interface DesConstructionSchedulePlanMapper extends BaseMapperPlus<DesConstructionSchedulePlan, DesConstructionSchedulePlanVo> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
package org.dromara.design.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.dromara.design.domain.DesConstructionSchedulePlan;
|
||||
import org.dromara.design.domain.dto.constructionscheduleplan.*;
|
||||
import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 施工进度计划Service接口
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-08-01
|
||||
*/
|
||||
public interface IDesConstructionSchedulePlanService extends IService<DesConstructionSchedulePlan> {
|
||||
|
||||
/**
|
||||
* 查询施工进度计划
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 施工进度计划
|
||||
*/
|
||||
DesConstructionSchedulePlanVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询符合条件的施工进度计划列表
|
||||
*
|
||||
* @param req 查询条件
|
||||
* @return 施工进度计划列表
|
||||
*/
|
||||
List<DesConstructionSchedulePlanVo> queryList(DesConstructionSchedulePlanQueryReq req);
|
||||
|
||||
/**
|
||||
* 新增施工进度计划
|
||||
*
|
||||
* @param req 施工进度计划
|
||||
* @return 新增施工进度计划封装
|
||||
*/
|
||||
DesConstructionSchedulePlanVo insertByBo(DesConstructionSchedulePlanCreateReq req);
|
||||
|
||||
/**
|
||||
* 修改施工进度计划
|
||||
*
|
||||
* @param req 施工进度计划
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(DesConstructionSchedulePlanUpdateReq req);
|
||||
|
||||
/**
|
||||
* 修改施工进度计划为完成状态
|
||||
*
|
||||
* @param req 施工进度计划
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateFinish(DesConstructionSchedulePlanFinishReq req);
|
||||
|
||||
/**
|
||||
* 批量删除施工进度计划信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteByIds(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获取施工进度计划视图对象
|
||||
*
|
||||
* @param constructionSchedulePlan 施工进度计划对象
|
||||
* @return 施工进度计划视图对象
|
||||
*/
|
||||
DesConstructionSchedulePlanVo getVo(DesConstructionSchedulePlan constructionSchedulePlan);
|
||||
|
||||
/**
|
||||
* 获取施工进度计划查询条件封装
|
||||
*
|
||||
* @param req 查询条件
|
||||
* @return 查询条件封装
|
||||
*/
|
||||
LambdaQueryWrapper<DesConstructionSchedulePlan> buildQueryWrapper(DesConstructionSchedulePlanQueryReq req);
|
||||
|
||||
/**
|
||||
* 获取施工进度计划分页对象视图
|
||||
*
|
||||
* @param constructionSchedulePlanList 施工进度计划分页对象
|
||||
* @return 施工进度计划分页对象视图
|
||||
*/
|
||||
List<DesConstructionSchedulePlanVo> getVoList(List<DesConstructionSchedulePlan> constructionSchedulePlanList);
|
||||
|
||||
/**
|
||||
* 导出Excel
|
||||
*
|
||||
* @param projectId 项目id
|
||||
*/
|
||||
void exportExcelByProjectId(Long projectId, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 读取Excel文件
|
||||
*
|
||||
* @param file Excel文件
|
||||
* @param projectId 项目ID
|
||||
* @return 读取的数据列表
|
||||
*/
|
||||
List<DesConstructionSchedulePlanExcelDto> readExcel(MultipartFile file, Long projectId);
|
||||
|
||||
/**
|
||||
* 将Excel数据转换为实体列表
|
||||
*
|
||||
* @param excelList Excel数据列表
|
||||
* @return 实体列表
|
||||
*/
|
||||
List<DesConstructionSchedulePlan> convertToEntities(List<DesConstructionSchedulePlanExcelDto> excelList);
|
||||
}
|
||||
@ -0,0 +1,627 @@
|
||||
package org.dromara.design.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.dromara.common.core.constant.HttpStatus;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.ObjectUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.design.domain.DesConstructionSchedulePlan;
|
||||
import org.dromara.design.domain.bo.DesUserBo;
|
||||
import org.dromara.design.domain.dto.constructionscheduleplan.*;
|
||||
import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo;
|
||||
import org.dromara.design.mapper.DesConstructionSchedulePlanMapper;
|
||||
import org.dromara.design.service.IDesConstructionSchedulePlanService;
|
||||
|
||||
import org.dromara.project.service.IBusProjectService;
|
||||
import org.dromara.system.domain.vo.SysDictDataVo;
|
||||
import org.dromara.system.service.ISysDictDataService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 施工进度计划Service业务层处理
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-08-01
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DesConstructionSchedulePlanServiceImpl extends ServiceImpl<DesConstructionSchedulePlanMapper, DesConstructionSchedulePlan>
|
||||
implements IDesConstructionSchedulePlanService {
|
||||
|
||||
@Resource
|
||||
private IBusProjectService projectService;
|
||||
|
||||
@Resource
|
||||
private ISysDictDataService dictDataService;
|
||||
|
||||
/**
|
||||
* 查询施工进度计划
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 施工进度计划
|
||||
*/
|
||||
@Override
|
||||
public DesConstructionSchedulePlanVo queryById(Long id) {
|
||||
DesConstructionSchedulePlan constructionSchedulePlan = this.getById(id);
|
||||
if (constructionSchedulePlan == null) {
|
||||
throw new ServiceException("施工进度计划信息不存在", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return this.getVo(constructionSchedulePlan);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的施工进度计划列表
|
||||
*
|
||||
* @param req 查询条件
|
||||
* @return 施工进度计划列表
|
||||
*/
|
||||
@Override
|
||||
public List<DesConstructionSchedulePlanVo> queryList(DesConstructionSchedulePlanQueryReq req) {
|
||||
List<DesConstructionSchedulePlan> result = this.list(this.buildQueryWrapper(req));
|
||||
return this.getVoList(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增施工进度计划
|
||||
*
|
||||
* @param req 施工进度计划
|
||||
* @return 新增施工进度计划封装
|
||||
*/
|
||||
@Override
|
||||
public DesConstructionSchedulePlanVo insertByBo(DesConstructionSchedulePlanCreateReq req) {
|
||||
DesConstructionSchedulePlan constructionSchedulePlan = new DesConstructionSchedulePlan();
|
||||
BeanUtils.copyProperties(req, constructionSchedulePlan);
|
||||
boolean save = this.save(constructionSchedulePlan);
|
||||
if (!save) {
|
||||
throw new ServiceException("新增施工进度计划信息异常", HttpStatus.ERROR);
|
||||
}
|
||||
DesConstructionSchedulePlan newConstructionSchedulePlan = this.getById(constructionSchedulePlan.getId());
|
||||
return this.getVo(newConstructionSchedulePlan);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改施工进度计划
|
||||
*
|
||||
* @param req 施工进度计划
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(DesConstructionSchedulePlanUpdateReq req) {
|
||||
DesConstructionSchedulePlan constructionSchedulePlan = new DesConstructionSchedulePlan();
|
||||
BeanUtils.copyProperties(req, constructionSchedulePlan);
|
||||
return this.updateById(constructionSchedulePlan);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改施工进度计划为完成状态
|
||||
*
|
||||
* @param req 施工进度计划
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateFinish(DesConstructionSchedulePlanFinishReq req) {
|
||||
DesConstructionSchedulePlan plan = this.getById(req.getId());
|
||||
if (plan == null) {
|
||||
throw new ServiceException("施工进度计划信息不存在", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
if (plan.getStatus().equals("4")) {
|
||||
throw new ServiceException("施工进度计划已完成", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
LocalDate practicalStartDate = plan.getPracticalStartDate();
|
||||
LocalDate finishDate = req.getFinishDate();
|
||||
if (practicalStartDate == null) {
|
||||
throw new ServiceException("请先填写实际开始时间", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
if (finishDate.isBefore(practicalStartDate)) {
|
||||
throw new ServiceException("实际结束时间不能早于实际开始时间", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
plan.setStatus("4");
|
||||
plan.setPracticalEndDate(finishDate);
|
||||
return this.updateById(plan);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除施工进度计划信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean deleteByIds(Collection<Long> ids) {
|
||||
return this.removeBatchByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取施工进度计划视图对象
|
||||
*
|
||||
* @param constructionSchedulePlan 施工进度计划对象
|
||||
* @return 施工进度计划视图对象
|
||||
*/
|
||||
@Override
|
||||
public DesConstructionSchedulePlanVo getVo(DesConstructionSchedulePlan constructionSchedulePlan) {
|
||||
DesConstructionSchedulePlanVo vo = new DesConstructionSchedulePlanVo();
|
||||
if (constructionSchedulePlan == null) {
|
||||
return vo;
|
||||
}
|
||||
BeanUtils.copyProperties(constructionSchedulePlan, vo);
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取施工进度计划查询条件封装
|
||||
*
|
||||
* @param req 查询条件
|
||||
* @return 查询条件封装
|
||||
*/
|
||||
@Override
|
||||
public LambdaQueryWrapper<DesConstructionSchedulePlan> buildQueryWrapper(DesConstructionSchedulePlanQueryReq req) {
|
||||
LambdaQueryWrapper<DesConstructionSchedulePlan> lqw = new LambdaQueryWrapper<>();
|
||||
if (req == null) {
|
||||
return lqw;
|
||||
}
|
||||
Long projectId = req.getProjectId();
|
||||
String nodeName = req.getNodeName();
|
||||
String status = req.getStatus();
|
||||
lqw.eq(ObjectUtils.isNotEmpty(projectId), DesConstructionSchedulePlan::getProjectId, projectId);
|
||||
lqw.like(StringUtils.isNotBlank(nodeName), DesConstructionSchedulePlan::getNodeName, nodeName);
|
||||
lqw.eq(StringUtils.isNotBlank(status), DesConstructionSchedulePlan::getStatus, status);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取施工进度计划分页对象视图
|
||||
*
|
||||
* @param constructionSchedulePlanList 施工进度计划分页对象
|
||||
* @return 施工进度计划分页对象视图
|
||||
*/
|
||||
@Override
|
||||
public List<DesConstructionSchedulePlanVo> getVoList(List<DesConstructionSchedulePlan> constructionSchedulePlanList) {
|
||||
return constructionSchedulePlanList.stream().map(this::getVo).toList();
|
||||
}
|
||||
|
||||
// region 导出 excel
|
||||
|
||||
/**
|
||||
* 导出Excel
|
||||
*
|
||||
* @param projectId 项目id
|
||||
*/
|
||||
@Override
|
||||
public void exportExcelByProjectId(Long projectId, HttpServletResponse response) {
|
||||
DesUserBo desUserBo = new DesUserBo();
|
||||
desUserBo.setProjectId(projectId);
|
||||
Map<Long, String> projectStructureMap = projectService.getStructureAsList(projectId);
|
||||
if (projectStructureMap.isEmpty()) {
|
||||
throw new ServiceException("获取项目列表失败,项目为空!!!");
|
||||
}
|
||||
List<SysDictDataVo> dictDataVos = dictDataService.selectByDictType("project_construction_status");
|
||||
if (dictDataVos == null || dictDataVos.isEmpty()) {
|
||||
throw new ServiceException("项目施工状态为空!!");
|
||||
}
|
||||
Map<String, String> statusMap = new HashMap<>();
|
||||
for (SysDictDataVo vo : dictDataVos) {
|
||||
statusMap.put(vo.getDictValue(), vo.getDictLabel());
|
||||
}
|
||||
|
||||
|
||||
Workbook workbook = new XSSFWorkbook();
|
||||
// 创建主 Sheet 和隐藏 Sheet
|
||||
Sheet mainSheet = workbook.createSheet("设计里程碑计划模版");
|
||||
Sheet dataSheet = workbook.createSheet("DropdownData");
|
||||
workbook.setSheetHidden(workbook.getSheetIndex(dataSheet), true);
|
||||
|
||||
// 3. 创建单元格样式
|
||||
CellStyle editableStyle = createEditableCellStyle(workbook); // 可编辑单元格样式
|
||||
CellStyle protectedStyle = createProtectedCellStyle(workbook); // 受保护单元格样式(ID列用
|
||||
//填充隐藏数据Sheet
|
||||
int rowIndex = 0;
|
||||
// 填充项目关联结构(A列和B列)
|
||||
for (Map.Entry<Long, String> entry : projectStructureMap.entrySet()) {
|
||||
Row row = dataSheet.createRow(rowIndex++);
|
||||
row.createCell(0).setCellValue(entry.getValue());
|
||||
row.createCell(1).setCellValue(entry.getKey().toString());
|
||||
}
|
||||
// 重置行索引,填充人员和人员ID(C列和D列)
|
||||
rowIndex = 0;
|
||||
for (Map.Entry<String, String> entry : statusMap.entrySet()) {
|
||||
Row row = dataSheet.getRow(rowIndex);
|
||||
if (row == null) {
|
||||
row = dataSheet.createRow(rowIndex);
|
||||
}
|
||||
row.createCell(4).setCellValue(entry.getValue());
|
||||
row.createCell(5).setCellValue(entry.getKey());
|
||||
rowIndex++;
|
||||
}
|
||||
// 主 Sheet 设置表头
|
||||
Row sheetRow = mainSheet.createRow(0);
|
||||
String[] headers = {"编号(格式:1,1.1,1.1.1。用于进行父子结构关联)", "节点名称",
|
||||
"预计开始时间(输入格式:2025-09-06)", "预计结束时间", "实际开始时间", "实际结束时间", "状态", "状态编码", "备注"};
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
Cell cell = sheetRow.createCell(i);
|
||||
cell.setCellValue(headers[i]);
|
||||
if (i == 0) {
|
||||
CellStyle css = workbook.createCellStyle();
|
||||
DataFormat format = workbook.createDataFormat();
|
||||
css.setDataFormat(format.getFormat("@"));
|
||||
cell.setCellStyle(css);
|
||||
}
|
||||
|
||||
}
|
||||
// 6. 设置专业下拉列表(第二列)
|
||||
// setMajorDropdown(mainSheet, projectStructureMap.size());
|
||||
setStatusDropdown(mainSheet, statusMap.size());
|
||||
// String formulaTemplate = "IFERROR(INDEX(DropdownData!$B$1:$B$" + projectStructureMap.size() + ", MATCH(C{rowNum}, DropdownData!$A$1:$A$" + projectStructureMap.size() + ", 0)),\"\")";
|
||||
String formulaTemplate1 = "IFERROR(INDEX(DropdownData!$F$1:$F$" + statusMap.size() + ", MATCH(G{rowNum}, DropdownData!$E$1:$E$" + statusMap.size() + ", 0)),\"\")";
|
||||
for (int i = 1; i <= 1000; i++) { // 从第2行到101行
|
||||
Row row = mainSheet.createRow(i);
|
||||
int currentRowNum = i + 1; // Excel行号从1开始
|
||||
// String formula = formulaTemplate.replace("{rowNum}", String.valueOf(currentRowNum));
|
||||
//
|
||||
// Cell cell = row.createCell(2);
|
||||
// cell.setCellStyle(editableStyle); //专业不锁定
|
||||
//
|
||||
// Cell idCell = row.createCell(3);
|
||||
// idCell.setCellFormula(formula);
|
||||
// idCell.setCellStyle(protectedStyle); // 应用隐藏公式样式
|
||||
|
||||
String formula1 = formulaTemplate1.replace("{rowNum}", String.valueOf(currentRowNum));
|
||||
|
||||
Cell cell1 = row.createCell(6);
|
||||
cell1.setCellStyle(editableStyle); //专业不锁定
|
||||
|
||||
Cell idCell1 = row.createCell(7);
|
||||
idCell1.setCellFormula(formula1);
|
||||
idCell1.setCellStyle(protectedStyle); // 应用隐藏公式样式
|
||||
|
||||
}
|
||||
|
||||
|
||||
for (int i = 1; i <= 100; i++) {
|
||||
Row row = mainSheet.getRow(i);
|
||||
if (row == null) {
|
||||
row = mainSheet.createRow(i);
|
||||
}
|
||||
Cell cell = row.createCell(0);
|
||||
CellStyle textStyle = workbook.createCellStyle();
|
||||
textStyle.setLocked(false);
|
||||
DataFormat format = workbook.createDataFormat();
|
||||
textStyle.setDataFormat(format.getFormat("@")); // "@" 表示文本格式
|
||||
cell.setCellStyle(textStyle);
|
||||
|
||||
Cell cell1 = row.createCell(1);
|
||||
cell1.setCellStyle(editableStyle);
|
||||
|
||||
Cell cell4 = row.createCell(2);
|
||||
cell4.setCellStyle(editableStyle);
|
||||
|
||||
Cell cell5 = row.createCell(3);
|
||||
cell5.setCellStyle(editableStyle);
|
||||
|
||||
Cell cell6 = row.createCell(4);
|
||||
cell6.setCellStyle(editableStyle);
|
||||
|
||||
Cell cell7 = row.createCell(5);
|
||||
cell7.setCellStyle(editableStyle);
|
||||
|
||||
Cell cell10 = row.createCell(8);
|
||||
cell10.setCellStyle(editableStyle);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 保护工作表,仅允许编辑未锁定的单元格
|
||||
mainSheet.protectSheet("123456"); // 空密码
|
||||
|
||||
// 核心:锁定表头(第1行)和前1列(包含ID列)
|
||||
mainSheet.createFreezePane(0, 1, 0, 1);
|
||||
|
||||
// 调整列宽(更新列索引)
|
||||
mainSheet.setColumnWidth(0, 20 * 320); // 编号
|
||||
mainSheet.setColumnWidth(1, 20 * 280); // 节点名称
|
||||
mainSheet.setColumnWidth(2, 20 * 320); // 预计开始时间
|
||||
mainSheet.setColumnWidth(3, 20 * 200); // 预计结束时间
|
||||
mainSheet.setColumnWidth(4, 20 * 200); // 实际开始时间
|
||||
mainSheet.setColumnWidth(5, 20 * 200); // 实际结束时间
|
||||
mainSheet.setColumnWidth(6, 20 * 100); // 状态
|
||||
mainSheet.setColumnWidth(7, 20 * 200); // 状态编码
|
||||
mainSheet.setColumnWidth(8, 20 * 200); // 备注
|
||||
|
||||
|
||||
// 2. 设置响应头
|
||||
// 设置响应头,指定Excel格式和下载文件名
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("设计里程碑计划模版.xlsx", StandardCharsets.UTF_8));
|
||||
|
||||
// 直接写入响应输出流
|
||||
try {
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建可编辑单元格样式
|
||||
*/
|
||||
private CellStyle createEditableCellStyle(Workbook workbook) {
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
style.setLocked(false); // 关键:允许编辑
|
||||
return style;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建受保护单元格样式(用于ID列)
|
||||
*/
|
||||
private CellStyle createProtectedCellStyle(Workbook workbook) {
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
DataFormat dataFormat = workbook.createDataFormat();
|
||||
short formatIndex = dataFormat.getFormat("0"); // 匹配“自定义→0”格式
|
||||
style.setDataFormat(formatIndex);
|
||||
style.setHidden(true); // 隐藏公式
|
||||
style.setLocked(true);
|
||||
return style;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置专业下拉列表(第二列,索引1)
|
||||
*/
|
||||
private void setMajorDropdown(Sheet mainSheet, int majorCount) {
|
||||
DataValidationHelper helper = mainSheet.getDataValidationHelper();
|
||||
|
||||
// 专业数据范围:数据Sheet的A列(从第1行到专业数量行)
|
||||
String majorRange = "DropdownData!$A$1:$A$" + majorCount;
|
||||
|
||||
DataValidationConstraint constraint = helper.createFormulaListConstraint(majorRange);
|
||||
// 作用范围:第2行到100行,第二列
|
||||
CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, 2, 2);
|
||||
|
||||
DataValidation validation = helper.createValidation(constraint, addressList);
|
||||
validation.setShowErrorBox(true);
|
||||
mainSheet.addValidationData(validation);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置专业下拉列表(第二列,索引1)
|
||||
*/
|
||||
private void setStatusDropdown(Sheet mainSheet, int majorCount) {
|
||||
DataValidationHelper helper = mainSheet.getDataValidationHelper();
|
||||
|
||||
// 专业数据范围:数据Sheet的A列(从第1行到专业数量行)
|
||||
String majorRange = "DropdownData!$E$1:$E$" + majorCount;
|
||||
|
||||
DataValidationConstraint constraint = helper.createFormulaListConstraint(majorRange);
|
||||
// 作用范围:第2行到100行,第二列
|
||||
CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, 6, 6);
|
||||
|
||||
DataValidation validation = helper.createValidation(constraint, addressList);
|
||||
validation.setShowErrorBox(true);
|
||||
mainSheet.addValidationData(validation);
|
||||
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
/**
|
||||
* 读取Excel文件
|
||||
*
|
||||
* @param file Excel文件
|
||||
* @param projectId 项目ID
|
||||
* @return 读取的数据列表
|
||||
*/
|
||||
@Override
|
||||
public List<DesConstructionSchedulePlanExcelDto> readExcel(MultipartFile file, Long projectId) {
|
||||
List<DesConstructionSchedulePlanExcelDto> dataList = new ArrayList<>();
|
||||
|
||||
try (InputStream inputStream = file.getInputStream();
|
||||
XSSFWorkbook workbook = new XSSFWorkbook(inputStream)) {
|
||||
|
||||
XSSFSheet sheet = workbook.getSheetAt(0);
|
||||
|
||||
// 从第二行(index=1)开始读取数据,跳过表头
|
||||
for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
||||
Row row = sheet.getRow(rowIndex);
|
||||
if (hasValidData(row)) {
|
||||
String number = getCellValue(row.getCell(0));
|
||||
String nodeName = getCellValue(row.getCell(1));
|
||||
String projectStructureName = null;
|
||||
Long projectStructure = null;
|
||||
LocalDate planStartDate = getLocalDateValue(row.getCell(2));
|
||||
LocalDate planEndDate = getLocalDateValue(row.getCell(3));
|
||||
LocalDate practicalStartDate = getLocalDateValue(row.getCell(4));
|
||||
LocalDate practicalEndDate = getLocalDateValue(row.getCell(5));
|
||||
String status = getCellValue(row.getCell(7));
|
||||
String remark = getCellValue(row.getCell(8));
|
||||
|
||||
DesConstructionSchedulePlanExcelDto excelData = new DesConstructionSchedulePlanExcelDto(
|
||||
number, projectId, nodeName, projectStructure, projectStructureName,
|
||||
planStartDate, planEndDate, practicalStartDate, practicalEndDate, status, remark
|
||||
);
|
||||
dataList.add(excelData);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("读取表格数据失败", e);
|
||||
throw new ServiceException("读取表格数据失败");
|
||||
}
|
||||
|
||||
return dataList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Excel数据转换为实体列表
|
||||
*
|
||||
* @param excelList Excel数据列表
|
||||
* @return 实体列表
|
||||
*/
|
||||
@Override
|
||||
public List<DesConstructionSchedulePlan> convertToEntities(List<DesConstructionSchedulePlanExcelDto> excelList) {
|
||||
List<DesConstructionSchedulePlan> result = new ArrayList<>();
|
||||
Map<String, Long> numberIdMap = new HashMap<>();
|
||||
|
||||
for (DesConstructionSchedulePlanExcelDto dto : excelList) {
|
||||
DesConstructionSchedulePlan entity = new DesConstructionSchedulePlan();
|
||||
|
||||
LocalDate planStartDate = dto.getPlanStartDate();
|
||||
LocalDate planEndDate = dto.getPlanEndDate();
|
||||
if (planStartDate == null || planEndDate == null || planStartDate.isAfter(planEndDate)) {
|
||||
throw new ServiceException("计划开始时间和计划结束时间不能为空,且计划开始时间不能大于计划结束时间", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 生成主键
|
||||
Long id = IdWorker.getId();
|
||||
entity.setId(id);
|
||||
|
||||
entity.setProjectId(dto.getProjectId());
|
||||
entity.setNodeName(dto.getNodeName());
|
||||
entity.setProjectStructure(dto.getProjectStructure());
|
||||
entity.setProjectStructureName(dto.getProjectStructureName());
|
||||
entity.setPlanStartDate(planStartDate);
|
||||
entity.setPlanEndDate(planEndDate);
|
||||
entity.setPracticalStartDate(dto.getPracticalStartDate());
|
||||
entity.setPracticalEndDate(dto.getPracticalEndDate());
|
||||
entity.setStatus(dto.getStatus());
|
||||
entity.setRemark(dto.getRemark());
|
||||
// 确定父ID
|
||||
String number = dto.getNumber();
|
||||
if (number != null && number.contains(".")) {
|
||||
String parentNumber = number.substring(0, number.lastIndexOf("."));
|
||||
Long parentId = numberIdMap.get(parentNumber);
|
||||
if (parentId == null) {
|
||||
throw new ServiceException("未找到父编号:" + parentNumber, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
entity.setParentId(parentId);
|
||||
} else {
|
||||
entity.setParentId(0L); // 顶级节点
|
||||
}
|
||||
|
||||
// 保存当前编号对应的id
|
||||
numberIdMap.put(number, id);
|
||||
result.add(entity);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean hasValidData(Row row) {
|
||||
// 遍历行中的所有单元格
|
||||
for (int cellIndex = 0; cellIndex < row.getLastCellNum(); cellIndex++) {
|
||||
Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
|
||||
String cellValue = getCellValue(cell).trim();
|
||||
|
||||
// 只要有一个单元格有非空值,就认为是有效行
|
||||
if (!cellValue.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String getCellValue(Cell cell) {
|
||||
if (cell == null) {
|
||||
return "";
|
||||
}
|
||||
// 使用CellType枚举判断单元格类型(POI 4.0+版本推荐方式)
|
||||
CellType cellType = cell.getCellType();
|
||||
// 对于公式单元格,获取其计算结果的类型
|
||||
if (cellType == CellType.FORMULA) {
|
||||
cellType = cell.getCachedFormulaResultType();
|
||||
}
|
||||
|
||||
switch (cellType) {
|
||||
case STRING:
|
||||
return cell.getStringCellValue().trim();
|
||||
case NUMERIC:
|
||||
if (DateUtil.isCellDateFormatted(cell)) {
|
||||
Date date = cell.getDateCellValue();
|
||||
return date.toString();
|
||||
} else {
|
||||
// 处理数字类型,避免科学计数法
|
||||
// 处理数字,移除不必要的.0后缀
|
||||
String numericValue = String.valueOf(cell.getNumericCellValue());
|
||||
if (numericValue.endsWith(".0")) {
|
||||
return numericValue.substring(0, numericValue.length() - 2);
|
||||
}
|
||||
return numericValue;
|
||||
}
|
||||
case BOOLEAN:
|
||||
return String.valueOf(cell.getBooleanCellValue());
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private static LocalDate getLocalDateValue(Cell cell) {
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CellType cellType = cell.getCellType();
|
||||
if (cellType == CellType.FORMULA) {
|
||||
cellType = cell.getCachedFormulaResultType();
|
||||
}
|
||||
|
||||
try {
|
||||
if (cellType == CellType.NUMERIC) {
|
||||
if (DateUtil.isCellDateFormatted(cell)) {
|
||||
Date date = cell.getDateCellValue();
|
||||
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
} else {
|
||||
// 如果是数字但不是日期,就尝试转为 LocalDate (例如 20250730)
|
||||
double numericValue = cell.getNumericCellValue();
|
||||
String text = String.valueOf((long) numericValue);
|
||||
return LocalDate.parse(text);
|
||||
}
|
||||
} else if (cellType == CellType.STRING) {
|
||||
String text = cell.getStringCellValue().trim();
|
||||
if (text.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
// 尝试解析不同格式
|
||||
try {
|
||||
return LocalDate.parse(text); // 默认 ISO 格式 yyyy-MM-dd
|
||||
} catch (Exception e) {
|
||||
// 如果 Excel 是 yyyy/MM/dd 或 yyyy.MM.dd,可以额外处理
|
||||
try {
|
||||
return LocalDate.parse(text, java.time.format.DateTimeFormatter.ofPattern("yyyy/MM/dd"));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
try {
|
||||
return LocalDate.parse(text, java.time.format.DateTimeFormatter.ofPattern("yyyy.MM.dd"));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return null; // 不识别的格式就返回 null
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -628,6 +628,7 @@ public class DesDesignChangeServiceImpl extends ServiceImpl<DesDesignChangeMappe
|
||||
} else if ("2".equals(bean.getDesignDisposal())) {
|
||||
LambdaUpdateWrapper<DesVolumeFile> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.set(DesVolumeFile::getType, DesVolumeFile.WASTE)
|
||||
.eq(DesVolumeFile::getType, DesVolumeFile.BLUEPRINT)
|
||||
.eq(DesVolumeFile::getVolumeCatalogId, volumeCatalog.getDesign());
|
||||
String saveFile = designChange.getSaveFile();
|
||||
if (StringUtils.isNotBlank(saveFile)) {
|
||||
@ -658,7 +659,7 @@ public class DesDesignChangeServiceImpl extends ServiceImpl<DesDesignChangeMappe
|
||||
String lastVersion = list.getFirst().getVersion();
|
||||
// 提取版本号数字部分(去除LT-前缀)
|
||||
String versionNumber = lastVersion;
|
||||
if (lastVersion.startsWith("LT-")) {
|
||||
if (lastVersion.startsWith("LT-") || lastVersion.startsWith("GC-")) {
|
||||
versionNumber = lastVersion.substring(3); // 去除"LT-"前缀
|
||||
}
|
||||
int majorVersion = (int) Math.floor(Double.parseDouble(versionNumber)) + 1;
|
||||
|
||||
@ -448,9 +448,9 @@ public class DesDrawingServiceImpl extends ServiceImpl<DesDrawingMapper, DesDraw
|
||||
try {
|
||||
ByteArrayOutputStream baos = PdfBoxQrCodeGenerator.addQRCodeToPDFOnAllPages(ossVo.getUrl(), bytes,isChangeFile);
|
||||
|
||||
try (FileOutputStream fileOut = new FileOutputStream("C:\\Users\\YuanJie\\Desktop\\test1.pdf")) {
|
||||
baos.writeTo(fileOut);
|
||||
}
|
||||
// try (FileOutputStream fileOut = new FileOutputStream("C:\\Users\\YuanJie\\Desktop\\test1.pdf")) {
|
||||
// baos.writeTo(fileOut);
|
||||
// }
|
||||
|
||||
FileNameMap fileNameMap = URLConnection.getFileNameMap();
|
||||
String originalName = ossVo.getOriginalName();
|
||||
|
||||
@ -421,17 +421,17 @@ public class DesVolumeFileServiceImpl extends ServiceImpl<DesVolumeFileMapper, D
|
||||
|
||||
if (DesVolumeFile.BLUEPRINT.equals(type)) {
|
||||
// 蓝图文件:LT-1.0, LT-1.1, LT-1.2...
|
||||
if (CollectionUtil.isEmpty(existingFilesInDB)) {
|
||||
// 没有历史版本,从1.0开始,根据文件索引递增
|
||||
int minorVersion = fileIndex;
|
||||
versionStr = "LT-1." + minorVersion;
|
||||
} else {
|
||||
// 有历史版本,基于最高版本递增
|
||||
double maxVersion = Double.parseDouble(maxBatchVersion);
|
||||
int majorVersion = (int) Math.floor(maxVersion);
|
||||
int minorVersion = (int) ((maxVersion - majorVersion) * 10) + fileIndex + 1;
|
||||
|
||||
// 如果是第一个文件且没有历史版本,则从1.0开始
|
||||
if (fileIndex == 0 && CollectionUtil.isEmpty(existingFilesInDB)) {
|
||||
versionStr = "1.0";
|
||||
} else {
|
||||
versionStr = majorVersion + "." + minorVersion;
|
||||
int minorVersion = (int) Math.round((maxVersion - majorVersion) * 10) + fileIndex + 1;
|
||||
versionStr = "LT-" + majorVersion + "." + minorVersion;
|
||||
}
|
||||
versionStr = "LT-" + versionStr;
|
||||
} else if (DesVolumeFile.PROCESS.equals(type)) {
|
||||
// 过程图纸:基于蓝图版本号
|
||||
List<DesVolumeFile> blueprintFiles = baseMapper.selectList(new LambdaQueryWrapper<DesVolumeFile>()
|
||||
|
||||
@ -8,6 +8,7 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.gps.domain.vo.GpsStatusVo;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
@ -56,6 +57,16 @@ public class GpsEquipmentSonController extends BaseController {
|
||||
return R.ok(gpsEquipmentSonService.queryList(bo));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询GPS设备定位日期信息列表
|
||||
*/
|
||||
@SaCheckPermission("gps:equipmentSon:getRlList")
|
||||
@GetMapping("/getRlList")
|
||||
public R<List<GpsStatusVo>> getRlList(GpsEquipmentSonBo bo) {
|
||||
return R.ok(gpsEquipmentSonService.getRlList(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询GPS设备定位信息列表(大屏获取人员最后一次位置)
|
||||
*/
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
package org.dromara.gps.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Data
|
||||
public class GpsStatusVo implements Serializable {
|
||||
private LocalDate riqi;
|
||||
private Long count;
|
||||
}
|
||||
@ -3,8 +3,10 @@ package org.dromara.gps.mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.dromara.gps.domain.GpsEquipmentSon;
|
||||
import org.dromara.gps.domain.bo.GpsEquipmentSonBo;
|
||||
import org.dromara.gps.domain.vo.GpsEquipmentSonVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.dromara.gps.domain.vo.GpsStatusVo;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
@ -28,9 +30,10 @@ public interface GpsEquipmentSonMapper extends BaseMapperPlus<GpsEquipmentSon, G
|
||||
"AND create_time BETWEEN #{startTime} AND #{endTime}\n" +
|
||||
")\n" +
|
||||
"SELECT\n" +
|
||||
" *\n" +
|
||||
" r.*,su.nick_name as userName\n" +
|
||||
"FROM\n" +
|
||||
" RankedData\n" +
|
||||
" RankedData r\n" +
|
||||
"LEFT JOIN sys_user su ON r.user_id=su.user_id\n" +
|
||||
"WHERE\n" +
|
||||
" rn = 1;")
|
||||
List<GpsEquipmentSonVo> getClientList(@Param("projectId") Long projectId, @Param("startTime") LocalDateTime startOfDay, @Param("endTime") LocalDateTime now);
|
||||
@ -77,4 +80,32 @@ public interface GpsEquipmentSonMapper extends BaseMapperPlus<GpsEquipmentSon, G
|
||||
"WHERE\n" +
|
||||
" rn = 1;")
|
||||
List<GpsEquipmentSonVo> getUserListByProjectId(@Param("projectId") Long projectId, @Param("startTime") LocalDateTime startOfDay, @Param("endTime") LocalDateTime now);
|
||||
|
||||
@Select("WITH RECURSIVE date_range AS (\n" +
|
||||
" -- 1. 初始化开始日期(取startTime的“年月日”部分,忽略时分秒)\n" +
|
||||
" SELECT DATE(#{bo.startTime}) AS stat_date\n" +
|
||||
" UNION ALL\n" +
|
||||
" -- 2. 递归生成后续日期,直到不超过endTime的“年月日”\n" +
|
||||
" SELECT DATE_ADD(stat_date, INTERVAL 1 DAY)\n" +
|
||||
" FROM date_range\n" +
|
||||
" WHERE stat_date < DATE(#{bo.endTime})\n" +
|
||||
")\n" +
|
||||
"\n" +
|
||||
"SELECT \n" +
|
||||
" dr.stat_date AS riqi, -- 统计日期(格式:YYYY-MM-DD)\n" +
|
||||
" COUNT(ges.id) AS count -- 当天符合条件的记录数\n" +
|
||||
"FROM date_range dr\n" +
|
||||
"LEFT JOIN (\n" +
|
||||
" SELECT \n" +
|
||||
" DATE(create_time) AS data_date, -- 提取创建时间的“年月日”\n" +
|
||||
" id -- 仅需主键用于计数(减少数据传输)\n" +
|
||||
" FROM gps_equipment_son\n" +
|
||||
" WHERE \n" +
|
||||
" project_id = #{bo.projectId} -- 匹配项目ID\n" +
|
||||
" AND client_id =#{bo.clientId} -- 客户端ID为空\n" +
|
||||
" AND create_time BETWEEN #{bo.startTime} AND #{bo.endTime} -- 时间范围\n" +
|
||||
") ges ON dr.stat_date = ges.data_date -- 按日期关联\n" +
|
||||
"GROUP BY dr.stat_date -- 按统计日期分组\n" +
|
||||
"ORDER BY dr.stat_date; -- 按日期升序排列")
|
||||
List<GpsStatusVo> getRlList(@Param("bo") GpsEquipmentSonBo bo);
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ 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.gps.domain.vo.GpsStatusVo;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
@ -78,4 +79,6 @@ public interface IGpsEquipmentSonService extends IService<GpsEquipmentSon>{
|
||||
List<GpsEquipmentSonVo> getLargerScreenList(GpsEquipmentSonBo bo);
|
||||
|
||||
List<GpsEquipmentSonVo> getUserListByProjectId(Long projectId, LocalDateTime startOfDay, LocalDateTime now);
|
||||
|
||||
List<GpsStatusVo> getRlList(GpsEquipmentSonBo bo);
|
||||
}
|
||||
|
||||
@ -272,14 +272,14 @@ public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, Gps
|
||||
JSONObject messageObj = new JSONObject();
|
||||
messageObj.put("type", "GPS_DATA_UPDATE"); // 消息类型
|
||||
messageObj.put("clientId", sonBo.getClientId()); // 设备唯一标识
|
||||
messageObj.put("projectId", sonBo.getProjectId()); // 项目ID
|
||||
messageObj.put("userId", sonBo.getUserId()); // 关联用户ID
|
||||
messageObj.put("projectId", sonBo.getProjectId().toString()); // 项目ID
|
||||
messageObj.put("userId", sonBo.getUserId().toString()); // 关联用户ID
|
||||
|
||||
// 位置信息
|
||||
JSONObject locationObj = new JSONObject();
|
||||
locationObj.put("latitude", sonBo.getLocLatitude()); // 纬度
|
||||
locationObj.put("longitude", sonBo.getLocLongitude()); // 经度
|
||||
locationObj.put("altitude", sonBo.getLocAltitude()); // 海拔
|
||||
locationObj.put("latitude", sonBo.getLocLatitude().toString()); // 纬度
|
||||
locationObj.put("longitude", sonBo.getLocLongitude().toString()); // 经度
|
||||
locationObj.put("altitude", sonBo.getLocAltitude().toString()); // 海拔
|
||||
messageObj.put("location", locationObj);
|
||||
|
||||
// 转换为String类型返回
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package org.dromara.gps.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
@ -11,6 +12,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.contractor.domain.SubConstructionUser;
|
||||
import org.dromara.contractor.service.ISubConstructionUserService;
|
||||
import org.dromara.gps.domain.vo.GpsStatusVo;
|
||||
import org.dromara.system.domain.vo.SysOssVo;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.dromara.system.service.ISysDictDataService;
|
||||
@ -100,6 +102,7 @@ public class GpsEquipmentSonServiceImpl extends ServiceImpl<GpsEquipmentSonMappe
|
||||
lqw.eq(bo.getProjectId() != null, GpsEquipmentSon::getProjectId, bo.getProjectId());
|
||||
lqw.eq(bo.getUserId() != null, GpsEquipmentSon::getUserId, bo.getUserId());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getClientId()), GpsEquipmentSon::getClientId, bo.getClientId());
|
||||
lqw.between(bo.getStartTime() != null && bo.getEndTime() != null, GpsEquipmentSon::getCreateTime, bo.getStartTime(), bo.getEndTime());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@ -194,4 +197,18 @@ public class GpsEquipmentSonServiceImpl extends ServiceImpl<GpsEquipmentSonMappe
|
||||
public List<GpsEquipmentSonVo> getUserListByProjectId(Long projectId, LocalDateTime startOfDay, LocalDateTime now) {
|
||||
return baseMapper.getUserListByProjectId(projectId,startOfDay,now);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GpsStatusVo> getRlList(GpsEquipmentSonBo bo) {
|
||||
if (bo.getProjectId() == null) {
|
||||
throw new ServiceException("项目id不能为空!");
|
||||
}
|
||||
if (bo.getClientId() == null) {
|
||||
throw new ServiceException("设备id不能为空!");
|
||||
}
|
||||
if (bo.getStartTime() == null || bo.getEndTime() == null) {
|
||||
throw new ServiceException("开始时间和结算时间不能为空!!!");
|
||||
}
|
||||
return baseMapper.getRlList(bo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.manager.ys7manager.Ys7Manager;
|
||||
import org.dromara.manager.ys7manager.vo.Ys7QueryDeviceResponseVo;
|
||||
import org.dromara.other.service.IOthYs7DeviceService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -17,7 +18,8 @@ import java.util.List;
|
||||
* @date 2025/6/17 9:33
|
||||
*/
|
||||
@Slf4j
|
||||
//@Component
|
||||
@Component
|
||||
@ConditionalOnProperty(prefix = "ys7.job", name = "device-sync-enabled", havingValue = "true")
|
||||
public class IncSyncYs7DeviceData {
|
||||
|
||||
@Resource
|
||||
|
||||
@ -19,9 +19,7 @@ import org.dromara.system.service.ISysRoleService;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@ -59,6 +57,7 @@ public class DesignFileJob {
|
||||
.eq(DesSmsRecord::getAgain, "1")
|
||||
.le(DesSmsRecord::getCreateTime, threeDaysAgo) // Date类型直接比较
|
||||
);
|
||||
HashSet<String> phoneNumbers = new HashSet<>();
|
||||
for (DesSmsRecord record : records) {
|
||||
DesVolumeFile desVolumeFile = designFileService.getById(record.getVolumeFileId());
|
||||
DesVolumeCatalog desVolumeCatalog = volumeCatalogService.getById(desVolumeFile.getVolumeCatalogId());
|
||||
@ -85,10 +84,13 @@ public class DesignFileJob {
|
||||
List<Long> list1 = list.stream().map(DesVolumeFileViewer::getUserId).toList();
|
||||
//找出没有查看的人 发送短信
|
||||
List<SysUser> list2 = sysUsers.stream().filter(vo -> !list1.contains(vo.getUserId())).toList();
|
||||
asyncUtil.sendSms(list2.stream().map(SysUser::getPhonenumber).toList(), "config5");
|
||||
phoneNumbers.addAll(list2.stream().map(SysUser::getPhonenumber).toList());
|
||||
|
||||
}
|
||||
|
||||
if(CollectionUtil.isEmpty(phoneNumbers)){
|
||||
return;
|
||||
}
|
||||
asyncUtil.sendSms(new ArrayList<>(phoneNumbers), "config5");
|
||||
List<Long> list1 = records.stream().map(DesSmsRecord::getId).toList();
|
||||
|
||||
desSmsRecordService.lambdaUpdate().in(DesSmsRecord::getId, list1)
|
||||
|
||||
@ -51,32 +51,40 @@ public class InspectionJob {
|
||||
|
||||
SmsBlend smsBlend = SmsFactory.getSmsBlend("config4");
|
||||
|
||||
List<String> phones = new ArrayList<>();
|
||||
List<Long> userIds = new ArrayList<>();
|
||||
// 每500条记录作为一批进行处理
|
||||
int batchSize = 500;
|
||||
for (int i = 0; i < list.size(); i += batchSize) {
|
||||
int endIndex = Math.min(i + batchSize, list.size());
|
||||
List<QltQualityInspection> batch = list.subList(i, endIndex);
|
||||
List<Long> userIds = new ArrayList<>();
|
||||
|
||||
for (QltQualityInspection qualityInspection : batch) {
|
||||
Long correctorId = qualityInspection.getCorrectorId();
|
||||
String phonenumber = userService.queryById(correctorId).getPhonenumber();
|
||||
if (phonenumber == null) {
|
||||
continue;
|
||||
}
|
||||
if(phones.contains(phonenumber)){
|
||||
continue;
|
||||
}
|
||||
phones.add(phonenumber);
|
||||
SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, new LinkedHashMap<String, String>());
|
||||
if (!smsResponse.isSuccess()) {
|
||||
log.error("验证码短信发送异常 => {}", smsResponse);
|
||||
}
|
||||
if(!userIds.contains(correctorId)){
|
||||
userIds.add(correctorId);
|
||||
}
|
||||
if(userIds.isEmpty()){
|
||||
continue;
|
||||
|
||||
}
|
||||
log.info("质量工单短信提醒批次发送完成,当前批次数量: {}", batch.size());
|
||||
}
|
||||
if(!userIds.isEmpty()){
|
||||
SseMessageDto sseMessageDto = new SseMessageDto();
|
||||
sseMessageDto.setMessage("您负责整改的质量工单已逾期,请尽快前往处理!");
|
||||
sseMessageDto.setUserIds(userIds);
|
||||
SseMessageUtils.publishMessage(sseMessageDto);
|
||||
log.info("质量工单短信提醒批次发送完成,当前批次数量: {}", batch.size());
|
||||
}
|
||||
|
||||
log.info("执行定时任务:质量工单短信提醒完成,总处理数量: {}", list.size());
|
||||
@ -93,34 +101,38 @@ public class InspectionJob {
|
||||
|
||||
SmsBlend smsBlend = SmsFactory.getSmsBlend("config6");
|
||||
|
||||
List<String> phones = new ArrayList<>();
|
||||
List<Long> userIds = new ArrayList<>();
|
||||
// 每500条记录作为一批进行处理
|
||||
int batchSize = 500;
|
||||
for (int i = 0; i < list.size(); i += batchSize) {
|
||||
int endIndex = Math.min(i + batchSize, list.size());
|
||||
List<HseSafetyInspection> batch = list.subList(i, endIndex);
|
||||
|
||||
List<Long> userIds = new ArrayList<>();
|
||||
for (HseSafetyInspection safetyInspection : batch) {
|
||||
Long correctorId = safetyInspection.getCorrectorId();
|
||||
String phonenumber = userService.queryById(correctorId).getPhonenumber();
|
||||
if (phonenumber == null) {
|
||||
continue;
|
||||
}
|
||||
if(phones.contains(phonenumber)){
|
||||
continue;
|
||||
}
|
||||
phones.add(phonenumber);
|
||||
SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, new LinkedHashMap<String, String>());
|
||||
if (!smsResponse.isSuccess()) {
|
||||
log.error("验证码短信发送异常 => {}", smsResponse);
|
||||
}
|
||||
userIds.add(correctorId);
|
||||
}
|
||||
|
||||
log.info("安全工单短信提醒批次发送完成,当前批次数量: {}", batch.size());
|
||||
}
|
||||
if(!userIds.isEmpty()){
|
||||
SseMessageDto sseMessageDto = new SseMessageDto();
|
||||
sseMessageDto.setMessage("您负责整改的安全工单已逾期,请尽快前往处理!");
|
||||
sseMessageDto.setUserIds(userIds);
|
||||
SseMessageUtils.publishMessage(sseMessageDto);
|
||||
|
||||
log.info("安全工单短信提醒批次发送完成,当前批次数量: {}", batch.size());
|
||||
}
|
||||
|
||||
log.info("执行定时任务:安全工单短信提醒完成,总处理数量: {}", list.size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,4 +94,14 @@ public class MatMaterialsInventory extends BaseEntity {
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 操作人id
|
||||
*/
|
||||
private Long operatorId;
|
||||
|
||||
/**
|
||||
* 分包单位id
|
||||
*/
|
||||
private Long recipientId;
|
||||
|
||||
}
|
||||
|
||||
@ -355,7 +355,7 @@ public class MatMaterialsInventoryServiceImpl extends ServiceImpl<MatMaterialsIn
|
||||
lqw.eq(ObjectUtils.isNotEmpty(number), MatMaterialsInventory::getNumber, number);
|
||||
lqw.eq(ObjectUtils.isNotEmpty(outPut), MatMaterialsInventory::getOutPut, outPut);
|
||||
// 排序
|
||||
lqw.orderByDesc(MatMaterialsInventory::getCreateTime);
|
||||
lqw.orderByAsc(MatMaterialsInventory::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package org.dromara.materials.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
@ -330,6 +331,8 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
|
||||
lqw.eq(ObjectUtils.isNotEmpty(status), MatMaterials::getStatus, status);
|
||||
lqw.eq(ObjectUtils.isNotEmpty(projectId), MatMaterials::getProjectId, projectId);
|
||||
lqw.eq(ObjectUtils.isNotEmpty(companyId), MatMaterials::getCompanyId, companyId);
|
||||
|
||||
lqw.orderByDesc(MatMaterials::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@ -367,6 +370,9 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
|
||||
@Override
|
||||
public void create(Long projectId, List<MatMaterialReceiveItemDto> itemList, String formCode, String supplierUnit, String nickname) {
|
||||
for (MatMaterialReceiveItemDto item : itemList) {
|
||||
if(item.getAcceptedQuantity().compareTo(BigDecimal.ZERO) <= 0){
|
||||
continue;
|
||||
}
|
||||
MatMaterials matMaterials = new MatMaterials();
|
||||
matMaterials.setMaterialsName(item.getName());
|
||||
matMaterials.setProjectId(projectId);
|
||||
@ -484,7 +490,10 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
|
||||
if (receive != null) {
|
||||
BeanUtils.copyProperties(receive, vo);
|
||||
}
|
||||
List<MatMaterialsNumberVo> numberVos = validMaterials.stream().map(m -> {
|
||||
|
||||
List<MatMaterialsNumberVo> numberVos = new ArrayList<>();
|
||||
|
||||
for (MatMaterials m : validMaterials) {
|
||||
MatMaterialsNumberVo numberVo = new MatMaterialsNumberVo();
|
||||
BeanUtils.copyProperties(m, numberVo);
|
||||
MatMaterialsInventory inv = inventoryMap.get(m.getId());
|
||||
@ -499,8 +508,10 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
|
||||
return outVo;
|
||||
}).toList());
|
||||
}
|
||||
return numberVo;
|
||||
}).toList();
|
||||
if(CollectionUtil.isNotEmpty(numberVo.getOutList())){
|
||||
numberVos.add(numberVo);
|
||||
}
|
||||
}
|
||||
vo.setMaterials(numberVos);
|
||||
resultList.add(vo);
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ public class DeviceMessageSender {
|
||||
* @param face 人脸模板地址(HTTP链接)
|
||||
* @return 异常信息(无异常则返回null)
|
||||
*/
|
||||
public static Exception sendPersonnelInformation(String sn, String userId, String name, String face) {
|
||||
public Boolean sendPersonnelInformation(String sn, String userId, String name, String face) {
|
||||
try {
|
||||
// 生成UUID
|
||||
String sUuid = DeviceWebSocketServer.generateUUIDWithSixRandomDigits();
|
||||
@ -45,10 +45,10 @@ public class DeviceMessageSender {
|
||||
|
||||
// 发送请求并等待响应(忽略响应结果,只关注是否成功)
|
||||
DeviceWebSocketServer.sendRequestAndWaitResponse(sn, sUuid, people);
|
||||
return null;
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error("下发人员信息失败,SN: {}, UserID: {}", sn, userId, e);
|
||||
return e;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ public class DeviceMessageSender {
|
||||
* @return 响应结果(包含人员信息)
|
||||
* @throws Exception 发送或接收过程中的异常
|
||||
*/
|
||||
public static KqjEntity.CommonResponse getAllUsers(String sn) throws Exception {
|
||||
public KqjEntity.CommonResponse getAllUsers(String sn) throws Exception {
|
||||
// 生成UUID
|
||||
String sUuid = DeviceWebSocketServer.generateUUIDWithSixRandomDigits();
|
||||
|
||||
@ -87,7 +87,7 @@ public class DeviceMessageSender {
|
||||
* @return 响应结果
|
||||
* @throws Exception 发送或接收过程中的异常
|
||||
*/
|
||||
public static KqjEntity.CommonResponse deleteUser(String sn, String userId) throws Exception {
|
||||
public KqjEntity.CommonResponse deleteUser(String sn, String userId) throws Exception {
|
||||
// 生成UUID
|
||||
String sUuid = DeviceWebSocketServer.generateUUIDWithSixRandomDigits();
|
||||
|
||||
@ -116,7 +116,7 @@ public class DeviceMessageSender {
|
||||
* @return 响应结果
|
||||
* @throws Exception 发送或接收过程中的异常
|
||||
*/
|
||||
public static KqjEntity.CommonResponse batchDeleteUsers(String sn, String[] userIds) throws Exception {
|
||||
public KqjEntity.CommonResponse batchDeleteUsers(String sn, String[] userIds) throws Exception {
|
||||
// 生成UUID
|
||||
String sUuid = DeviceWebSocketServer.generateUUIDWithSixRandomDigits();
|
||||
|
||||
@ -144,7 +144,7 @@ public class DeviceMessageSender {
|
||||
* @return 响应结果
|
||||
* @throws Exception 发送或接收过程中的异常
|
||||
*/
|
||||
public static KqjEntity.CommonResponse deleteAllUsers(String sn) throws Exception {
|
||||
public KqjEntity.CommonResponse deleteAllUsers(String sn) throws Exception {
|
||||
// 生成UUID
|
||||
String sUuid = DeviceWebSocketServer.generateUUIDWithSixRandomDigits();
|
||||
|
||||
|
||||
@ -1,153 +1,165 @@
|
||||
package org.dromara.mobileAttendanceMachine;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.websocket.*;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.project.service.IBusAttendanceMachineService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.websocket.*;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.http.WebSocket;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* WebSocket服务端实现(对应Golang的HandleWebSocket逻辑)
|
||||
* ServerEndpoint注解指定WebSocket连接路径
|
||||
* WebSocket服务端(设备连接管理、消息处理)
|
||||
* 核心逻辑:通过状态标记区分设备注册阶段和正常通信阶段,避免多处理器冲突
|
||||
*/
|
||||
@ServerEndpoint("/ws/device")
|
||||
@ServerEndpoint("/custom-ws/device")
|
||||
@Component
|
||||
@Log4j2
|
||||
public class DeviceWebSocketServer {
|
||||
|
||||
// ------------------------------ 常量定义(对应Golang的const) ------------------------------
|
||||
public static class Constants {
|
||||
public static final String DECLARE = "declare"; // 设备初上线
|
||||
public static final String PING = "ping"; // 心跳
|
||||
public static final String TO_CLIENT = "to_client"; // 服务器消息下发到客户端的响应
|
||||
}
|
||||
private final static IBusAttendanceMachineService attendanceMachineService = SpringUtils.getBean(IBusAttendanceMachineService.class);
|
||||
|
||||
// JSON序列化/反序列化工具(单例)
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
// ------------------------------ 常量定义 ------------------------------
|
||||
public static final String DECLARE = "declare"; // 设备注册消息
|
||||
public static final String PING = "ping"; // 心跳消息
|
||||
public static final String TO_CLIENT = "to_client"; // 设备响应消息
|
||||
private static final int REGISTER_TIMEOUT = 10; // 注册超时时间(秒)
|
||||
|
||||
// 1. 存储所有连接的设备信息(key: 设备SN,value: 设备信息)
|
||||
// ------------------------------ 全局静态存储 ------------------------------
|
||||
// JSON序列化工具(单例)
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
// 设备连接池:key=设备SN,value=设备信息(含Session)
|
||||
private static final Map<String, KqjEntity.DeviceInfo> connectedDevices = new ConcurrentHashMap<>();
|
||||
// 2. 存储UUID对应的响应通道(key: UUID,value: 响应结果容器)
|
||||
private static final Map<String, ResponseHolder<KqjEntity.CommonResponse>> responseChannels = new ConcurrentHashMap<>();
|
||||
// 响应通道:key=UUID,value=响应结果容器
|
||||
private static final Map<String, ResponseHolder> responseChannels = new ConcurrentHashMap<>();
|
||||
// 设备-SN反向映射:key=设备SN,value=关联的UUID列表(用于连接关闭时清理)
|
||||
private static final Map<String, Set<String>> snToUuids = new ConcurrentHashMap<>();
|
||||
|
||||
// 当前连接的WebSocket会话
|
||||
private Session session;
|
||||
// 当前连接的设备SN(连接建立后从DECLARE消息中提取)
|
||||
private String currentDeviceSn;
|
||||
// ------------------------------ 每个连接的实例变量 ------------------------------
|
||||
private Session session; // 当前WebSocket会话
|
||||
private String currentDeviceSn; // 当前连接的设备SN(注册后赋值)
|
||||
private volatile boolean isRegistered; // 注册状态:false=未注册,true=已注册
|
||||
private CompletableFuture<Boolean> registerFuture; // 注册阶段的消息Future
|
||||
|
||||
// ------------------------------ 连接生命周期方法 ------------------------------
|
||||
|
||||
/**
|
||||
* 连接建立时触发(对应Golang中upgrader.Upgrade后的初始化逻辑)
|
||||
* 连接建立时触发(初始化状态)
|
||||
*/
|
||||
@OnOpen
|
||||
public void onOpen(Session session) {
|
||||
this.session = session;
|
||||
log.info("新的WebSocket连接建立,会话ID: {}", session.getId());
|
||||
this.isRegistered = false;
|
||||
this.registerFuture = new CompletableFuture<>(); // 初始化注册Future
|
||||
|
||||
log.info("新连接建立,会话ID: {},等待设备注册({}秒超时)...", session.getId(), REGISTER_TIMEOUT);
|
||||
|
||||
// 启动注册超时监听
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
// 等待注册消息,超时则关闭连接
|
||||
if (!registerFuture.get(REGISTER_TIMEOUT, TimeUnit.SECONDS)) {
|
||||
throw new TimeoutException("注册超时");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("设备注册超时/失败,会话ID: {}", session.getId(), e);
|
||||
try {
|
||||
if (session.isOpen()) {
|
||||
session.close(new CloseReason(CloseReason.CloseCodes.TRY_AGAIN_LATER, "注册超时(请发送DECLARE消息)"));
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
log.error("关闭超时连接失败", ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收消息时触发(所有消息统一处理,按状态区分)
|
||||
*/
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) {
|
||||
if (message == null || message.isEmpty()) {
|
||||
log.warn("会话ID: {} 收到空消息,忽略", session.getId());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 读取设备第一条消息(DECLARE消息),完成设备注册
|
||||
KqjEntity.DeclareMessage declareMsg = registerDevice();
|
||||
this.currentDeviceSn = declareMsg.getSn();
|
||||
log.info("设备注册成功,SN: {}, 设备信息: {}", currentDeviceSn, declareMsg);
|
||||
// 解析通用消息的CMD(所有消息必须包含CMD)
|
||||
KqjEntity.GenericMessage genericMsg = objectMapper.readValue(message, KqjEntity.GenericMessage.class);
|
||||
String cmd = genericMsg.getCmd();
|
||||
if (cmd == null) {
|
||||
log.warn("会话ID: {} 收到无CMD消息,关闭连接: {}", session.getId(), message);
|
||||
session.close(new CloseReason(CloseReason.CloseCodes.PROTOCOL_ERROR, "消息缺少cmd字段"));
|
||||
return;
|
||||
}
|
||||
|
||||
// 未注册状态:仅处理DECLARE注册消息
|
||||
if (!isRegistered) {
|
||||
handleRegisterStage(message, cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
// 已注册状态:处理正常业务消息
|
||||
handleNormalStage(message, cmd);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("设备注册失败,关闭连接", e);
|
||||
log.error("会话ID: {} 处理消息失败: {}", session.getId(), message, e);
|
||||
try {
|
||||
session.close(new CloseReason(CloseReason.CloseCodes.PROTOCOL_ERROR, "设备注册失败"));
|
||||
if (session.isOpen()) {
|
||||
session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "消息处理异常"));
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
log.error("关闭异常连接失败", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 接收客户端消息时触发(对应Golang的for循环读取消息逻辑)
|
||||
*/
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) {
|
||||
if (message == null || message.isEmpty()) {
|
||||
log.warn("收到空消息,忽略处理");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 先解析通用消息的CMD字段(对应Golang的GenericMessage)
|
||||
KqjEntity.GenericMessage genericMsg = objectMapper.readValue(message, KqjEntity.GenericMessage.class);
|
||||
String cmd = genericMsg.getCmd();
|
||||
if (cmd == null) {
|
||||
log.warn("收到无CMD字段的消息,忽略: {}", message);
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据CMD类型处理不同逻辑(对应Golang的switch case)
|
||||
switch (cmd) {
|
||||
case Constants.DECLARE:
|
||||
log.info("设备在线心跳(DECLARE),SN: {}", currentDeviceSn);
|
||||
break;
|
||||
|
||||
case Constants.PING:
|
||||
handlePing(message);
|
||||
break;
|
||||
|
||||
case Constants.TO_CLIENT:
|
||||
handleToClientResponse(message);
|
||||
break;
|
||||
|
||||
default:
|
||||
log.warn("收到未知CMD消息,类型: {}, 内容: {}", cmd, message);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("处理消息失败,消息内容: {}", message, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 连接关闭时触发(对应Golang的defer conn.Close()和资源清理逻辑)
|
||||
* 连接关闭时触发(清理资源)
|
||||
*/
|
||||
@OnClose
|
||||
public void onClose(Session session, CloseReason closeReason) {
|
||||
log.info("WebSocket连接关闭,会话ID: {}, 原因: {}", session.getId(), closeReason);
|
||||
log.info("连接关闭,会话ID: {},原因: {}", session.getId(), closeReason);
|
||||
|
||||
// 1. 移除设备连接信息
|
||||
if (currentDeviceSn != null) {
|
||||
// 1. 移除设备连接(若已注册)
|
||||
if (currentDeviceSn != null && connectedDevices.containsKey(currentDeviceSn)) {
|
||||
connectedDevices.remove(currentDeviceSn);
|
||||
// 更新设备状态为离线(对应Golang的service.BusAttendanceMachine().Change)
|
||||
log.info("设备离线,SN: {},会话ID: {}", currentDeviceSn, session.getId());
|
||||
|
||||
// 2. 更新设备状态为离线(业务服务调用)
|
||||
updateDeviceStatus(currentDeviceSn, "0");
|
||||
|
||||
// 3. 清理该设备关联的响应通道
|
||||
cleanDeviceResponseChannels(currentDeviceSn);
|
||||
}
|
||||
|
||||
// 2. 清理当前设备对应的响应通道(避免内存泄漏)
|
||||
responseChannels.entrySet().removeIf(entry -> {
|
||||
if (entry.getValue().getSn().equals(currentDeviceSn)) {
|
||||
entry.getValue().getResultFuture().completeExceptionally(
|
||||
new Exception("设备连接已关闭,响应通道清理")
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// 4. 重置实例变量
|
||||
this.session = null;
|
||||
this.currentDeviceSn = null;
|
||||
this.isRegistered = false;
|
||||
this.registerFuture = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 连接异常时触发
|
||||
*/
|
||||
@OnError
|
||||
public void onError(Session session, Throwable throwable) {
|
||||
log.error("WebSocket连接异常,会话ID: {}", session.getId(), throwable);
|
||||
// 异常时主动关闭连接
|
||||
log.error("连接异常,会话ID: {},异常信息: {}", session.getId(), throwable.getMessage(), throwable);
|
||||
try {
|
||||
if (session.isOpen()) {
|
||||
session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "连接异常"));
|
||||
@ -157,63 +169,174 @@ public class DeviceWebSocketServer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------ 核心业务方法 ------------------------------
|
||||
// ------------------------------ 消息处理核心逻辑 ------------------------------
|
||||
|
||||
/**
|
||||
* 设备注册(对应Golang的addDevice函数)
|
||||
* 读取DECLARE消息,解析设备信息并存储
|
||||
* 处理注册阶段消息(仅接受DECLARE)
|
||||
*/
|
||||
private KqjEntity.DeclareMessage registerDevice() throws Exception {
|
||||
// 阻塞读取第一条消息(DECLARE消息)
|
||||
String firstMessage = readFirstMessage();
|
||||
KqjEntity.DeclareMessage declareMsg = objectMapper.readValue(firstMessage, KqjEntity.DeclareMessage.class);
|
||||
|
||||
// 校验SN合法性
|
||||
String sn = declareMsg.getSn();
|
||||
if (sn == null || sn.isEmpty()) {
|
||||
throw new IllegalArgumentException("设备SN为空,注册失败");
|
||||
// private void handleRegisterStage(String message, String cmd) throws Exception {
|
||||
// // 非DECLARE消息直接拒绝
|
||||
// if (!DECLARE.equals(cmd)) {
|
||||
// log.warn("未注册设备发送非法消息,cmd: {},关闭连接", cmd);
|
||||
// session.close(new CloseReason(CloseReason.CloseCodes.PROTOCOL_ERROR, "请先发送注册消息(cmd=declare)"));
|
||||
// registerFuture.complete(false); // 标记注册失败
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 解析DECLARE消息并完成注册
|
||||
// KqjEntity.DeclareMessage declareMsg = objectMapper.readValue(message, KqjEntity.DeclareMessage.class);
|
||||
// String sn = declareMsg.getSn();
|
||||
// if (sn == null || sn.isEmpty()) {
|
||||
// log.warn("注册消息缺少SN,关闭连接");
|
||||
// session.close(new CloseReason(CloseReason.CloseCodes.PROTOCOL_ERROR, "注册消息缺少sn字段"));
|
||||
// registerFuture.complete(false);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 存储设备信息(IP、端口、Session)
|
||||
// InetSocketAddress remoteAddr = (InetSocketAddress) session.getUserProperties().get("jakarta.websocket.endpoint.remoteAddress");
|
||||
// String ip = remoteAddr.getAddress().getHostAddress();
|
||||
// String port = String.valueOf(remoteAddr.getPort());
|
||||
//
|
||||
// KqjEntity.DeviceInfo deviceInfo = new KqjEntity.DeviceInfo();
|
||||
// deviceInfo.setIp(ip);
|
||||
// deviceInfo.setPort(port);
|
||||
// deviceInfo.setConn(session); // 直接存储Jakarta Session,无类型转换
|
||||
// connectedDevices.put(sn, deviceInfo);
|
||||
//
|
||||
// // 初始化设备-SN反向映射
|
||||
// snToUuids.computeIfAbsent(sn, k -> ConcurrentHashMap.newKeySet());
|
||||
//
|
||||
// // 调用业务服务完成注册
|
||||
// registerDeviceToService(sn);
|
||||
//
|
||||
// // 注册成功:更新状态
|
||||
// this.currentDeviceSn = sn;
|
||||
// this.isRegistered = true;
|
||||
// registerFuture.complete(true); // 标记注册成功
|
||||
// log.info("设备注册成功,SN: {},IP: {}:{},会话ID: {}", sn, ip, port, session.getId());
|
||||
// }
|
||||
private void handleRegisterStage(String message, String cmd) throws Exception {
|
||||
// 非DECLARE消息直接拒绝
|
||||
if (!DECLARE.equals(cmd)) {
|
||||
log.warn("未注册设备发送非法消息,cmd: {},关闭连接", cmd);
|
||||
session.close(new CloseReason(CloseReason.CloseCodes.PROTOCOL_ERROR, "请先发送注册消息(cmd=declare)"));
|
||||
registerFuture.complete(false); // 标记注册失败
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析客户端IP和端口(对应Golang的parseRemoteAddr)
|
||||
InetSocketAddress remoteAddr = (InetSocketAddress) session.getUserProperties().get("javax.websocket.endpoint.remoteAddress");
|
||||
String ip = remoteAddr.getAddress().getHostAddress();
|
||||
String port = String.valueOf(remoteAddr.getPort());
|
||||
// 解析DECLARE消息并完成注册
|
||||
KqjEntity.DeclareMessage declareMsg;
|
||||
try {
|
||||
declareMsg = objectMapper.readValue(message, KqjEntity.DeclareMessage.class);
|
||||
} catch (Exception e) {
|
||||
log.error("解析DECLARE消息失败,原始消息: {}", message, e);
|
||||
session.close(new CloseReason(CloseReason.CloseCodes.PROTOCOL_ERROR, "DECLARE消息格式错误"));
|
||||
registerFuture.complete(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// 存储设备信息
|
||||
String sn = declareMsg.getSn();
|
||||
if (sn == null || sn.isEmpty()) {
|
||||
log.warn("注册消息缺少SN,关闭连接,消息内容: {}", message);
|
||||
session.close(new CloseReason(CloseReason.CloseCodes.PROTOCOL_ERROR, "注册消息缺少sn字段"));
|
||||
registerFuture.complete(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// 存储设备信息(IP、端口、Session)- 核心优化:兼容多容器,避免空指针
|
||||
String ip = "unknown";
|
||||
String port = "unknown";
|
||||
InetSocketAddress remoteAddr = null;
|
||||
|
||||
// 尝试多种容器可能的键(优先级:Jakarta标准 -> Undertow专用 -> Javax兼容)
|
||||
Object addrObj = session.getUserProperties().get("jakarta.websocket.endpoint.remoteAddress");
|
||||
if (addrObj == null) {
|
||||
addrObj = session.getUserProperties().get("io.undertow.websocket.remoteAddress"); // Undertow专用
|
||||
}
|
||||
if (addrObj == null) {
|
||||
addrObj = session.getUserProperties().get("javax.websocket.endpoint.remoteAddress"); // 兼容旧版
|
||||
}
|
||||
|
||||
// 校验并解析IP和端口
|
||||
if (addrObj instanceof InetSocketAddress) {
|
||||
remoteAddr = (InetSocketAddress) addrObj;
|
||||
// 防止getAddress()返回null(极端情况)
|
||||
if (remoteAddr.getAddress() != null) {
|
||||
ip = remoteAddr.getAddress().getHostAddress();
|
||||
}
|
||||
port = String.valueOf(remoteAddr.getPort());
|
||||
log.info("解析设备地址成功,会话ID: {},IP: {},端口: {}", session.getId(), ip, port);
|
||||
} else {
|
||||
// 地址获取失败时,使用默认值,不中断注册流程
|
||||
log.warn("无法解析设备地址,会话ID: {},addrObj类型: {}",
|
||||
session.getId(), addrObj == null ? "null" : addrObj.getClass().getName());
|
||||
log.warn("继续注册流程,使用默认地址(unknown)");
|
||||
}
|
||||
|
||||
// 创建设备信息(即使IP获取失败,也正常注册)
|
||||
KqjEntity.DeviceInfo deviceInfo = new KqjEntity.DeviceInfo();
|
||||
deviceInfo.setIp(ip);
|
||||
deviceInfo.setPort(port);
|
||||
|
||||
// ======================== 添加类型检查 ========================
|
||||
// 检查session是否能转换为WebSocket,避免强转失败
|
||||
if (!(session instanceof WebSocket)) {
|
||||
throw new IllegalStateException("WebSocket容器不支持Session转WebSocket,无法注册设备,SN: " + sn);
|
||||
}
|
||||
// 强转并赋值
|
||||
deviceInfo.setConn((WebSocket) session); // 用Session替换Golang的*websocket.Conn
|
||||
// ============================================================
|
||||
|
||||
|
||||
deviceInfo.setConn(session);
|
||||
connectedDevices.put(sn, deviceInfo);
|
||||
|
||||
// 调用业务服务注册设备(对应Golang的service.BusAttendanceMachine().Register)
|
||||
// 初始化设备-SN反向映射
|
||||
snToUuids.computeIfAbsent(sn, k -> ConcurrentHashMap.newKeySet());
|
||||
|
||||
// 调用业务服务完成注册
|
||||
registerDeviceToService(sn);
|
||||
|
||||
return declareMsg;
|
||||
// 注册成功:更新状态
|
||||
this.currentDeviceSn = sn;
|
||||
this.isRegistered = true;
|
||||
registerFuture.complete(true); // 标记注册成功
|
||||
log.info("设备注册成功,SN: {},IP: {}:{},会话ID: {}", sn, ip, port, session.getId());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理PING消息(对应Golang的handlePing函数)
|
||||
* 处理正常通信阶段消息(PING、TO_CLIENT等)
|
||||
*/
|
||||
private void handleNormalStage(String message, String cmd) throws Exception {
|
||||
switch (cmd) {
|
||||
case DECLARE:
|
||||
// 已注册设备发送DECLARE视为在线心跳
|
||||
log.info("设备在线心跳,SN: {},会话ID: {}", currentDeviceSn, session.getId());
|
||||
break;
|
||||
|
||||
case PING:
|
||||
// 处理心跳:回复PONG
|
||||
handlePing(message);
|
||||
break;
|
||||
|
||||
case TO_CLIENT:
|
||||
// 处理设备响应消息
|
||||
handleToClientResponse(message);
|
||||
break;
|
||||
|
||||
default:
|
||||
log.warn("收到未知消息类型,SN: {},cmd: {},内容: {}", currentDeviceSn, cmd, message);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------ 业务子逻辑 ------------------------------
|
||||
|
||||
/**
|
||||
* 处理PING心跳消息(回复PONG)
|
||||
*/
|
||||
private void handlePing(String message) throws Exception {
|
||||
// 解析PING消息中的SN(双重校验)
|
||||
KqjEntity.DeclareMessage pingMsg = objectMapper.readValue(message, KqjEntity.DeclareMessage.class);
|
||||
String sn = pingMsg.getSn();
|
||||
if (!currentDeviceSn.equals(sn)) {
|
||||
log.warn("心跳消息SN不匹配,当前SN: {},消息SN: {}", currentDeviceSn, sn);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 回复PONG消息
|
||||
// 构造PONG响应
|
||||
KqjEntity.PongMessage pongMsg = new KqjEntity.PongMessage();
|
||||
pongMsg.setCmd(Constants.PING);
|
||||
pongMsg.setCmd("pong");
|
||||
pongMsg.setFrom("server");
|
||||
pongMsg.setTo(sn);
|
||||
|
||||
@ -223,247 +346,197 @@ public class DeviceWebSocketServer {
|
||||
|
||||
// 发送PONG消息
|
||||
session.getBasicRemote().sendText(objectMapper.writeValueAsString(pongMsg));
|
||||
log.info("发送PONG消息给设备,SN: {}", sn);
|
||||
log.info("发送PONG消息,SN: {},会话ID: {}", sn, session.getId());
|
||||
|
||||
// 2. 更新设备连接状态(对应Golang的connectedDevices[sn]重设)
|
||||
if (connectedDevices.containsKey(sn)) {
|
||||
KqjEntity.DeviceInfo deviceInfo = connectedDevices.get(sn);
|
||||
deviceInfo.setConn((WebSocket) session);
|
||||
connectedDevices.put(sn, deviceInfo);
|
||||
}
|
||||
|
||||
// 3. 调用业务服务更新设备状态(对应Golang的service.BusAttendanceMachine().Register)
|
||||
// 更新设备连接状态(业务服务调用)
|
||||
registerDeviceToService(sn);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理TO_CLIENT响应消息(对应Golang的requestResponse函数)
|
||||
* 处理TO_CLIENT响应消息(分发到对应的UUID通道)
|
||||
*/
|
||||
private void handleToClientResponse(String message) throws Exception {
|
||||
log.info("收到TO_CLIENT响应消息: {}", message);
|
||||
KqjEntity.CommonResponse commonResp = objectMapper.readValue(message, KqjEntity.CommonResponse.class);
|
||||
|
||||
// 根据UUID查找响应通道,传递响应结果
|
||||
String uuid = commonResp.getTo();
|
||||
ResponseHolder<KqjEntity.CommonResponse> holder = responseChannels.get(uuid);
|
||||
if (uuid == null || uuid.isEmpty()) {
|
||||
log.warn("响应消息缺少UUID(to字段),SN: {},内容: {}", currentDeviceSn, message);
|
||||
return;
|
||||
}
|
||||
|
||||
// 查找响应通道并分发结果
|
||||
ResponseHolder holder = responseChannels.get(uuid);
|
||||
if (holder != null) {
|
||||
holder.getResultFuture().complete(commonResp);
|
||||
responseChannels.remove(uuid); // 移除已完成的通道
|
||||
log.info("响应已分发到UUID: {}, 响应内容: {}", uuid, commonResp);
|
||||
responseChannels.remove(uuid);
|
||||
snToUuids.get(currentDeviceSn).remove(uuid); // 清理反向映射
|
||||
log.info("响应分发成功,UUID: {},SN: {}", uuid, currentDeviceSn);
|
||||
} else {
|
||||
log.warn("未找到UUID: {}对应的响应通道,响应丢弃", uuid);
|
||||
log.warn("未找到UUID对应的响应通道,UUID: {},SN: {}", uuid, currentDeviceSn);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------ 业务服务调用(需替换为真实实现) ------------------------------
|
||||
|
||||
/**
|
||||
* 设备注册到业务服务(对应原Golang的service.BusAttendanceMachine().Register)
|
||||
*/
|
||||
private void registerDeviceToService(String sn) {
|
||||
try {
|
||||
// TODO: 替换为真实的业务服务调用(如Spring Bean注入后调用)
|
||||
log.info("【业务服务】设备注册,SN: {}", sn);
|
||||
// 示例:BusAttendanceMachineService.register(sn);
|
||||
if (attendanceMachineService != null) {
|
||||
attendanceMachineService.insertBySn(sn);
|
||||
} else {
|
||||
log.error("IBusAttendanceMachineService 为空,无法进行设备注册");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("【业务服务】设备注册失败,SN: {}", sn, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新设备状态(对应原Golang的service.BusAttendanceMachine().Change)
|
||||
*/
|
||||
private void updateDeviceStatus(String sn, String status) {
|
||||
try {
|
||||
// TODO: 替换为真实的业务服务调用
|
||||
log.info("【业务服务】更新设备状态,SN: {},状态: {}", sn, status);
|
||||
// 示例:BusAttendanceMachineService.changeStatus(sn, status);
|
||||
if (attendanceMachineService != null) {
|
||||
attendanceMachineService.changeStatus(sn, status);
|
||||
} else {
|
||||
log.error("IBusAttendanceMachineService 为空,无法更新设备状态");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("【业务服务】更新设备状态失败,SN: {}", sn, e);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------ 工具方法 ------------------------------
|
||||
|
||||
/**
|
||||
* 读取设备第一条消息(阻塞直到收到消息)
|
||||
*/
|
||||
private String readFirstMessage() throws Exception {
|
||||
// 使用CompletableFuture等待消息
|
||||
final java.util.concurrent.CompletableFuture<String> firstMsgFuture = new java.util.concurrent.CompletableFuture<>();
|
||||
// 使用AtomicReference包装临时处理器,解决未初始化问题
|
||||
final java.util.concurrent.atomic.AtomicReference<MessageHandler.Whole<String>> tempHandlerRef = new java.util.concurrent.atomic.AtomicReference<>();
|
||||
|
||||
// 定义临时消息处理器
|
||||
MessageHandler.Whole<String> tempHandler = msg -> {
|
||||
if (!firstMsgFuture.isDone()) {
|
||||
firstMsgFuture.complete(msg);
|
||||
// 从引用中获取处理器并移除
|
||||
session.removeMessageHandler(tempHandlerRef.get());
|
||||
}
|
||||
};
|
||||
// 将处理器存入引用
|
||||
tempHandlerRef.set(tempHandler);
|
||||
// 注册处理器
|
||||
session.addMessageHandler(tempHandler);
|
||||
|
||||
// 等待消息,超时10秒
|
||||
return firstMsgFuture.get(10, TimeUnit.SECONDS);
|
||||
// // 使用Java并发工具等待消息(模拟Golang的阻塞读取)
|
||||
// final java.util.concurrent.CompletableFuture<String> firstMsgFuture = new java.util.concurrent.CompletableFuture<>();
|
||||
//
|
||||
// // 临时注册消息处理器,读取第一条消息后移除
|
||||
// MessageHandler.Whole<String> tempHandler = msg -> {
|
||||
// if (!firstMsgFuture.isDone()) {
|
||||
// firstMsgFuture.complete(msg);
|
||||
// // 移除临时处理器(避免重复处理)
|
||||
// session.removeMessageHandler(tempHandler);
|
||||
// }
|
||||
// };
|
||||
// session.addMessageHandler(tempHandler);
|
||||
//
|
||||
// // 等待消息,超时10秒(防止设备一直不发消息)
|
||||
// return firstMsgFuture.get(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送消息给指定设备(对应Golang的sendMessageToDevice函数)
|
||||
* 发送消息给指定设备(对应原Golang的sendMessageToDevice)
|
||||
*/
|
||||
public static boolean sendMessageToDevice(String sn, String uuid, Object message) {
|
||||
// 1. 检查设备是否在线
|
||||
KqjEntity.DeviceInfo deviceInfo = connectedDevices.get(sn);
|
||||
if (deviceInfo == null) {
|
||||
log.warn("设备不存在,SN: {}", sn);
|
||||
log.warn("发送消息失败:设备不存在,SN: {}", sn);
|
||||
responseChannels.remove(uuid);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 将WebSocket转回Session(因为状态由Session管理)
|
||||
WebSocket webSocket = deviceInfo.getConn();
|
||||
if (!(webSocket instanceof Session)) {
|
||||
log.warn("设备连接类型错误,无法判断状态,SN: {}", sn);
|
||||
responseChannels.remove(uuid);
|
||||
return false;
|
||||
}
|
||||
Session session = (Session) webSocket;
|
||||
|
||||
// 3. 检查连接是否打开
|
||||
if (!session.isOpen()) {
|
||||
log.warn("设备连接已关闭,SN: {}", sn);
|
||||
connectedDevices.remove(sn); // 移除已关闭的设备
|
||||
// 2. 检查Session是否有效
|
||||
Session session = deviceInfo.getConn();
|
||||
if (session == null || !session.isOpen()) {
|
||||
log.warn("发送消息失败:设备连接已关闭,SN: {}", sn);
|
||||
connectedDevices.remove(sn);
|
||||
snToUuids.remove(sn);
|
||||
responseChannels.remove(uuid);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 4. 序列化消息并发送
|
||||
// 3. 序列化并发送消息
|
||||
String msgJson = objectMapper.writeValueAsString(message);
|
||||
session.getBasicRemote().sendText(msgJson); // 通过Session发送消息
|
||||
log.info("发送消息给设备,SN: {}, UUID: {}, 消息: {}", sn, uuid, msgJson);
|
||||
session.getBasicRemote().sendText(msgJson);
|
||||
// 关联UUID和设备SN(用于后续清理)
|
||||
snToUuids.get(sn).add(uuid);
|
||||
log.info("发送消息成功,SN: {},UUID: {},消息: {}", sn, uuid, msgJson);
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("发送消息失败,SN: {}, UUID: {}", sn, uuid, e);
|
||||
// 发送失败时移除设备(可能连接已异常)
|
||||
log.error("发送消息失败,SN: {},UUID: {}", sn, uuid, e);
|
||||
// 清理无效资源
|
||||
connectedDevices.remove(sn);
|
||||
snToUuids.remove(sn);
|
||||
responseChannels.remove(uuid);
|
||||
return false;
|
||||
}
|
||||
// // 1. 检查设备是否在线
|
||||
// KqjEntity.DeviceInfo deviceInfo = connectedDevices.get(sn);
|
||||
// if (deviceInfo == null || !deviceInfo.getSession().isOpen()) {
|
||||
// log.warn("设备不在线,SN: {}", sn);
|
||||
// // 清理无效的响应通道
|
||||
// responseChannels.remove(uuid);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// // 2. 序列化消息并发送
|
||||
// String msgJson = objectMapper.writeValueAsString(message);
|
||||
// deviceInfo.getSession().getBasicRemote().sendText(msgJson);
|
||||
// log.info("发送消息给设备,SN: {}, UUID: {}, 消息: {}", sn, uuid, msgJson);
|
||||
// return true;
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// log.error("发送消息失败,SN: {}, UUID: {}", sn, uuid, e);
|
||||
// // 清理异常的响应通道
|
||||
// responseChannels.remove(uuid);
|
||||
// return false;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送请求并等待响应(对应Golang的SendRequestAndWaitResponse函数)
|
||||
* 发送请求并等待响应(对应原Golang的SendRequestAndWaitResponse)
|
||||
*/
|
||||
public static KqjEntity.CommonResponse sendRequestAndWaitResponse(String sn, String uuid, Object payload) throws Exception {
|
||||
// 1. 创建响应结果容器
|
||||
ResponseHolder<KqjEntity.CommonResponse> responseHolder = new ResponseHolder<>(sn);
|
||||
responseChannels.put(uuid, responseHolder);
|
||||
// 1. 创建响应容器并注册
|
||||
ResponseHolder holder = new ResponseHolder(sn);
|
||||
responseChannels.put(uuid, holder);
|
||||
|
||||
try {
|
||||
// 2. 发送请求
|
||||
boolean sendSuccess = sendMessageToDevice(sn, uuid, payload);
|
||||
if (!sendSuccess) {
|
||||
throw new Exception("发送请求失败,设备不在线或发送异常,SN: " + sn);
|
||||
log.error("发送请求失败,设备不在线或连接异常,SN: {}", sn);
|
||||
throw new ServiceException("发送请求失败,设备不在线或连接异常,SN: " + sn);
|
||||
}
|
||||
|
||||
// 3. 等待响应,超时10秒
|
||||
return responseHolder.getResultFuture().get(10, TimeUnit.SECONDS);
|
||||
|
||||
} catch (java.util.concurrent.TimeoutException e) {
|
||||
log.error("等待响应超时,SN: {}, UUID: {}", sn, uuid);
|
||||
// 3. 等待响应(10秒超时)
|
||||
return holder.getResultFuture().get(10, TimeUnit.SECONDS);
|
||||
} catch (TimeoutException e) {
|
||||
log.error("等待响应超时,SN: {},UUID: {}", sn, uuid);
|
||||
responseChannels.remove(uuid);
|
||||
throw new Exception("等待响应超时(10秒)", e);
|
||||
|
||||
snToUuids.get(sn).remove(uuid);
|
||||
log.error("等待响应超时(10秒),SN: {}", sn, e);
|
||||
throw new Exception("等待响应超时(10秒),SN: " + sn, e);
|
||||
} finally {
|
||||
// 清理响应通道(防止内存泄漏)
|
||||
// 4. 清理响应通道(防止内存泄漏)
|
||||
responseChannels.remove(uuid);
|
||||
if (snToUuids.containsKey(sn)) {
|
||||
snToUuids.get(sn).remove(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成带6位随机数的UUID(对应Golang的GenerateUUIDWithSixRandomDigits函数)
|
||||
* 生成带6位随机数的UUID(对应原Golang的GenerateUUIDWithSixRandomDigits)
|
||||
*/
|
||||
public static String generateUUIDWithSixRandomDigits() {
|
||||
// 生成标准UUID
|
||||
String uuidStr = UUID.randomUUID().toString().replace("-", "");
|
||||
// 生成6位随机数(100000-999999)
|
||||
Random random = new Random();
|
||||
int randomNum = random.nextInt(900000) + 100000;
|
||||
// 拼接返回
|
||||
int randomNum = random.nextInt(900000) + 100000; // 6位随机数(100000-999999)
|
||||
return uuidStr + "-" + randomNum;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------ 业务服务调用(模拟Golang的service层) ------------------------------
|
||||
|
||||
/**
|
||||
* 注册设备到业务服务(对应Golang的service.BusAttendanceMachine().Register)
|
||||
* 实际项目中替换为真实的Service调用
|
||||
* 清理设备关联的所有响应通道(连接关闭时调用)
|
||||
*/
|
||||
private void registerDeviceToService(String sn) {
|
||||
try {
|
||||
// 模拟业务服务调用(如更新数据库设备状态为在线)
|
||||
log.info("调用业务服务注册设备,SN: {}", sn);
|
||||
// TODO: 替换为真实的Service代码(如Spring Bean调用)
|
||||
} catch (Exception e) {
|
||||
log.error("业务服务注册设备失败,SN: {}", sn, e);
|
||||
}
|
||||
private void cleanDeviceResponseChannels(String sn) {
|
||||
Set<String> uuids = snToUuids.remove(sn);
|
||||
if (uuids == null || uuids.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新设备状态(对应Golang的service.BusAttendanceMachine().Change)
|
||||
* 实际项目中替换为真实的Service调用
|
||||
*/
|
||||
private void updateDeviceStatus(String sn, String status) {
|
||||
try {
|
||||
log.info("调用业务服务更新设备状态,SN: {}, 状态: {}", sn, status);
|
||||
// TODO: 替换为真实的Service代码(如Spring Bean调用)
|
||||
} catch (Exception e) {
|
||||
log.error("业务服务更新设备状态失败,SN: {}", sn, e);
|
||||
for (String uuid : uuids) {
|
||||
ResponseHolder holder = responseChannels.remove(uuid);
|
||||
if (holder != null) {
|
||||
holder.getResultFuture().completeExceptionally(
|
||||
new Exception("设备已离线,响应通道已清理,SN: " + sn)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("清理设备响应通道,SN: {},共清理UUID数量: {}", sn, uuids.size());
|
||||
}
|
||||
|
||||
// ------------------------------ 内部辅助类 ------------------------------
|
||||
|
||||
/**
|
||||
* 响应结果容器(对应Golang的chan CommonResponse)
|
||||
* 用CompletableFuture实现异步结果等待
|
||||
* 响应结果容器(替代Golang的chan,用CompletableFuture实现异步等待)
|
||||
*/
|
||||
private static class ResponseHolder<T> {
|
||||
private static class ResponseHolder {
|
||||
private final String sn; // 关联的设备SN
|
||||
private final java.util.concurrent.CompletableFuture<T> resultFuture;
|
||||
private final CompletableFuture<KqjEntity.CommonResponse> resultFuture;
|
||||
|
||||
public ResponseHolder(String sn) {
|
||||
this.sn = sn;
|
||||
this.resultFuture = new java.util.concurrent.CompletableFuture<>();
|
||||
this.resultFuture = new CompletableFuture<>();
|
||||
}
|
||||
|
||||
public String getSn() {
|
||||
return sn;
|
||||
}
|
||||
|
||||
public java.util.concurrent.CompletableFuture<T> getResultFuture() {
|
||||
public CompletableFuture<KqjEntity.CommonResponse> getResultFuture() {
|
||||
return resultFuture;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
package org.dromara.mobileAttendanceMachine;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import jakarta.websocket.Session;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.net.http.WebSocket;
|
||||
|
||||
/**
|
||||
* @Author 铁憨憨
|
||||
* @Date 2025/10/14 14:47
|
||||
* @Version 1.0
|
||||
* 实体类:WebSocket消息结构和设备信息
|
||||
*/
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class KqjEntity {
|
||||
|
||||
/**
|
||||
* 设备连接信息(修正conn为Jakarta Session)
|
||||
*/
|
||||
@Data
|
||||
public static class DeviceInfo {
|
||||
@JsonProperty("ip")
|
||||
@ -25,14 +24,15 @@ public class KqjEntity {
|
||||
private String port;
|
||||
|
||||
@JsonProperty("conn")
|
||||
private WebSocket conn;
|
||||
private Session conn; // 关键修正:使用Jakarta WebSocket的Session
|
||||
}
|
||||
|
||||
// ------------------------------ 以下为原有实体类,保持不变 ------------------------------
|
||||
/**
|
||||
* 通用消息结构,用于解析初始的 cmd 字段
|
||||
*/
|
||||
@Data
|
||||
public class GenericMessage {
|
||||
public static class GenericMessage {
|
||||
@JsonProperty("cmd")
|
||||
private String cmd;
|
||||
}
|
||||
@ -41,7 +41,7 @@ public class KqjEntity {
|
||||
* 公共响应结构
|
||||
*/
|
||||
@Data
|
||||
public class CommonResponse {
|
||||
public static class CommonResponse {
|
||||
@JsonProperty("cmd")
|
||||
private String cmd;
|
||||
|
||||
@ -56,12 +56,12 @@ public class KqjEntity {
|
||||
}
|
||||
|
||||
@Data
|
||||
public class CommonResponseData {
|
||||
public static class CommonResponseData {
|
||||
@JsonProperty("cmd")
|
||||
private String cmd;
|
||||
|
||||
@JsonProperty("userIds")
|
||||
private String[] userIds; // 用户IDS
|
||||
private String[] userIds;
|
||||
|
||||
@JsonProperty("user_id")
|
||||
private String userId;
|
||||
@ -77,7 +77,7 @@ public class KqjEntity {
|
||||
}
|
||||
|
||||
@Data
|
||||
public class DelMultiUserData {
|
||||
public static class DelMultiUserData {
|
||||
@JsonProperty("user_id")
|
||||
private String userId;
|
||||
|
||||
@ -88,12 +88,11 @@ public class KqjEntity {
|
||||
private String msg;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设备上线消息
|
||||
*/
|
||||
@Data
|
||||
public class DeclareMessage {
|
||||
public static class DeclareMessage {
|
||||
@JsonProperty("cmd")
|
||||
private String cmd;
|
||||
|
||||
@ -134,7 +133,6 @@ public class KqjEntity {
|
||||
private PongMessageData data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 心跳回复消息结构
|
||||
*/
|
||||
@ -150,13 +148,13 @@ public class KqjEntity {
|
||||
@Data
|
||||
public class PeopleInformation {
|
||||
@JsonProperty("cmd")
|
||||
private String cmd; // 该接口固定为to_device
|
||||
private String cmd;
|
||||
|
||||
@JsonProperty("from")
|
||||
private String from; // 可不填写,填写uuid来做为发送请求或响应的标识
|
||||
private String from;
|
||||
|
||||
@JsonProperty("to")
|
||||
private String to; // 设备号(请查看公共设置中的设备号)
|
||||
private String to;
|
||||
|
||||
@JsonProperty("data")
|
||||
private PeopleInData data;
|
||||
@ -174,10 +172,10 @@ public class KqjEntity {
|
||||
private String name;
|
||||
|
||||
@JsonProperty("face_template")
|
||||
private String faceTemplate; // http 链接图
|
||||
private String faceTemplate;
|
||||
|
||||
@JsonProperty("id_valid")
|
||||
private String idValid; // 人员有效期(人员在这个时间点后,无法通行)格式:yyyy-MM-dd 或者 yyyy-MM-dd HH:mm,为 "" 则为永久
|
||||
private String idValid;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -207,7 +205,7 @@ public class KqjEntity {
|
||||
private String userId;
|
||||
|
||||
@JsonProperty("user_type")
|
||||
private int userType; // 删除的用户类型:0-人脸接口下发的数据 1-人证比对接口下发的数据
|
||||
private int userType;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -237,7 +235,7 @@ public class KqjEntity {
|
||||
private String[] userIds;
|
||||
|
||||
@JsonProperty("user_type")
|
||||
private int userType; // 删除的用户类型:0-人脸接口下发的数据 1-人证比对接口下发的数据
|
||||
private int userType;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -264,7 +262,7 @@ public class KqjEntity {
|
||||
private String cmd;
|
||||
|
||||
@JsonProperty("user_type")
|
||||
private int userType; // 删除的用户类型:0-人脸接口下发的数据 1-人证比对接口下发的数据
|
||||
private int userType;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -273,13 +271,13 @@ public class KqjEntity {
|
||||
@Data
|
||||
public class PersonnelInformationAcquisition {
|
||||
@JsonProperty("cmd")
|
||||
private String cmd; // 该接口固定为to_device
|
||||
private String cmd;
|
||||
|
||||
@JsonProperty("from")
|
||||
private String from; // 可不填写,填写uuid来做为发送请求或响应的标识
|
||||
private String from;
|
||||
|
||||
@JsonProperty("to")
|
||||
private String to; // 设备号(请查看公共设置中的设备号)
|
||||
private String to;
|
||||
|
||||
@JsonProperty("data")
|
||||
private PersonnelInformationAcquisitionTwo data;
|
||||
@ -293,5 +291,4 @@ public class KqjEntity {
|
||||
@JsonProperty("value")
|
||||
private int value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,22 +1,13 @@
|
||||
package org.dromara.mobileAttendanceMachine;
|
||||
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
|
||||
/**
|
||||
* @Author 铁憨憨
|
||||
* @Date 2025/10/14 16:11
|
||||
* @Version 1.0
|
||||
*
|
||||
* 系统启动就会开启ws
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
public class WebSocketConfig {
|
||||
|
||||
/**
|
||||
* 自动注册所有标注了@ServerEndpoint的WebSocket端点
|
||||
*/
|
||||
@Bean
|
||||
public ServerEndpointExporter serverEndpointExporter() {
|
||||
return new ServerEndpointExporter();
|
||||
|
||||
@ -452,8 +452,10 @@ public class OutTableController extends BaseController {
|
||||
|
||||
BigDecimal monthCompletionValue = BigDecimal.ZERO;
|
||||
for (BusProcurement busProcurement : busProcurements1) {
|
||||
if(busProcurement.getAcceptedQuantity()!=null){
|
||||
monthCompletionValue = monthCompletionValue.add(busProcurement.getAcceptedQuantity().multiply(busProcurement.getUnitPrice()).setScale(4, RoundingMode.HALF_UP));
|
||||
}
|
||||
}
|
||||
vo.setMonthCompletionValue(monthCompletionValue);
|
||||
|
||||
}
|
||||
|
||||
@ -50,6 +50,11 @@ public class OutConstructionValue extends BaseEntity {
|
||||
*/
|
||||
private Long progressCategoryId;
|
||||
|
||||
/**
|
||||
* 分项工程名称
|
||||
*/
|
||||
private String progressCategoryName;
|
||||
|
||||
/**
|
||||
* 计划详情id
|
||||
*/
|
||||
|
||||
@ -25,4 +25,19 @@ public class OutConstructionAllValueVo implements Serializable {
|
||||
* 对甲产值
|
||||
*/
|
||||
private BigDecimal ownerValue;
|
||||
|
||||
/**
|
||||
* 人工填报数量
|
||||
*/
|
||||
private BigDecimal artificialNum;
|
||||
|
||||
/**
|
||||
* 无人机识别数量
|
||||
*/
|
||||
private BigDecimal uavNum;
|
||||
|
||||
/**
|
||||
* 确认数量
|
||||
*/
|
||||
private BigDecimal confirmNum;
|
||||
}
|
||||
|
||||
@ -171,4 +171,19 @@ public class OutConstructionValueVo implements Serializable {
|
||||
* 工作类型
|
||||
*/
|
||||
private String workType;
|
||||
|
||||
/**
|
||||
* 计量方式(0无 1数量 2百分比)
|
||||
*/
|
||||
private String unitType;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 完成数量
|
||||
*/
|
||||
private Integer completeNum;
|
||||
}
|
||||
|
||||
@ -110,7 +110,6 @@ public class OutConstructionValueServiceImpl extends ServiceImpl<OutConstruction
|
||||
private LambdaQueryWrapper<OutConstructionValue> buildQueryWrapper(OutConstructionValueBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<OutConstructionValue> lqw = Wrappers.lambdaQuery();
|
||||
lqw.orderByDesc(OutConstructionValue::getId);
|
||||
Long projectId = bo.getProjectId();
|
||||
List<Long> ids = new ArrayList<>();
|
||||
if (projectId != null) {
|
||||
@ -150,6 +149,9 @@ public class OutConstructionValueServiceImpl extends ServiceImpl<OutConstruction
|
||||
lqw.in(OutConstructionValue::getProgressCategoryId, categoryIds);
|
||||
}
|
||||
}
|
||||
lqw.orderByAsc(OutConstructionValue::getProgressCategoryName);
|
||||
lqw.orderByDesc(OutConstructionValue::getProgressCategoryId);
|
||||
lqw.orderByDesc(OutConstructionValue::getReportDate);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@ -275,6 +277,27 @@ public class OutConstructionValueServiceImpl extends ServiceImpl<OutConstruction
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add)
|
||||
.setScale(4, RoundingMode.HALF_UP);
|
||||
vo.setOwnerValue(ownerValue);
|
||||
// 统计确认数量
|
||||
BigDecimal confirmNum = list.stream()
|
||||
.map(OutConstructionValueVo::getConfirmNum)
|
||||
.filter(Objects::nonNull)
|
||||
.map(BigDecimal::valueOf) // 转换成 BigDecimal
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
vo.setConfirmNum(confirmNum);
|
||||
// 统计人工填报数量
|
||||
BigDecimal artificialNum = list.stream()
|
||||
.map(OutConstructionValueVo::getArtificialNum)
|
||||
.filter(Objects::nonNull)
|
||||
.map(BigDecimal::valueOf) // 转换成 BigDecimal
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
vo.setArtificialNum(artificialNum);
|
||||
// 统计无人机识别数量
|
||||
BigDecimal uavNum = list.stream()
|
||||
.map(OutConstructionValueVo::getUavNum)
|
||||
.filter(Objects::nonNull)
|
||||
.map(BigDecimal::valueOf) // 转换成 BigDecimal
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
vo.setUavNum(uavNum);
|
||||
return vo;
|
||||
}
|
||||
|
||||
@ -335,6 +358,8 @@ public class OutConstructionValueServiceImpl extends ServiceImpl<OutConstruction
|
||||
PgsProgressCategoryVo pgsProgressCategoryVo = pgsProgressCategoryService.queryById(vo.getProgressCategoryId());
|
||||
vo.setProgressCategoryName(pgsProgressCategoryVo.getName());
|
||||
vo.setWorkType(pgsProgressCategoryVo.getWorkType());
|
||||
vo.setUnitType(pgsProgressCategoryVo.getUnitType());
|
||||
vo.setUnit(pgsProgressCategoryVo.getUnit());
|
||||
PgsProgressCategoryVo pgsProgressCategoryVo1 = pgsProgressCategoryService.queryById(pgsProgressCategoryVo.getParentId());
|
||||
vo.setCategoryId(pgsProgressCategoryVo1.getId());
|
||||
vo.setCategoryName(pgsProgressCategoryVo1.getName());
|
||||
@ -346,10 +371,14 @@ public class OutConstructionValueServiceImpl extends ServiceImpl<OutConstruction
|
||||
if (vo.getMatrixId() != null && vo.getMatrixId() != 0) {
|
||||
FacMatrix facMatrix = facMatrixService.getById(vo.getMatrixId());
|
||||
vo.setMatrixName(facMatrix.getMatrixName());
|
||||
vo.setCategoryName(facMatrix.getMatrixName() + "/" + pgsProgressCategoryVo1.getName());
|
||||
}
|
||||
BusProjectVo busProjectVo1 = busProjectService.queryById(pgsProgressCategoryVo.getProjectId());
|
||||
vo.setSubProjectId(busProjectVo1.getId());
|
||||
vo.setSubProjectName(busProjectVo1.getProjectName());
|
||||
|
||||
// 统计完成数量
|
||||
vo.setCompleteNum(vo.getArtificialNum() + vo.getUavNum());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -79,6 +79,15 @@ public class PgsProgressCategoryController extends BaseController {
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据进度父级查询进度类别列表已完成产值
|
||||
*/
|
||||
@SaCheckPermission("progress:progressCategory:listByParent")
|
||||
@GetMapping("/getValueByParentId")
|
||||
public R<PgsProgressCategoryValueVo> getValueByParentId(PgsProgressCategoryQueryByParentReq req) {
|
||||
return R.ok(pgsProgressCategoryService.getValueByParentId(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据项目获取进度类别模版顶级目录列表
|
||||
*/
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
package org.dromara.progress.domain.vo.progresscategory;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025-10-16 11:41
|
||||
*/
|
||||
@Data
|
||||
public class PgsProgressCategoryValueVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -7985655623513612674L;
|
||||
|
||||
/**
|
||||
* 产值金额(业主)
|
||||
*/
|
||||
private BigDecimal ownerValue;
|
||||
|
||||
/**
|
||||
* 产值金额(分包)
|
||||
*/
|
||||
private BigDecimal constructionValue;
|
||||
}
|
||||
@ -155,7 +155,12 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
|
||||
*/
|
||||
List<Map<String, Object>> getMatrixIdAndNumber(Long projectId);
|
||||
|
||||
|
||||
/**
|
||||
* 转换进度类别vo为进度类别实体
|
||||
*
|
||||
* @param vo 进度类别vo
|
||||
* @return 进度类别实体
|
||||
*/
|
||||
PgsProgressCategory convertVoToEntity(PgsProgressCategoryVo vo);
|
||||
|
||||
/**
|
||||
@ -246,4 +251,12 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
|
||||
* @return 进度类别甘特图结构
|
||||
*/
|
||||
List<PgsProgressCategoryGanttSubProjectVo> getGanttStructureList(Long progressCategoryId);
|
||||
|
||||
/**
|
||||
* 获取进度类别产值
|
||||
*
|
||||
* @param req 查询条件
|
||||
* @return 进度类别产值
|
||||
*/
|
||||
PgsProgressCategoryValueVo getValueByParentId(PgsProgressCategoryQueryByParentReq req);
|
||||
}
|
||||
|
||||
@ -254,7 +254,7 @@ public class PgsConstructionSchedulePlanServiceImpl extends ServiceImpl<PgsConst
|
||||
}
|
||||
// 主 Sheet 设置表头
|
||||
Row sheetRow = mainSheet.createRow(0);
|
||||
String[] headers = {"编号(格式:1,1-1,1-1-1。用于进行父子结构关联)", "节点名称", "对应项目结构", "对应项目结构编码",
|
||||
String[] headers = {"编号(格式:1,1.1,1.1.1。用于进行父子结构关联)", "节点名称", "对应项目结构", "对应项目结构编码",
|
||||
"预计开始时间(输入格式:2025-09-06)", "预计结束时间", "实际开始时间", "实际结束时间", "状态", "状态编码", "备注"};
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
Cell cell = sheetRow.createCell(i);
|
||||
@ -302,7 +302,11 @@ public class PgsConstructionSchedulePlanServiceImpl extends ServiceImpl<PgsConst
|
||||
row = mainSheet.createRow(i);
|
||||
}
|
||||
Cell cell = row.createCell(0);
|
||||
cell.setCellStyle(editableStyle);
|
||||
CellStyle textStyle = workbook.createCellStyle();
|
||||
textStyle.setLocked(false);
|
||||
DataFormat format = workbook.createDataFormat();
|
||||
textStyle.setDataFormat(format.getFormat("@")); // "@" 表示文本格式
|
||||
cell.setCellStyle(textStyle);
|
||||
|
||||
Cell cell1 = row.createCell(1);
|
||||
cell1.setCellStyle(editableStyle);
|
||||
|
||||
@ -2126,6 +2126,60 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取进度类别产值
|
||||
*
|
||||
* @param req 查询条件
|
||||
* @return 进度类别产值
|
||||
*/
|
||||
@Override
|
||||
public PgsProgressCategoryValueVo getValueByParentId(PgsProgressCategoryQueryByParentReq req) {
|
||||
PgsProgressCategoryValueVo vo = new PgsProgressCategoryValueVo();
|
||||
vo.setOwnerValue(BigDecimal.ZERO);
|
||||
vo.setConstructionValue(BigDecimal.ZERO);
|
||||
// 根据查询条件获取数据
|
||||
Long parentId = req.getParentId();
|
||||
String name = req.getName();
|
||||
if (parentId == null) {
|
||||
return vo;
|
||||
}
|
||||
QueryWrapper<PgsProgressCategory> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.apply("FIND_IN_SET({0}, ancestors)", parentId);
|
||||
queryWrapper.like(StringUtils.isNotBlank(name), "name", name);
|
||||
List<PgsProgressCategory> progressCategoryList = this.list(queryWrapper);
|
||||
if (CollUtil.isEmpty(progressCategoryList)) {
|
||||
return vo;
|
||||
}
|
||||
// 过滤掉那些还有子节点的,只保留最底层
|
||||
Set<Long> parentIds = progressCategoryList.stream()
|
||||
.map(PgsProgressCategory::getParentId)
|
||||
.collect(Collectors.toSet());
|
||||
List<PgsProgressCategory> categoryList = progressCategoryList.stream()
|
||||
.filter(item -> !parentIds.contains(item.getId())) // 没有被当作别人父id的,就是叶子节点
|
||||
.toList();
|
||||
// 统计完成产值
|
||||
BigDecimal ownerValue = categoryList.stream().map(item -> {
|
||||
BigDecimal completed = item.getCompleted();
|
||||
BigDecimal ownerPrice = item.getOwnerPrice();
|
||||
if (item.getUnitType().equals(PgsProgressUnitTypeEnum.PERCENTAGE.getValue())) {
|
||||
completed = completed.multiply(item.getTotal()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
|
||||
}
|
||||
return completed.multiply(ownerPrice);
|
||||
}).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(4, RoundingMode.HALF_UP);
|
||||
vo.setOwnerValue(ownerValue);
|
||||
// 统计施工产值
|
||||
BigDecimal constructionValue = categoryList.stream().map(item -> {
|
||||
BigDecimal completed = item.getCompleted();
|
||||
BigDecimal constructionPrice = item.getConstructionPrice();
|
||||
if (item.getUnitType().equals(PgsProgressUnitTypeEnum.PERCENTAGE.getValue())) {
|
||||
completed = completed.multiply(item.getTotal()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
|
||||
}
|
||||
return completed.multiply(constructionPrice);
|
||||
}).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(4, RoundingMode.HALF_UP);
|
||||
vo.setConstructionValue(constructionValue);
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算进度类别(含子类别)的开始和结束时间。
|
||||
* <p>
|
||||
|
||||
@ -971,6 +971,7 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
|
||||
value.setRangeId(rangeId);
|
||||
value.setMatrixId(category.getMatrixId());
|
||||
value.setProgressCategoryId(progressCategoryId);
|
||||
value.setProgressCategoryName(category.getName());
|
||||
value.setDetailId(planDetail.getId());
|
||||
BigDecimal finishedNumber = planDetail.getFinishedNumber();
|
||||
BigDecimal aiFill = planDetail.getAiFill();
|
||||
@ -1049,6 +1050,7 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
|
||||
value.setRangeId(range.getId());
|
||||
value.setMatrixId(category.getMatrixId());
|
||||
value.setProgressCategoryId(progressCategoryId);
|
||||
value.setProgressCategoryName(category.getName());
|
||||
value.setDetailId(planDetail.getId());
|
||||
BigDecimal finishedNumber = planDetail.getFinishedNumber();
|
||||
BigDecimal aiFill = planDetail.getAiFill();
|
||||
|
||||
@ -0,0 +1,109 @@
|
||||
package org.dromara.project.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.project.domain.BusAttendanceMachine;
|
||||
import org.dromara.project.domain.dto.attendance.*;
|
||||
import org.dromara.project.domain.vo.attendance.DeviceResult;
|
||||
import org.dromara.project.service.IBusAttendanceMachineService;
|
||||
import org.dromara.project.service.IBusAttendanceService;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
|
||||
/**
|
||||
* 考勤
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2025-08-05
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping()
|
||||
@Slf4j
|
||||
public class BusAttendanceDeviceController extends BaseController {
|
||||
|
||||
private final IBusAttendanceService busAttendanceService;
|
||||
|
||||
private final IBusAttendanceMachineService busAttendanceMachineService;
|
||||
|
||||
@PostMapping("/api/v1/record/face")
|
||||
@SaIgnore
|
||||
public DeviceResult punchCardByFace(@RequestBody DeviceDto dto) {
|
||||
//打印接收数据
|
||||
log.info("接收数据:{}", dto);
|
||||
if (dto.getLogs().isEmpty()) {
|
||||
return new DeviceResult(500, "没有数据");
|
||||
}
|
||||
Log first = dto.getLogs().getFirst();
|
||||
|
||||
Long userId = Long.valueOf(first.getUser_id());
|
||||
|
||||
BusAttendanceMachine one = busAttendanceMachineService.lambdaQuery()
|
||||
.eq(BusAttendanceMachine::getSn, dto.getSn())
|
||||
.last("limit 1")
|
||||
.one();
|
||||
if (one == null || one.getProjectId() == null) {
|
||||
return new DeviceResult(500, "考勤机不存在或未关联项目");
|
||||
}
|
||||
|
||||
String recogTime = first.getRecog_time();
|
||||
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(recogTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
|
||||
BusAttendancePunchCardByFaceReq req = new BusAttendancePunchCardByFaceReq();
|
||||
DeviceLocation location = first.getLocation();
|
||||
req.setLat(location.getLatitude());
|
||||
req.setLng(location.getLongitude());
|
||||
req.setProjectId(one.getProjectId());
|
||||
req.setUserId(userId);
|
||||
req.setPunchTime(localDateTime);
|
||||
req.setSource("1");
|
||||
//打印req
|
||||
log.info("请求参数:{}", req);
|
||||
//base64转MultipartFile
|
||||
try {
|
||||
// 假设first.getImage()返回base64字符串,且你有一个文件名
|
||||
MultipartFile file = convert(first.getPhoto(), "face.jpg");
|
||||
log.info("开始打卡");
|
||||
busAttendanceService.punchCardByFace(file, req);
|
||||
return new DeviceResult(0, "打卡成功");
|
||||
} catch (IOException e) {
|
||||
return new DeviceResult(500, "文件转换失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static MultipartFile convert(String base64String, String fileName) throws IOException {
|
||||
// 先进行URL解码(如果是URL编码过的数据)
|
||||
try {
|
||||
base64String = java.net.URLDecoder.decode(base64String, "UTF-8");
|
||||
} catch (Exception e) {
|
||||
// 如果不是URL编码的数据,直接跳过
|
||||
}
|
||||
|
||||
// 去除base64前缀(如data:image/png;base64,)
|
||||
if (base64String.contains(",")) {
|
||||
base64String = base64String.split(",")[1];
|
||||
}
|
||||
|
||||
// 解码base64字符串
|
||||
byte[] decodedBytes = Base64.decodeBase64(base64String);
|
||||
|
||||
// 创建MultipartFile对象
|
||||
return new MockMultipartFile(fileName, fileName, "image/jpeg", decodedBytes);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
package org.dromara.project.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
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.web.core.BaseController;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineQueryReq;
|
||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineUpdateReq;
|
||||
import org.dromara.project.domain.vo.BusAttendanceMachineVo;
|
||||
import org.dromara.project.service.IBusAttendanceMachineService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 考勤机
|
||||
*
|
||||
* @author lilemy
|
||||
* @date 2025-10-15
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/project/attendanceMachine")
|
||||
public class BusAttendanceMachineController extends BaseController {
|
||||
|
||||
private final IBusAttendanceMachineService busAttendanceMachineService;
|
||||
|
||||
/**
|
||||
* 查询考勤机列表
|
||||
*/
|
||||
@SaCheckPermission("project:attendanceMachine:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<BusAttendanceMachineVo> list(BusAttendanceMachineQueryReq req, PageQuery pageQuery) {
|
||||
return busAttendanceMachineService.queryPageList(req, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出考勤机列表
|
||||
*/
|
||||
@SaCheckPermission("project:attendanceMachine:export")
|
||||
@Log(title = "考勤机", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(BusAttendanceMachineQueryReq req, HttpServletResponse response) {
|
||||
List<BusAttendanceMachineVo> list = busAttendanceMachineService.queryList(req);
|
||||
ExcelUtil.exportExcel(list, "考勤机", BusAttendanceMachineVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取考勤机详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("project:attendanceMachine:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<BusAttendanceMachineVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(busAttendanceMachineService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改考勤机
|
||||
*/
|
||||
@SaCheckPermission("project:attendanceMachine:edit")
|
||||
@Log(title = "考勤机", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated @RequestBody BusAttendanceMachineUpdateReq req) {
|
||||
return toAjax(busAttendanceMachineService.updateByBo(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除考勤机
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("project:attendanceMachine:remove")
|
||||
@Log(title = "考勤机", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(busAttendanceMachineService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user