fix(成本分析): 采购类型F和E50逻辑调整
This commit is contained in:
parent
42cfcb449a
commit
d8eecd5e53
|
|
@ -1,22 +1,17 @@
|
|||
package com.nflg.product.material.api.user.authority;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.mysql.cj.log.Log;
|
||||
import com.nflg.product.base.core.api.BaseApi;
|
||||
import com.nflg.product.material.mapper.master.AuthorityRolePowerMapper;
|
||||
import com.nflg.product.material.pojo.dto.AuthorityPowerDTO;
|
||||
import com.nflg.product.material.pojo.dto.SaveMemuPermissionDTO;
|
||||
import com.nflg.product.material.pojo.entity.AuthorityPowerEntity;
|
||||
import com.nflg.product.material.pojo.query.AuthorityPowerQuery;
|
||||
import com.nflg.product.material.pojo.vo.AuthorityMenuVO;
|
||||
import com.nflg.product.material.pojo.vo.AuthorityPowerVO;
|
||||
import com.nflg.product.material.service.AuthorityPowerService;
|
||||
import com.nflg.product.material.service.AuthorityRolePowerService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import nflg.product.common.constant.STATE;
|
||||
import nflg.product.common.vo.ResultVO;
|
||||
import org.omg.PortableInterceptor.LOCATION_FORWARD;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.nflg.product.material.pojo.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import org.omg.CORBA.PRIVATE_MEMBER;
|
||||
|
||||
/**
|
||||
* @decription
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import org.springframework.context.annotation.Configuration;
|
|||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
@Configuration
|
||||
|
|
@ -40,4 +41,21 @@ public class RedisTemplateConfig {
|
|||
return template;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisObjectTemplate(RedisConnectionFactory factory) {
|
||||
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(factory);
|
||||
|
||||
// 使用StringRedisSerializer来序列化和反序列化redis的key值
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.setHashKeySerializer(new StringRedisSerializer());
|
||||
|
||||
// 使用GenericJackson2JsonRedisSerializer来序列化和反序列化redis的value值
|
||||
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
|
||||
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
|
||||
|
||||
template.afterPropertiesSet();
|
||||
return template;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
package com.nflg.product.technology.mapper.master;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.nflg.product.technology.pojo.entity.MaterialMainAttrEntity;
|
||||
|
||||
public interface MaterialMainAttrMapper extends BaseMapper<MaterialMainAttrEntity> {
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package com.nflg.product.technology.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@ApiModel(value = "com-nflg-product-technology-pojo-main-entity-MaterialMainAttrEntity")
|
||||
@TableName(value = "t_material_main_attr")
|
||||
public class MaterialMainAttrEntity implements Serializable {
|
||||
|
||||
/**
|
||||
* 行ID 雪花
|
||||
*/
|
||||
@TableId(value = "row_id", type = IdType.ASSIGN_ID)
|
||||
@ApiModelProperty(value = "行ID 雪花")
|
||||
private Long rowId;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@TableField(value = "material_no")
|
||||
@ApiModelProperty(value = "物料编码")
|
||||
private String materialNo;
|
||||
|
||||
@TableField(value = "factory")
|
||||
@ApiModelProperty(value = "工厂")
|
||||
private String factory;
|
||||
|
||||
@TableField(value = "purchase_type")
|
||||
@ApiModelProperty(value = "采购类型")
|
||||
private String purchaseType;
|
||||
|
||||
@TableField(value = "special_purchase_type")
|
||||
@ApiModelProperty(value = "特殊采购类")
|
||||
private String specialPurchaseType;
|
||||
|
||||
@TableField(value = "plan_delivery_time")
|
||||
@ApiModelProperty(value = "计划交货时间(天数)")
|
||||
private Integer planDeliveryTime;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@TableField(value = "created_by", fill = FieldFill.INSERT)
|
||||
@ApiModelProperty(value = "创建人")
|
||||
private String createdBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(value = "created_time", fill = FieldFill.INSERT)
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private LocalDateTime createdTime;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
@TableField(value = "updated_by", fill = FieldFill.INSERT_UPDATE)
|
||||
@ApiModelProperty(value = "更新人")
|
||||
private String updatedBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
|
||||
@ApiModelProperty(value = "更新时间")
|
||||
private LocalDateTime updatedTime;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
|
|
@ -56,6 +56,9 @@ public class BomCostCalculateService {
|
|||
@Resource
|
||||
private ProcessRouteTaskProcessesService processRouteTaskProcessesService;
|
||||
|
||||
@Resource
|
||||
private MaterialMainAttrService materialMainAttrService;
|
||||
|
||||
/**
|
||||
* 缓存时长
|
||||
*/
|
||||
|
|
@ -80,17 +83,18 @@ public class BomCostCalculateService {
|
|||
config.setManday(manday);
|
||||
config.setVirtualWorkings(virtualWorkingService.listDTO());
|
||||
List<EBomCostCacheDTO> result = Collections.synchronizedList(new ArrayList<>(50));
|
||||
calculateBom(pDto, datas, config, result);
|
||||
calculateBom(true, pDto, datas, config, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private EBomCostCacheDTO calculateBom(EBomDTO dto, List<EBomDTO> datas, BomCostCalculateConfig config, List<EBomCostCacheDTO> result) {
|
||||
private EBomCostCacheDTO calculateBom(boolean isRoot, EBomDTO dto, List<EBomDTO> datas, BomCostCalculateConfig config, List<EBomCostCacheDTO> result) {
|
||||
String cdata = redisTemplate.opsForValue().get(buildKey(dto));
|
||||
List<EBomDTO> children = datas.stream()
|
||||
.filter(d -> StrUtil.equals(d.getParentMaterialNo(), dto.getMaterialNo()))
|
||||
.collect(Collectors.toList());
|
||||
if (StrUtil.isBlank(cdata)) {
|
||||
final List<WorkingHourDTO> workingHours = processRouteTaskProcessesService.getWorkingHour(dto.getMaterialNo());
|
||||
boolean purchaseTypeIsF = materialMainAttrService.purchaseTypeIsF(dto.getMaterialNo());
|
||||
boolean purchaseTypeIsE50 = materialMainAttrService.purchaseTypeIsE50(dto.getMaterialNo());
|
||||
if ((isRoot && purchaseTypeIsE50) || StrUtil.isBlank(cdata)) {
|
||||
List<WorkingHourDTO> workingHours = isRoot
|
||||
? processRouteTaskProcessesService.getWorkingHour(dto.getParentMaterialNo())
|
||||
: (purchaseTypeIsE50 ? new ArrayList<>() : processRouteTaskProcessesService.getWorkingHour(dto.getMaterialNo()));
|
||||
log.debug(StrUtil.format("BOM成本计算 {} 物料工时: {}", dto.getMaterialNo(), JsonUtil.toJson(workingHours)));
|
||||
EBomCostCacheDTO cdto = new EBomCostCacheDTO();
|
||||
cdto.setMaterialNo(dto.getMaterialNo());
|
||||
|
|
@ -105,54 +109,63 @@ public class BomCostCalculateService {
|
|||
cdto.setAuxiliaryDepartmentExpenses(calculateAuxiliaryDepartmentExpenses(dto, config, workingHours));
|
||||
cdto.setPaintCost(calculatePaintCost(dto));
|
||||
cdto.setProductionCosts(calculateProductionCosts(dto, config, workingHours));
|
||||
if (CollectionUtil.isEmpty(children)) {
|
||||
if (purchaseTypeIsF) {
|
||||
cdto.setHasChildren(false);
|
||||
// 计算自身
|
||||
cdto.setPurchasedParts(!BomConstant.STEELS_CATEGORY_CODE.contains(dto.getMaterialCategoryCode()));
|
||||
if (cdto.isPurchasedParts()) {
|
||||
// 外购件只计算采购成本
|
||||
cdto.setPurchasedPartsCost(calculatePurchasedPartsCost(dto));
|
||||
} else {
|
||||
// 非外购件计算材料成本和制作成本
|
||||
// 计算材料成本
|
||||
cdto.setSteelsCost(calculateSteelsCost(dto));
|
||||
// 计算损耗成本
|
||||
cdto.setWasteCost(calculateWasteCost(dto));
|
||||
}
|
||||
cdto.setPurchasedParts(true);
|
||||
cdto.setPurchasedPartsCost(calculatePurchasedPartsCost(dto));
|
||||
} else {
|
||||
cdto.setHasChildren(true);
|
||||
cdto.setPurchasedParts(false);
|
||||
//计算子级成本
|
||||
List<EBomCostCacheDTO> childrenCost = children.parallelStream()
|
||||
.map(c -> calculateBom(c, datas, config, result))
|
||||
List<EBomDTO> children = datas.stream()
|
||||
.filter(d -> StrUtil.equals(d.getParentMaterialNo(), dto.getMaterialNo()))
|
||||
.collect(Collectors.toList());
|
||||
for (EBomCostCacheDTO c : childrenCost) {
|
||||
EBomDTO dto1 = children.stream().filter(cc -> StrUtil.equals(cc.getMaterialNo(), c.getMaterialNo())).findFirst().orElse(null);
|
||||
cdto.setSteelsCost(cdto.getSteelsCost().add(c.getSteelsCost().multiply(dto1.getNum())));
|
||||
cdto.setSteelsCost(cdto.getSteelsCost().add(c.getWasteCost().multiply(dto1.getNum())));
|
||||
cdto.setPurchasedPartsCost(cdto.getPurchasedPartsCost().add(c.getPurchasedPartsCost().multiply(dto1.getNum())));
|
||||
cdto.setPieceRateSalary(cdto.getPieceRateSalary().add(c.getPieceRateSalary().multiply(dto1.getNum())));
|
||||
cdto.setWelfareExpenses(cdto.getWelfareExpenses().add(c.getWelfareExpenses().multiply(dto1.getNum())));
|
||||
cdto.setHydropowerCost(cdto.getHydropowerCost().add(c.getHydropowerCost().multiply(dto1.getNum())));
|
||||
cdto.setDepreciationCost(cdto.getDepreciationCost().add(c.getDepreciationCost().multiply(dto1.getNum())));
|
||||
cdto.setWorkshopManagementLaborCost(cdto.getWorkshopManagementLaborCost().add(c.getWorkshopManagementLaborCost().multiply(dto1.getNum())));
|
||||
cdto.setWorkshopOfficeExpenses(cdto.getWorkshopOfficeExpenses().add(c.getWorkshopOfficeExpenses().multiply(dto1.getNum())));
|
||||
cdto.setAuxiliaryDepartmentLaborCost(cdto.getAuxiliaryDepartmentLaborCost().add(c.getAuxiliaryDepartmentLaborCost().multiply(dto1.getNum())));
|
||||
cdto.setAuxiliaryDepartmentExpenses(cdto.getAuxiliaryDepartmentExpenses().add(c.getAuxiliaryDepartmentExpenses().multiply(dto1.getNum())));
|
||||
cdto.setPaintCost(cdto.getPaintCost().add(c.getPaintCost().multiply(dto1.getNum())));
|
||||
if (CollectionUtil.isNotEmpty(c.getProductionCosts())) {
|
||||
c.getProductionCosts().forEach(pc -> {
|
||||
ProductionCostDTO pdto = cdto.getProductionCosts().parallelStream()
|
||||
.filter(p -> StrUtil.equals(p.getName(), pc.getName()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (Objects.isNull(pdto)) {
|
||||
pdto = new ProductionCostDTO();
|
||||
pdto.setName(pc.getName());
|
||||
cdto.getProductionCosts().add(pdto);
|
||||
}
|
||||
pdto.setCost(pdto.getCost().add(pc.getCost().multiply(dto1.getNum())));
|
||||
});
|
||||
if (CollectionUtil.isEmpty(children)) {
|
||||
cdto.setHasChildren(false);
|
||||
// 计算自身
|
||||
cdto.setPurchasedParts(!BomConstant.STEELS_CATEGORY_CODE.contains(dto.getMaterialCategoryCode()));
|
||||
if (cdto.isPurchasedParts()) {
|
||||
// 外购件只计算采购成本
|
||||
cdto.setPurchasedPartsCost(calculatePurchasedPartsCost(dto));
|
||||
} else {
|
||||
// 非外购件计算材料成本和制作成本
|
||||
// 计算材料成本
|
||||
cdto.setSteelsCost(calculateSteelsCost(dto));
|
||||
// 计算损耗成本
|
||||
cdto.setWasteCost(calculateWasteCost(dto));
|
||||
}
|
||||
} else {
|
||||
cdto.setHasChildren(true);
|
||||
cdto.setPurchasedParts(false);
|
||||
//计算子级成本
|
||||
List<EBomCostCacheDTO> childrenCost = children.parallelStream()
|
||||
.map(c -> calculateBom(false, c, datas, config, result))
|
||||
.collect(Collectors.toList());
|
||||
for (EBomCostCacheDTO c : childrenCost) {
|
||||
EBomDTO dto1 = children.stream().filter(cc -> StrUtil.equals(cc.getMaterialNo(), c.getMaterialNo())).findFirst().orElse(null);
|
||||
cdto.setSteelsCost(cdto.getSteelsCost().add(c.getSteelsCost().multiply(dto1.getNum())));
|
||||
cdto.setSteelsCost(cdto.getSteelsCost().add(c.getWasteCost().multiply(dto1.getNum())));
|
||||
cdto.setPurchasedPartsCost(cdto.getPurchasedPartsCost().add(c.getPurchasedPartsCost().multiply(dto1.getNum())));
|
||||
cdto.setPieceRateSalary(cdto.getPieceRateSalary().add(c.getPieceRateSalary().multiply(dto1.getNum())));
|
||||
cdto.setWelfareExpenses(cdto.getWelfareExpenses().add(c.getWelfareExpenses().multiply(dto1.getNum())));
|
||||
cdto.setHydropowerCost(cdto.getHydropowerCost().add(c.getHydropowerCost().multiply(dto1.getNum())));
|
||||
cdto.setDepreciationCost(cdto.getDepreciationCost().add(c.getDepreciationCost().multiply(dto1.getNum())));
|
||||
cdto.setWorkshopManagementLaborCost(cdto.getWorkshopManagementLaborCost().add(c.getWorkshopManagementLaborCost().multiply(dto1.getNum())));
|
||||
cdto.setWorkshopOfficeExpenses(cdto.getWorkshopOfficeExpenses().add(c.getWorkshopOfficeExpenses().multiply(dto1.getNum())));
|
||||
cdto.setAuxiliaryDepartmentLaborCost(cdto.getAuxiliaryDepartmentLaborCost().add(c.getAuxiliaryDepartmentLaborCost().multiply(dto1.getNum())));
|
||||
cdto.setAuxiliaryDepartmentExpenses(cdto.getAuxiliaryDepartmentExpenses().add(c.getAuxiliaryDepartmentExpenses().multiply(dto1.getNum())));
|
||||
cdto.setPaintCost(cdto.getPaintCost().add(c.getPaintCost().multiply(dto1.getNum())));
|
||||
if (CollectionUtil.isNotEmpty(c.getProductionCosts())) {
|
||||
c.getProductionCosts().forEach(pc -> {
|
||||
ProductionCostDTO pdto = cdto.getProductionCosts().parallelStream()
|
||||
.filter(p -> StrUtil.equals(p.getName(), pc.getName()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (Objects.isNull(pdto)) {
|
||||
pdto = new ProductionCostDTO();
|
||||
pdto.setName(pc.getName());
|
||||
cdto.getProductionCosts().add(pdto);
|
||||
}
|
||||
pdto.setCost(pdto.getCost().add(pc.getCost().multiply(dto1.getNum())));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -167,7 +180,12 @@ public class BomCostCalculateService {
|
|||
//log.debug(cdata);
|
||||
EBomCostCacheDTO cdto = JsonUtil.fromJson(cdata, EBomCostCacheDTO.class);
|
||||
result.add(cdto);
|
||||
children.parallelStream().forEach(c -> calculateBom(c, datas, config, result));
|
||||
if (!purchaseTypeIsF) {
|
||||
List<EBomDTO> children = datas.stream()
|
||||
.filter(d -> StrUtil.equals(d.getParentMaterialNo(), dto.getMaterialNo()))
|
||||
.collect(Collectors.toList());
|
||||
children.parallelStream().forEach(c -> calculateBom(false, c, datas, config, result));
|
||||
}
|
||||
return cdto;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
package com.nflg.product.technology.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.nflg.product.technology.mapper.master.MaterialMainAttrMapper;
|
||||
import com.nflg.product.technology.pojo.entity.MaterialMainAttrEntity;
|
||||
import org.springframework.data.redis.core.HashOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service
|
||||
public class MaterialMainAttrService extends ServiceImpl<MaterialMainAttrMapper, MaterialMainAttrEntity> {
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public boolean purchaseTypeIsF(String materialNo) {
|
||||
String key = "technology:materialNo:purchaseTypeIsF";
|
||||
HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
|
||||
Object data = hashOps.get(key, materialNo);
|
||||
if (Objects.isNull(data)) {
|
||||
data = lambdaQuery()
|
||||
.eq(MaterialMainAttrEntity::getMaterialNo, materialNo)
|
||||
.eq(MaterialMainAttrEntity::getPurchaseType, "F")
|
||||
.eq(MaterialMainAttrEntity::getFactory, "1010")
|
||||
.exists();
|
||||
if (hashOps.size(key) == 0) {
|
||||
hashOps.put(key, materialNo, data);
|
||||
redisTemplate.expire(key, 8, TimeUnit.HOURS);
|
||||
} else {
|
||||
hashOps.put(key, materialNo, data);
|
||||
}
|
||||
}
|
||||
return (boolean) data;
|
||||
}
|
||||
|
||||
public boolean purchaseTypeIsE50(String materialNo) {
|
||||
String key = "technology:materialNo:purchaseTypeIsE50";
|
||||
HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
|
||||
Object data = hashOps.get(key, materialNo);
|
||||
if (Objects.isNull(data)) {
|
||||
data = lambdaQuery()
|
||||
.eq(MaterialMainAttrEntity::getMaterialNo, materialNo)
|
||||
.eq(MaterialMainAttrEntity::getFactory, "1010")
|
||||
.eq(MaterialMainAttrEntity::getPurchaseType, "E")
|
||||
.eq(MaterialMainAttrEntity::getSpecialPurchaseType, "50")
|
||||
.exists();
|
||||
if (hashOps.size(key) == 0) {
|
||||
hashOps.put(key, materialNo, data);
|
||||
redisTemplate.expire(key, 8, TimeUnit.HOURS);
|
||||
} else {
|
||||
hashOps.put(key, materialNo, data);
|
||||
}
|
||||
}
|
||||
return (boolean) data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.nflg.product.technology.mapper.master.MaterialMainAttrMapper">
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue