Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
hjx
2025-12-24 10:09:02 +08:00
20 changed files with 469 additions and 9 deletions
@@ -194,4 +194,7 @@ public class UserShipperEntity extends BaseVOEntity {
@ApiModelProperty(name = "客户nc编码")
private String customerNcCode;
@ApiModelProperty("结算币种")
private String settlementCurrency;
}
@@ -228,4 +228,7 @@ public class UserShipperDO extends UserDO {
@ApiModelProperty(name = "客户nc编码")
private String customerNcCode;
@ApiModelProperty("结算币种")
private String settlementCurrency;
}
@@ -194,4 +194,7 @@ public class UserShipperDTO extends UserDTO {
@ApiModelProperty("客户nc编码")
private String customerNcCode;
@ApiModelProperty("结算币种")
private String settlementCurrency;
}
@@ -96,7 +96,7 @@
FROM
user_shipper s
LEFT JOIN
"user" u
"USER" u
ON u.user_id = s.user_id
<where>
<if test="topOrganizationId != null "> and u.top_organization_id = #{topOrganizationId}</if>
@@ -117,7 +117,7 @@
FROM
user_shipper s
LEFT JOIN
"user" u
"USER" u
ON u.user_id = s.user_id and u.del_flag = 1
<where>
s.del_flag = 1 and s.shipper_fill = 3
@@ -411,7 +411,7 @@
a.user_account,
a.avatar
FROM
"user" a
"USER" a
WHERE
a.del_flag = 1
<include refid="common_where1"></include>
@@ -658,7 +658,7 @@
us.shipper_enterprise_name,
us.shipper_type
FROM
"user" u
"USER" u
LEFT JOIN user_shipper us ON u.user_id = us.user_id
WHERE
u.del_flag = 1
@@ -676,7 +676,7 @@
ude.driver_enterprise_name,
ude.driver_type
FROM
"user" u
"USER" u
LEFT JOIN user_driver_enterprise ude ON u.user_id = ude.user_id
WHERE
u.del_flag = 1
@@ -700,7 +700,7 @@
a.user_account,
a.avatar
FROM
"user" a
"USER" a
WHERE
a.del_flag = 1
and a.top_organization_id = #{topOrganizationId}
@@ -191,7 +191,7 @@
b.shipper_enterprise_fill,
a.business_type
FROM
"user" a
"USER" a
LEFT JOIN user_shipper b ON b.user_id = a.user_id
LEFT JOIN user_role ur ON b.user_id = ur.user_id
LEFT JOIN role r ON ur.role_id = r.role_id
@@ -1,5 +1,6 @@
package com.linke.finance.application.server.reconciliation;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.dingtalkworkflow_1_0.models.StartProcessInstanceResponse;
import com.linke.finance.domain.businessDocument.entity.BusinessDocument;
@@ -14,10 +15,13 @@ import com.linke.finance.domain.reconciliation.repository.todo.ReconciliationDO;
import com.linke.finance.domain.reconciliation.service.ReconciliationDomainService;
import com.linke.finance.domain.revenueExpensesRecord.entity.RevenueExpensesRecord;
import com.linke.finance.domain.revenueExpensesRecord.service.RevenueExpensesRecordDomainService;
import com.linke.finance.domain.tmsReceipt.entity.TmsReceipt;
import com.linke.finance.domain.tmsReceipt.repository.mapper.TmsReceiptMapper;
import com.linke.finance.domain.tmsReceipt.repository.po.TmsReceiptPO;
import com.linke.finance.domain.tmsReceipt.service.TmsReceiptDomainService;
import com.linke.finance.domain.verification.service.VerificationDomainService;
import com.linke.finance.infrastructure.feign.ProductServiceFeign;
import com.linke.finance.infrastructure.feign.WlhyServiceFeign;
import com.mhd.common.core.constant.SubjectConstants;
import com.mhd.common.core.domain.dto.ReconciliationDTO;
import com.mhd.common.core.domain.entity.Verification;
@@ -37,11 +41,13 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -65,6 +71,10 @@ public class ReconciliationApplicationService {
private TmsReceiptDomainService tmsReceiptDomainService;
@Autowired
private RevenueExpensesRecordDomainService revenueExpensesRecordDomainService;
@Autowired
private WlhyServiceFeign wlhyServiceFeign;
@Resource
private TmsReceiptMapper tmsReceiptMapper;
@@ -86,7 +96,21 @@ public class ReconciliationApplicationService {
reconciliationDO.setOrganizationId(userPo.getOrganizationId());
}
}
return reconciliationDomainService.queryList(reconciliationDO);
List<ReconciliationPO> reconciliationPOS = reconciliationDomainService.queryList(reconciliationDO);
for (ReconciliationPO reconciliationPO : reconciliationPOS) {
Long reconciliationId = reconciliationPO.getReconciliationId();
AjaxResult tmsOrderSettlementDetails = wlhyServiceFeign.getById(reconciliationId);
Map<String,Object> result = (Map<String,Object>)tmsOrderSettlementDetails.get("result");
if (ObjectUtil.isNotEmpty( result)){
Integer receiptIdstr = (Integer)result.get("receiptId");
Long receiptId = receiptIdstr.longValue();
TmsReceipt tmsReceipt = tmsReceiptMapper.selectById(receiptId);
if (tmsReceipt != null) {
reconciliationPO.setSettlementCurrency(tmsReceipt.getSettlementCurrency());
}
}
}
return reconciliationPOS;
}
/**
@@ -238,4 +238,8 @@ public class ReconciliationPO extends BaseVOEntity{
@ApiModelProperty(value = "nc唯一标识")
private String skNcId;
@ApiModelProperty("结算币种")
private String settlementCurrency;
}
@@ -115,4 +115,7 @@ public class TmsReceipt extends BaseVOEntity{
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private java.util.Date synchronousTime;
@ApiModelProperty("结算币种")
private String settlementCurrency;
}
@@ -107,4 +107,6 @@ public class TmsReceiptPO extends BaseVOEntity{
@ApiModelProperty("组织名称")
@Excel(name = "组织名称")
private String organizationName;
@ApiModelProperty("结算币种")
private String settlementCurrency;
}
@@ -132,4 +132,6 @@ public class TmsReceiptDO extends BaseVOEntity{
@ApiModelProperty("收款单号")
@Excel(name = "收款单号")
private String receivePaymentNumber;
@ApiModelProperty("结算币种")
private String settlementCurrency;
}
@@ -0,0 +1,19 @@
package com.linke.finance.infrastructure.feign;
import com.mhd.common.core.domain.dto.UserDriverDTO;
import com.mhd.common.core.web.domain.AjaxResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient("mhd-wlhy-service")
public interface WlhyServiceFeign {
/**
* @Description 绑定车辆
* @Author Alex
* @Date 2023/1/5 21:24
*/
@GetMapping("/ntocc/tmsOrder/getById")
public AjaxResult getById(@RequestParam(name="id",required=true) Long id);
}
@@ -127,4 +127,6 @@ public class TmsReceiptDTO extends BaseVOEntity{
@ApiModelProperty("挂账原因")
@Excel(name = "挂账原因")
private String creditReason;
@ApiModelProperty("结算币种")
private String settlementCurrency;
}
@@ -37,7 +37,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectTmsReceiptPo">
select id, top_organization_id,organization_id,organization_name,department_name,settlement_party_name,receive_payment_number, receive_payment_amount,
assignable_amount,assignment_status,credit_amount,credit_reason, receive_payment_time, serial_number,receive_voucher_url,
remark, account_name, account_information, create_by,create_by_name, create_time, update_by,update_by_name, update_time, del_flag from tms_receipt
remark, account_name, account_information, create_by,create_by_name, create_time, update_by,update_by_name, update_time, del_flag,SETTLEMENT_CURRENCY from tms_receipt
</sql>
<sql id="selectTmsReceiptPo1">
+5
View File
@@ -134,6 +134,11 @@
<artifactId>minio</artifactId>
<version>8.4.3</version>
</dependency>
<dependency>
<groupId>com.huaweicloud</groupId>
<artifactId>esdk-obs-java</artifactId>
<version>3.25.10</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
@@ -0,0 +1,33 @@
package com.linke.product.infrastructure.obs;
import com.mhd.common.core.web.domain.AjaxResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/api/file")
public class FileController {
@Autowired
private FileStorageService fileStorageService;
@PostMapping("/upload")
public AjaxResult<String> uploadFile(@RequestParam("file") MultipartFile file) {
String fileKey = fileStorageService.uploadFile(file);
String fileUrl = fileStorageService.getFileUrl(fileKey);
return AjaxResult.success(fileUrl);
}
@GetMapping("/url")
public AjaxResult<String> getFileUrl(@RequestParam String fileKey) {
String fileUrl = fileStorageService.getFileUrl(fileKey);
return AjaxResult.success(fileUrl);
}
@DeleteMapping
public AjaxResult<Boolean> deleteFile(@RequestParam String fileKey) {
boolean result = fileStorageService.deleteFile(fileKey);
return AjaxResult.success(result);
}
}
@@ -0,0 +1,35 @@
package com.linke.product.infrastructure.obs;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
public interface FileStorageService {
/**
* 文件上传
*/
String uploadFile(MultipartFile file);
/**
* 文件上传(指定路径)
*/
String uploadFile(String filePath, MultipartFile file);
/**
* 获取文件访问URL
*/
String getFileUrl(String fileKey);
/**
* 下载文件
*/
InputStream downloadFile(String fileKey);
/**
* 删除文件
*/
boolean deleteFile(String fileKey);
/**
* 判断文件是否存在
*/
boolean fileExists(String fileKey);
}
@@ -0,0 +1,134 @@
package com.linke.product.infrastructure.obs;
import com.mhd.common.core.utils.StringUtils;
import com.obs.services.ObsClient;
import com.obs.services.model.ObsObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.InputStream;
import java.util.UUID;
@Slf4j
@Service
public class HuaweiObsService implements FileStorageService {
@Autowired
private ObsClient obsClient;
@Autowired
private ObsProperties obsProperties;
private String bucketName;
@PostConstruct
public void init() {
this.bucketName = obsProperties.getBucketName();
}
@Override
public String uploadFile(MultipartFile file) {
String originalFilename = file.getOriginalFilename();
String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
String fileKey = UUID.randomUUID().toString() + fileExtension;
return uploadFile(fileKey, file);
}
@Override
public String uploadFile(String fileKey, MultipartFile file) {
try {
// 上传文件到OBS
obsClient.putObject(bucketName, fileKey, file.getInputStream());
log.info("文件上传成功: {}", fileKey);
return fileKey;
} catch (Exception e) {
log.error("文件上传失败: {}", fileKey, e);
throw new RuntimeException("文件上传失败", e);
}
}
@Override
public String getFileUrl(String fileKey) {
if (StringUtils.isNotBlank(obsProperties.getCdnDomain())) {
// 使用CDN域名
return "https://" + obsProperties.getCdnDomain() + "/" + fileKey;
} else {
// 生成临时访问URL(默认1小时有效期)
return "";
}
}
@Override
public InputStream downloadFile(String fileKey) {
try {
ObsObject obsObject = obsClient.getObject(bucketName, fileKey);
return obsObject.getObjectContent();
} catch (Exception e) {
log.error("文件下载失败: {}", fileKey, e);
throw new RuntimeException("文件下载失败", e);
}
}
@Override
public boolean deleteFile(String fileKey) {
try {
obsClient.deleteObject(bucketName, fileKey);
log.info("文件删除成功: {}", fileKey);
return true;
} catch (Exception e) {
log.error("文件删除失败: {}", fileKey, e);
return false;
}
}
@Override
public boolean fileExists(String fileKey) {
try {
return obsClient.doesObjectExist(bucketName, fileKey);
} catch (Exception e) {
log.error("检查文件存在失败: {}", fileKey, e);
return false;
}
}
/**
* 分片上传(大文件)
*/
/*public String multipartUpload(String fileKey, MultipartFile file) {
try {
// 初始化分片上传
String uploadId = obsClient.initiateMultipartUpload(bucketName, fileKey).getUploadId();
// 计算分片数量(每片5MB)
long partSize = 5 * 1024 * 1024L;
long fileSize = file.getSize();
int partCount = (int) (fileSize / partSize);
if (fileSize % partSize != 0) {
partCount++;
}
// 上传分片
for (int i = 0; i < partCount; i++) {
long startPos = i * partSize;
long curPartSize = (i + 1 == partCount) ? (fileSize - startPos) : partSize;
InputStream inputStream = file.getInputStream();
inputStream.skip(startPos);
obsClient.uploadPart(bucketName, fileKey, uploadId, i + 1, inputStream, curPartSize);
}
// 完成分片上传
obsClient.completeMultipartUpload(bucketName, fileKey, uploadId);
log.info("分片上传成功: {}", fileKey);
return fileKey;
} catch (Exception e) {
log.error("分片上传失败: {}", fileKey, e);
throw new RuntimeException("文件上传失败", e);
}
}*/
}
@@ -0,0 +1,128 @@
package com.linke.product.infrastructure.obs;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.BucketCors;
import com.obs.services.model.BucketCorsRule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Component
public class ObsBucketInitializer {
@Autowired
private ObsClient obsClient;
@Autowired
private ObsProperties obsProperties;
private static final String BUCKET_PREFIX = "diglog";
/**
* 应用启动时自动创建并配置桶
*/
//@PostConstruct
public void initBucket() {
// 根据环境生成桶名称,如:diglog-dev, diglog-test, diglog-prod
//String env = getEnvironment();
String bucketName = BUCKET_PREFIX;
try {
// 检查桶是否存在
boolean exists = obsClient.headBucket(bucketName);
if (!exists) {
// 创建桶
obsClient.createBucket(bucketName);
log.info("创建OBS桶成功: {}", bucketName);
// 配置桶的CORS(跨域资源共享)
configureBucketCors(bucketName);
// 配置生命周期规则(可选)
//configureLifecycle(bucketName);
// 配置访问日志(可选)
//configureAccessLog(bucketName);
} else {
log.info("OBS桶已存在: {}", bucketName);
}
// 更新配置中的桶名称
obsProperties.setBucketName(bucketName);
} catch (ObsException e) {
log.error("OBS桶操作失败: {}", e.getErrorMessage(), e);
throw new RuntimeException("OBS桶初始化失败", e);
}
}
/**
* 配置CORS规则
*/
private void configureBucketCors(String bucketName) {
BucketCors cors = new BucketCors();
List<BucketCorsRule> rules = new ArrayList<>();
BucketCorsRule rule = new BucketCorsRule();
rule.getAllowedHeader().add("*");
rule.getAllowedMethod().add("GET");
rule.getAllowedMethod().add("PUT");
rule.getAllowedMethod().add("POST");
rule.getAllowedMethod().add("DELETE");
rule.getAllowedMethod().add("HEAD");
rule.getAllowedOrigin().add("*");
rule.getExposeHeader().add("*");
rule.setMaxAgeSecond(3600);
rules.add(rule);
cors.setRules(rules);
obsClient.setBucketCors(bucketName, cors);
log.info("配置桶CORS规则: {}", bucketName);
}
/**
* 配置生命周期规则
*/
/*private void configureLifecycle(String bucketName) {
// 示例:30天后转为低频访问,365天后删除
String lifecycleConfig =
"<LifecycleConfiguration>" +
" <Rule>" +
" <ID>transition-and-expiration-rule</ID>" +
" <Prefix></Prefix>" +
" <Status>Enabled</Status>" +
" <Transition>" +
" <Days>30</Days>" +
" <StorageClass>WARM</StorageClass>" +
" </Transition>" +
" <Expiration>" +
" <Days>365</Days>" +
" </Expiration>" +
" </Rule>" +
"</LifecycleConfiguration>";
obsClient.setBucketLifecycle(bucketName, lifecycleConfig);
log.info("配置桶生命周期规则: {}", bucketName);
}*/
/**
* 获取当前环境
*/
/*private String getEnvironment() {
// 从配置文件或系统变量获取环境
String env = System.getProperty("spring.profiles.active",
System.getenv("SPRING_PROFILES_ACTIVE"));
if (env == null || env.isEmpty()) {
env = "dev"; // 默认开发环境
}
return env.toLowerCase();
}*/
}
@@ -0,0 +1,37 @@
package com.linke.product.infrastructure.obs;
import com.mhd.common.core.utils.StringUtils;
import com.obs.services.ObsClient;
import com.obs.services.ObsConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ObsConfig {
@Bean
public ObsClient obsClient(ObsProperties obsProperties) {
// 创建配置实例
ObsConfiguration config = new ObsConfiguration();
config.setSocketTimeout(obsProperties.getSocketTimeout());
config.setConnectionTimeout(obsProperties.getConnectionTimeout());
config.setEndPoint(obsProperties.getEndpoint());
// 创建ObsClient实例
if (StringUtils.isNotBlank(obsProperties.getSecurityToken())) {
// 使用临时安全令牌
return new ObsClient(
obsProperties.getAccessKey(),
obsProperties.getSecretKey(),
obsProperties.getSecurityToken(),
config
);
} else {
// 使用永久AK/SK
return new ObsClient(
obsProperties.getAccessKey(),
obsProperties.getSecretKey(),
config
);
}
}
}
@@ -0,0 +1,23 @@
package com.linke.product.infrastructure.obs;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "huawei.obs")
@Data
public class ObsProperties {
private String accessKey;
private String secretKey;
private String endpoint;
private String bucketName;
private String securityToken;
private String region;
private String cdnDomain;
private int maxConnections = 100;
private int socketTimeout = 30000;
private int connectionTimeout = 10000;
private int idleConnectionTime = 30000;
// getters and setters
}