销售订单接口

This commit is contained in:
2024-07-27 15:17:22 +08:00
parent 98ce5a2c5a
commit 466373c249
12 changed files with 746 additions and 1 deletions

View File

@@ -14,6 +14,10 @@ public class DictCode {
public static final String PURCHASEORDER_STATUS = "purchaseOrder.status";
public static final String SALEORDER_STATUS = "saleOrder.status";
public static final String PURCHASEORDER_GENRULE = "purchaseOrder.genRule";
public static final String NETDISK_ENTRYTYPE = "netDisk.entryType";
public static final String NOTEBOOK_CONTENTTYPE = "notebook.contentType";

View File

@@ -41,6 +41,35 @@ public class OrganizationConfigEntity extends OrgCommonEntity {
@Comment("销售订单号生成规则 0 手工填写 1 全局递增 2 年月日+递增 3 年月日时分秒 ")
private String saleOrderNoRule;
@Comment("销售订单号前缀")
private String saleOrderNoPrefix;
@Comment("销售订单号递增步长")
private Integer saleOrderNoStep;
@Comment("销售订单号递增起始值")
private Integer saleOrderNoStart;
@Comment("递增部分位数")
private Integer saleOrderNoAutoIncrLength;

View File

@@ -0,0 +1,66 @@
package cn.lihongjie.coal.saleOrder.controller;
import cn.lihongjie.coal.annotation.OrgScope;
import cn.lihongjie.coal.annotation.SysLog;
import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.saleOrder.dto.CreateSaleOrderDto;
import cn.lihongjie.coal.saleOrder.dto.SaleOrderDto;
import cn.lihongjie.coal.saleOrder.dto.UpdateSaleOrderDto;
import cn.lihongjie.coal.saleOrder.dto.UpdateWeightDataDto;
import cn.lihongjie.coal.saleOrder.service.SaleOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/saleOrder")
@SysLog(module = "采购订单")
@Slf4j
@OrgScope
public class SaleOrderController {
@Autowired private SaleOrderService service;
@PostMapping("/create")
public SaleOrderDto create(@RequestBody CreateSaleOrderDto request) {
return this.service.create(request);
}
@PostMapping("/nextsaleOrderNumber")
public String nextsaleOrderNumber(@RequestBody CreateSaleOrderDto request) {
return this.service.nextSaleOrderNumber(request);
}
@PostMapping("/update")
public SaleOrderDto update(@RequestBody UpdateSaleOrderDto request) {
return this.service.update(request);
}
@PostMapping("/updateWeightData")
public SaleOrderDto updateWeightData(@RequestBody UpdateWeightDataDto request) {
return this.service.updateWeightData(request);
}
@PostMapping("/delete")
public Object delete(@RequestBody IdRequest request) {
this.service.delete(request);
return true;
}
@PostMapping("/getById")
public SaleOrderDto getById(@RequestBody IdRequest request) {
return this.service.getById(request.getId());
}
@PostMapping("/list")
public Page<SaleOrderDto> list(@RequestBody CommonQuery request) {
return this.service.list(request);
}
}

View File

@@ -0,0 +1,72 @@
package cn.lihongjie.coal.saleOrder.dto;
import cn.lihongjie.coal.base.dto.OrgCommonDto;
import jakarta.persistence.ManyToOne;
import lombok.Data;
import org.hibernate.annotations.Comment;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class CreateSaleOrderDto extends OrgCommonDto {
@ManyToOne
@Comment("煤炭信息")
private String productInfo;
@ManyToOne
@Comment("客户信息")
private String supplier;
@Comment("采购数量")
private Double amount;
@Comment("采购单状态")
private String orderStatus;
@Comment("采购单价")
private Double price;
@Comment("是否含税")
private Boolean includeTax;
@Comment("税率")
private Double taxRate;
@Comment("其他费用")
private Double otherFee;
@Comment("销售日期")
private LocalDate saleDate;
@Comment("完成/作废时间")
private LocalDateTime finishTime;
@Comment("订单开始时间")
private LocalDateTime startTime;
@Comment("预计到货日期")
private LocalDate estimateDeliveryDate;
private LocalDate firstDeliveryDate;
private LocalDate lastDeliveryDate;
private List<String> weightDataList;
}

View File

@@ -0,0 +1,83 @@
package cn.lihongjie.coal.saleOrder.dto;
import cn.lihongjie.coal.base.dto.OrgCommonDto;
import cn.lihongjie.coal.common.DictCode;
import cn.lihongjie.coal.deliveryInformation.dto.DeliveryInformationDto;
import cn.lihongjie.coal.pojoProcessor.DictTranslate;
import cn.lihongjie.coal.product.dto.ProductDto;
import cn.lihongjie.coal.supplier.dto.SupplierDto;
import jakarta.persistence.ManyToOne;
import lombok.Data;
import org.hibernate.annotations.Comment;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class SaleOrderDto extends OrgCommonDto {
@Comment("销售日期")
private LocalDate saleDate;
private Double dayAmount;
@ManyToOne
@Comment("煤炭信息")
private ProductDto productInfo;
@ManyToOne
@Comment("客户信息")
private SupplierDto supplier;
private List<DeliveryInformationDto> deliveryInformationList;
@Comment("采购数量")
private Double amount;
@Comment("是否含税")
private Boolean includeTax;
@Comment("税率")
private Double taxRate;
@Comment("其他费用")
private Double otherFee;
private Double receivedAmount;
@Comment("收货进度 百分比")
private Double receivedPercentage;
private Double totalCarCount;
private Double leftAmount;
@Comment("第一次送货时间")
private LocalDateTime firstDeliveryTime;
@Comment("最后一次送货时间")
private LocalDateTime lastDeliveryTime;
@Comment("采购单价")
private Double price;
private Double total;
@Comment("采购单状态")
private String orderStatus;
@DictTranslate(dictKey = DictCode.SALEORDER_STATUS)
private String orderStatusName;
@Comment("完成/作废时间")
private LocalDateTime finishTime;
@Comment("订单开始时间")
private LocalDateTime startTime;
private List<String> weightDataList;
}

View File

@@ -0,0 +1,67 @@
package cn.lihongjie.coal.saleOrder.dto;
import cn.lihongjie.coal.base.dto.OrgCommonDto;
import jakarta.persistence.ManyToOne;
import lombok.Data;
import org.hibernate.annotations.Comment;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class UpdateSaleOrderDto extends OrgCommonDto {
@ManyToOne
@Comment("煤炭信息")
private String productInfo;
@ManyToOne
@Comment("客户信息")
private String supplier;
@Comment("采购数量")
private Double amount;
@Comment("采购单状态")
private String orderStatus;
@Comment("采购单价")
private Double price;
@Comment("是否含税")
private Boolean includeTax;
@Comment("税率")
private Double taxRate;
@Comment("其他费用")
private Double otherFee;
private LocalDate saleDate;
@Comment("预计到货日期")
private LocalDate estimateDeliveryDate;
@Comment("完成/作废时间")
private LocalDateTime finishTime;
@Comment("订单开始时间")
private LocalDateTime startTime;
private List<String> weightDataList;
}

View File

@@ -0,0 +1,17 @@
package cn.lihongjie.coal.saleOrder.dto;
import lombok.Data;
import org.hibernate.annotations.Comment;
import java.util.*;
@Data
public class UpdateWeightDataDto {
@Comment("操作类型 1 新增 2 全量覆盖 3 删除 ")
private String optType;
private String id;
private List<String> weightDataList;
}

View File

@@ -0,0 +1,114 @@
package cn.lihongjie.coal.saleOrder.entity;
import cn.lihongjie.coal.base.entity.OrgCommonEntity;
import cn.lihongjie.coal.product.entity.ProductEntity;
import cn.lihongjie.coal.supplier.entity.SupplierEntity;
import cn.lihongjie.coal.weightDeviceData.entity.WeightDeviceDataEntity;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import lombok.Data;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.Formula;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Data
@Entity
public class SaleOrderEntity extends OrgCommonEntity {
@Comment("销售日期")
private LocalDate saleDate;
@OneToMany
private List<WeightDeviceDataEntity> weightDataList;
//
// @ManyToOne
// @Comment("煤炭信息")
// private CoalInfoEntity coalInfo;
@ManyToOne
@Comment("产品信息")
private ProductEntity productInfo;
@ManyToOne
@Comment("客户信息")
private SupplierEntity supplier;
@Comment("采购数量")
private Double amount;
@Comment("是否含税")
private Boolean includeTax;
@Comment("税率")
private Double taxRate;
@Comment("采购单价")
private Double price;
@Comment("其他费用")
private Double otherFee;
@Formula("((amount * price) + coalesce(other_fee, 0))")
private Double total;
@Comment("采购单状态")
private String orderStatus;
@Comment("完成/作废时间")
private LocalDateTime finishTime;
@Comment("订单开始时间")
private LocalDateTime startTime;
@Formula("(round(EXTRACT(EPOCH FROM (coalesce(finish_time, now()) - start_time)) / 1000.0 / 60.0 / 24.0 ,2))")
private Double dayAmount;
@Override
public void prePersist() {
super.prePersist();
this.startTime = this.saleDate==null ? null: this.saleDate.atStartOfDay();
}
@Override
public void preUpdate() {
super.preUpdate();
this.startTime = this.saleDate==null ? null: this.saleDate.atStartOfDay();
}
}

View File

@@ -0,0 +1,21 @@
package cn.lihongjie.coal.saleOrder.mapper;
import cn.lihongjie.coal.base.mapper.BaseMapper;
import cn.lihongjie.coal.saleOrder.dto.CreateSaleOrderDto;
import cn.lihongjie.coal.saleOrder.dto.SaleOrderDto;
import cn.lihongjie.coal.saleOrder.dto.UpdateSaleOrderDto;
import cn.lihongjie.coal.saleOrder.entity.SaleOrderEntity;
import org.mapstruct.Mapper;
import org.mapstruct.control.DeepClone;
@Mapper(
componentModel = org.mapstruct.MappingConstants.ComponentModel.SPRING,
uses = {cn.lihongjie.coal.base.mapper.CommonMapper.class, cn.lihongjie.coal.base.mapper.CommonEntityMapper.class},
mappingControl = DeepClone.class)
public interface SaleOrderMapper
extends BaseMapper<
SaleOrderEntity,
SaleOrderDto,
CreateSaleOrderDto,
UpdateSaleOrderDto> {}

View File

@@ -0,0 +1,15 @@
package cn.lihongjie.coal.saleOrder.repository;
import cn.lihongjie.coal.base.dao.BaseRepository;
import cn.lihongjie.coal.saleOrder.entity.SaleOrderEntity;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
@Repository
public interface SaleOrderRepository extends BaseRepository<SaleOrderEntity> {
@Query("select (count(p) > 0) from SaleOrderEntity p where p.code = ?1 and p.organizationId = ?2")
boolean existsByCodeAndOrganizationId(String code, String organizationId);
}

View File

@@ -0,0 +1,236 @@
package cn.lihongjie.coal.saleOrder.service;
import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.base.mapper.CommonMapper;
import cn.lihongjie.coal.base.service.BaseService;
import cn.lihongjie.coal.common.Ctx;
import cn.lihongjie.coal.common.JpaUtils;
import cn.lihongjie.coal.organizationConfig.entity.OrganizationConfigEntity;
import cn.lihongjie.coal.organizationConfig.service.OrganizationConfigService;
import cn.lihongjie.coal.saleOrder.dto.CreateSaleOrderDto;
import cn.lihongjie.coal.saleOrder.dto.SaleOrderDto;
import cn.lihongjie.coal.saleOrder.dto.UpdateSaleOrderDto;
import cn.lihongjie.coal.saleOrder.dto.UpdateWeightDataDto;
import cn.lihongjie.coal.saleOrder.entity.SaleOrderEntity;
import cn.lihongjie.coal.saleOrder.mapper.SaleOrderMapper;
import cn.lihongjie.coal.saleOrder.repository.SaleOrderRepository;
import cn.lihongjie.coal.sequence.SequenceService;
import cn.lihongjie.coal.weightDeviceData.entity.WeightDeviceDataEntity;
import cn.lihongjie.coal.weightDeviceData.mapper.WeightDeviceDataMapper;
import cn.lihongjie.coal.weightDeviceData.repository.WeightDeviceDataRepository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Tuple;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Slf4j
@Transactional
public class SaleOrderService
extends BaseService<SaleOrderEntity, SaleOrderRepository> {
@Autowired SequenceService sequenceService;
@Autowired WeightDeviceDataRepository weightDeviceDataRepository;
@Autowired WeightDeviceDataMapper weightDeviceDataMapper;
@Autowired OrganizationConfigService organizationConfigService;
@Autowired private SaleOrderRepository repository;
@Autowired private SaleOrderMapper mapper;
@Autowired private ConversionService conversionService;
@PersistenceContext private EntityManager entityManager;
@Autowired private CommonMapper commonMapper;
public void delete(IdRequest request) {
this.repository.deleteAllById(request.getIds());
}
public SaleOrderDto getById(String id) {
SaleOrderEntity entity = repository.get(id);
return mapper.toDto(entity);
}
public SaleOrderDto create(CreateSaleOrderDto request) {
SaleOrderEntity entity = mapper.toEntity(request);
if (StringUtils.isNotEmpty(request.getCode())) {
if (repository.existsByCodeAndOrganizationId(
request.getCode(), Ctx.currentUser().getOrganizationId())) {
throw new RuntimeException("采购单号已存在");
}
}
this.repository.save(entity);
return getById(entity.getId());
}
public SaleOrderDto update(UpdateSaleOrderDto request) {
SaleOrderEntity entity = this.repository.get(request.getId());
if (StringUtils.isNotEmpty(request.getCode())) {
if (entityManager
.createQuery(
"select count(p) from SaleOrderEntity p where p.code = :code and p.id != :id and p.organizationId = :organizationId",
Long.class)
.setParameter("code", request.getCode())
.setParameter("organizationId", Ctx.currentUser().getOrganizationId())
.setParameter("id", request.getId())
.getSingleResult()
> 0L) {
throw new RuntimeException("采购单号已存在");
}
}
this.mapper.updateEntity(entity, request);
this.repository.save(entity);
return getById(entity.getId());
}
public SaleOrderDto updateWeightData(UpdateWeightDataDto request) {
SaleOrderEntity entity = this.repository.get(request.getId());
switch (request.getOptType()) {
case "0" -> {
if (CollectionUtils.isNotEmpty(entity.getWeightDataList())) {
Collection<String> toAdd =
CollectionUtils.removeAll(
request.getWeightDataList(),
entity.getWeightDataList().stream()
.map(x -> x.getId())
.collect(Collectors.toSet()));
entity.getWeightDataList()
.addAll(
toAdd.stream()
.map(
x ->
entityManager.getReference(
WeightDeviceDataEntity.class,
x))
.collect(Collectors.toList()));
} else {
request.setOptType("2");
updateWeightData(request);
}
}
case "1" -> {
entity.setWeightDataList(
request.getWeightDataList().stream()
.map(
x ->
entityManager.getReference(
WeightDeviceDataEntity.class, x))
.collect(Collectors.toList()));
}
case "2" -> {
entity.setWeightDataList(
entity.getWeightDataList().stream()
.filter(x -> !request.getWeightDataList().contains(x.getId()))
.collect(Collectors.toList()));
}
}
this.repository.save(entity);
return getById(entity.getId());
}
public Page<SaleOrderDto> list(CommonQuery query) {
Page<SaleOrderEntity> page =
repository.findAll(
query.specification(conversionService),
PageRequest.of(
query.getPageNo(),
query.getPageSize(),
Sort.by(query.getOrders())));
List<String> ids = page.stream().map(x -> x.getId()).toList();
List<Tuple> resultList =
entityManager
.createQuery(
"""
select round(coalesce(sum(w.sz), 0), 2) as receivedAmount, coalesce(count(w.id),0) as totalCarCount, round(coalesce(min(p.amount),0) - coalesce(sum(w.sz),0),2) as leftAmount, p.id as id, (coalesce(sum(w.sz),0) / sum(p.amount)) * 100.0 as receivedPercentage,
min(w.minTime) as firstDeliveryTime, max(w.minTime) as lastDeliveryTime
from SaleOrderEntity p
left join p.weightDataList w
where p.id in :ids
group by p.id
""",
Tuple.class)
.setParameter("ids", ids)
.getResultList();
Page<SaleOrderDto> ans = page.map(this.mapper::toDto);
JpaUtils.mergeMapToPojo(
ans.toList(), JpaUtils.convertTuplesToRawMap(resultList), conversionService);
return ans;
}
public String nextSaleOrderNumber(CreateSaleOrderDto dto) {
OrganizationConfigEntity currentOrgConfig = organizationConfigService.getCurrentOrgConfig();
switch (currentOrgConfig.getSaleOrderNoRule()) {
case "1" -> {
return sequenceService.genSeq(
"SaleOrderNo." + Ctx.currentUser().getOrganizationId(),
currentOrgConfig.getSaleOrderNoPrefix(),
currentOrgConfig.getSaleOrderNoAutoIncrLength(),
currentOrgConfig.getSaleOrderNoStart(),
currentOrgConfig.getSaleOrderNoStep());
}
case "2" -> {
return sequenceService.genSeq(
"SaleOrderNo."
+ Ctx.currentUser().getOrganizationId()
+ ObjectUtils.defaultIfNull(dto.getSaleDate(), LocalDate.now())
.format(DateTimeFormatter.ofPattern("yyyyMMdd")),
currentOrgConfig.getSaleOrderNoPrefix(),
currentOrgConfig.getSaleOrderNoAutoIncrLength(),
currentOrgConfig.getSaleOrderNoStart(),
currentOrgConfig.getSaleOrderNoStep());
}
case "3" -> {
return String.format(
"%s%s",
currentOrgConfig.getSaleOrderNoPrefix(),
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
}
default -> {
return "";
}
}
}
}

View File

@@ -1738,7 +1738,28 @@
}
]
},
{
"code": "saleOrder.status",
"name": "采购订单状态",
"item": [
{
"code": "0",
"name": "未开始"
},
{
"code": "1",
"name": "进行中"
},
{
"code": "2",
"name": "已完成"
},
{
"code": "3",
"name": "已取消"
}
]
},
{
"code": "purchaseOrder.genRule",
"name": "采购订单编号生成规则",