feat(产品成本分析): BOM组件成本分析
This commit is contained in:
parent
0311b76a17
commit
58e71449b4
|
|
@ -3,6 +3,7 @@ package com.nflg.product.technology.config;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
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.StringRedisSerializer;
|
||||
|
||||
|
|
@ -27,4 +28,16 @@ public class RedisTemplateConfig {
|
|||
return redisTemplate;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
|
||||
RedisTemplate<String, String> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(factory);
|
||||
|
||||
// 设置 key 和 value 的序列化方式
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.setValueSerializer(new StringRedisSerializer());
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package com.nflg.product.technology.constant;
|
||||
|
||||
public class BomConstant {
|
||||
public static final String PROJECT_TYPE_TEMPORARY = "T";
|
||||
}
|
||||
|
|
@ -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.EBomChildEntity;
|
||||
|
||||
public interface EBomChildMapper extends BaseMapper<EBomChildEntity> {
|
||||
}
|
||||
|
|
@ -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.EBomParentEntity;
|
||||
|
||||
public interface EBomParentMapper extends BaseMapper<EBomParentEntity> {
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.nflg.product.technology.mapper.master;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.nflg.product.technology.pojo.dto.EBomDTO;
|
||||
import com.nflg.product.technology.pojo.entity.MaterialMainEntity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface MaterialMainMapper extends BaseMapper<MaterialMainEntity> {
|
||||
List<EBomDTO> getInfos(Set<String> materialNos);
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.nflg.product.technology.pojo;
|
||||
|
||||
import com.nflg.product.technology.pojo.entity.VirtualWorkingEntity;
|
||||
import com.nflg.product.technology.pojo.query.VirtualWorkingManday;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class BomCostCalculateConfig {
|
||||
|
||||
private List<VirtualWorkingEntity> virtualWorkings;
|
||||
|
||||
private VirtualWorkingManday manday;
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
package com.nflg.product.technology.pojo.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class EBomCostCacheDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
private String materialNo;
|
||||
|
||||
/**
|
||||
* 钢材成本
|
||||
*/
|
||||
private BigDecimal steelsCost = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* 外购件成本
|
||||
*/
|
||||
private BigDecimal purchasedPartsCost = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* 标准计件工资
|
||||
*/
|
||||
private BigDecimal pieceRateSalary = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* 福利费用
|
||||
*/
|
||||
private BigDecimal welfareExpenses = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* 水电生产耗材成本
|
||||
*/
|
||||
private BigDecimal hydropowerCost = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* 折旧成本
|
||||
*/
|
||||
private BigDecimal depreciationCost = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* 车间管理人工费
|
||||
*/
|
||||
private BigDecimal workshopManagementLaborCost = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* 车间办公室费用
|
||||
*/
|
||||
private BigDecimal workshopOfficeExpenses = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* 辅助部门人工费
|
||||
*/
|
||||
private BigDecimal auxiliaryDepartmentLaborCost = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* 辅助部门费用
|
||||
*/
|
||||
private BigDecimal auxiliaryDepartmentExpenses = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* 油漆成本
|
||||
*/
|
||||
private BigDecimal paintCost = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* 制作成本
|
||||
*/
|
||||
private List<ProductionCostDTO> productionCosts;
|
||||
|
||||
/**
|
||||
* 是否外购件
|
||||
*/
|
||||
private boolean isPurchasedParts;
|
||||
|
||||
/**
|
||||
* 材料成本
|
||||
*/
|
||||
@JsonIgnore
|
||||
private BigDecimal materialCost;
|
||||
|
||||
public BigDecimal getMaterialCost() {
|
||||
return getSteelsCost().add(getPurchasedPartsCost());
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接人工制做成本
|
||||
*/
|
||||
@JsonIgnore
|
||||
private BigDecimal directManualProductionCost;
|
||||
|
||||
public BigDecimal getDirectManualProductionCost() {
|
||||
return getPieceRateSalary().add(getWelfareExpenses());
|
||||
}
|
||||
|
||||
/**
|
||||
* 辅助制造成本
|
||||
*/
|
||||
@JsonIgnore
|
||||
private BigDecimal auxiliaryManufacturingCost;
|
||||
|
||||
public BigDecimal getAuxiliaryManufacturingCost() {
|
||||
return getHydropowerCost().add(getDepreciationCost()).add(getWorkshopManagementLaborCost())
|
||||
.add(getWorkshopOfficeExpenses()).add(getAuxiliaryDepartmentLaborCost()).add(getAuxiliaryDepartmentExpenses());
|
||||
}
|
||||
|
||||
/**
|
||||
* 产品总成本
|
||||
*/
|
||||
@JsonIgnore
|
||||
private BigDecimal totalCost;
|
||||
|
||||
public BigDecimal getTotalCost() {
|
||||
return getMaterialCost().add(getDirectManualProductionCost()).add(getAuxiliaryManufacturingCost()).add(getPaintCost());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package com.nflg.product.technology.pojo.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class EBomDTO {
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
private String materialNo;
|
||||
|
||||
/**
|
||||
* 图号
|
||||
*/
|
||||
private String drawingNo;
|
||||
|
||||
/**
|
||||
* 物料描述
|
||||
*/
|
||||
private String materialDesc;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
private String materialUnit;
|
||||
|
||||
/**
|
||||
* 单重
|
||||
*/
|
||||
private BigDecimal unitWeight;
|
||||
|
||||
/**
|
||||
* 最近采购价格
|
||||
*/
|
||||
private BigDecimal lastPurchasePrice;
|
||||
|
||||
/**
|
||||
* 物料分类编码
|
||||
*/
|
||||
private String materialCategoryCode;
|
||||
|
||||
/**
|
||||
* 物料分类名称
|
||||
*/
|
||||
private String categoryName;
|
||||
|
||||
/**
|
||||
* 关联物料分类编码
|
||||
*/
|
||||
private String relCategoryCode;
|
||||
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
private String currentVersion;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private BigDecimal num;
|
||||
|
||||
/**
|
||||
* 父物料编码
|
||||
*/
|
||||
private String parentMaterialNo;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.nflg.product.technology.pojo.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class ProductionCostDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 费用名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 成本
|
||||
*/
|
||||
private BigDecimal cost = BigDecimal.ZERO;
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
package com.nflg.product.technology.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@ApiModel(value = "com-nflg-product-technology-pojo-entity-EBomChildEntity")
|
||||
@TableName(value = "t_bom_new_ebom_child")
|
||||
public class EBomChildEntity implements Serializable {
|
||||
|
||||
/**
|
||||
* 主键-雪花
|
||||
*/
|
||||
@TableId(value = "row_id", type = IdType.ASSIGN_ID)
|
||||
@ApiModelProperty(value = "主键-雪花")
|
||||
private Long rowId;
|
||||
|
||||
/**
|
||||
* 父行ID
|
||||
*/
|
||||
@TableField(value = "parent_row_id")
|
||||
@ApiModelProperty(value = "父行ID")
|
||||
private Long parentRowId;
|
||||
|
||||
/**
|
||||
* 排序号
|
||||
*/
|
||||
@TableField(value = "order_number")
|
||||
@ApiModelProperty(value = "排序号")
|
||||
private String orderNumber;
|
||||
|
||||
// /**
|
||||
// * 图号
|
||||
// */
|
||||
// @TableField(value = "drawing_no")
|
||||
// @ApiModelProperty(value = "图号")
|
||||
// private String drawingNo;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@TableField(value = "material_no")
|
||||
@ApiModelProperty(value = "物料编码")
|
||||
private String materialNo;
|
||||
|
||||
// /**
|
||||
// * 物料描述
|
||||
// */
|
||||
// @TableField(value = "material_desc")
|
||||
// @ApiModelProperty(value = "物料描述")
|
||||
// private String materialDesc;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
@TableField(value = "material_unit")
|
||||
@ApiModelProperty(value = "单位")
|
||||
private String materialUnit;
|
||||
|
||||
// /**
|
||||
// * 物料分类编码
|
||||
// */
|
||||
// @TableField(value = "material_category_code")
|
||||
// @ApiModelProperty(value = "物料分类编码")
|
||||
// private String materialCategoryCode;
|
||||
|
||||
/**
|
||||
* 单重
|
||||
*/
|
||||
@TableField(value = "unit_weight")
|
||||
@ApiModelProperty(value = "单重")
|
||||
private BigDecimal unitWeight;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
@TableField(value = "num")
|
||||
@ApiModelProperty(value = "数量")
|
||||
private BigDecimal num;
|
||||
|
||||
// /**
|
||||
// * 总重
|
||||
// */
|
||||
// @TableField(value = "total_weight")
|
||||
// @ApiModelProperty(value = "总重")
|
||||
// private BigDecimal totalWeight;
|
||||
|
||||
/**
|
||||
* 项目类型
|
||||
*/
|
||||
@TableField(value = "project_type")
|
||||
@ApiModelProperty(value = "项目类型")
|
||||
private String projectType;
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package com.nflg.product.technology.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@ApiModel(value = "com-nflg-product-technology-pojo-entity-EBomParentEntity")
|
||||
@TableName(value = "t_bom_new_ebom_parent")
|
||||
public class EBomParentEntity implements Serializable {
|
||||
|
||||
/**
|
||||
* 主键行ID-雪花
|
||||
*/
|
||||
@TableId(value = "row_id", type = IdType.ASSIGN_ID)
|
||||
@ApiModelProperty(value = "主键行ID-雪花")
|
||||
private Long rowId;
|
||||
|
||||
// /**
|
||||
// * 图号
|
||||
// */
|
||||
// @TableField(value = "drawing_no")
|
||||
// @ApiModelProperty(value = "图号")
|
||||
// private String drawingNo;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@TableField(value = "material_no")
|
||||
@ApiModelProperty(value = "物料编码")
|
||||
private String materialNo;
|
||||
|
||||
// /**
|
||||
// * 物料描述
|
||||
// */
|
||||
// @TableField(value = "material_desc")
|
||||
// @ApiModelProperty(value = "物料描述")
|
||||
// private String materialDesc;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
@TableField(value = "material_unit")
|
||||
@ApiModelProperty(value = "单位")
|
||||
private String materialUnit;
|
||||
|
||||
/**
|
||||
* 单重
|
||||
*/
|
||||
@TableField(value = "unit_weight")
|
||||
@ApiModelProperty(value = "单重")
|
||||
private BigDecimal unitWeight;
|
||||
|
||||
// /**
|
||||
// * 总重
|
||||
// */
|
||||
// @TableField(value = "total_weight")
|
||||
// @ApiModelProperty(value = "总重")
|
||||
// private BigDecimal totalWeight;
|
||||
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
@TableField(value = "current_version")
|
||||
@ApiModelProperty(value = "版本号")
|
||||
private String currentVersion;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
@TableField(value = "num")
|
||||
@ApiModelProperty(value = "数量")
|
||||
private BigDecimal num;
|
||||
|
||||
/**
|
||||
* 1=待复核、2=已复核、3=已退回、4=定版(已发布PBOM)
|
||||
*/
|
||||
@TableField(value = "status")
|
||||
@ApiModelProperty(value = "1=待复核、2=已复核、3=已退回、4=定版(已发布PBOM)")
|
||||
private Integer status;
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
package com.nflg.product.technology.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@ApiModel(value = "com-nflg-product-technology-pojo-main-entity-MaterialMainEntity")
|
||||
@TableName(value = "t_material_main")
|
||||
public class MaterialMainEntity 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 = "material_desc")
|
||||
@ApiModelProperty(value = "物料描述")
|
||||
private String materialDesc;
|
||||
|
||||
/**
|
||||
* 物料分类编码
|
||||
*/
|
||||
@TableField(value = "material_category_code")
|
||||
@ApiModelProperty(value = "物料分类编码")
|
||||
private String materialCategoryCode;
|
||||
|
||||
/**
|
||||
* 图号
|
||||
*/
|
||||
@TableField(value = "drawing_no")
|
||||
@ApiModelProperty(value = "图号")
|
||||
private String drawingNo;
|
||||
|
||||
/**
|
||||
* 重量-kg
|
||||
*/
|
||||
@TableField(value = "material_weight")
|
||||
@ApiModelProperty(value = "重量-kg")
|
||||
private String materialWeight;
|
||||
|
||||
/**
|
||||
* 基本计量单位
|
||||
*/
|
||||
@TableField(value = "material_unit")
|
||||
@ApiModelProperty(value = "基本计量单位")
|
||||
private String materialUnit;
|
||||
|
||||
/**
|
||||
* 物料类型:0:外购 1:自制
|
||||
*/
|
||||
@TableField(value = "material_type")
|
||||
@ApiModelProperty(value = "物料类型:0:外购 1:自制")
|
||||
private Integer materialType;
|
||||
|
||||
/**
|
||||
* 库存量
|
||||
*/
|
||||
@TableField(value = "material_stock")
|
||||
@ApiModelProperty(value = "库存量")
|
||||
private BigDecimal materialStock;
|
||||
|
||||
/**
|
||||
* 最近采购价格
|
||||
*/
|
||||
@TableField(value = "last_purchase_price")
|
||||
@ApiModelProperty(value = "最近采购价格")
|
||||
private BigDecimal lastPurchasePrice;
|
||||
|
||||
/**
|
||||
* 订单保护价
|
||||
*/
|
||||
@TableField(value = "order_protect_price")
|
||||
@ApiModelProperty(value = "订单保护价")
|
||||
private BigDecimal orderProtectPrice;
|
||||
|
||||
/**
|
||||
* 物料状态 1:激活 2:禁止采购 3:售后专用 4:冻结 5:完全弃用
|
||||
*/
|
||||
@TableField(value = "material_state")
|
||||
@ApiModelProperty(value = "物料状态 1:激活 2:禁止采购 3:售后专用 4:冻结 5:完全弃用")
|
||||
private Integer materialState;
|
||||
|
||||
/**
|
||||
* 制作物料获取类型:1=自制、2=外协、3=采购
|
||||
*/
|
||||
@TableField(value = "material_get_type")
|
||||
@ApiModelProperty(value = "制作物料获取类型:1=自制、2=外协、3=采购")
|
||||
private Integer materialGetType;
|
||||
}
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
package com.nflg.product.technology.pojo.query;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.nflg.product.base.core.config.BigDecimalSerializer;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
|
@ -21,9 +24,13 @@ public class VirtualWorkingManday implements Serializable {
|
|||
|
||||
@ApiModelProperty("计件人工工时工资(一线)")
|
||||
@Positive(message = "计件人工工时工资(一线)必须大于0")
|
||||
@JsonFormat(pattern = "#.##")
|
||||
@JsonSerialize(using = BigDecimalSerializer.class)
|
||||
private BigDecimal hourlyWages;
|
||||
|
||||
@ApiModelProperty("一线人工福利")
|
||||
@Min(value = 0, message = "一线人工福利必须大于等于0")
|
||||
@JsonFormat(pattern = "#.##")
|
||||
@JsonSerialize(using = BigDecimalSerializer.class)
|
||||
private BigDecimal benefit;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.nflg.product.technology.pojo.vo;
|
||||
|
||||
import com.nflg.product.technology.util.RandomUtil;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
|
@ -8,6 +7,7 @@ import lombok.experimental.Accessors;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -22,115 +22,51 @@ public class BomCostMultilayerVO implements Serializable {
|
|||
@ApiModelProperty("物料编码")
|
||||
private String materialNo;
|
||||
|
||||
public String getMaterialNo() {
|
||||
return RandomUtil.randomString(10);
|
||||
}
|
||||
|
||||
@ApiModelProperty("物料描述")
|
||||
private String materialDesc;
|
||||
|
||||
public String getMaterialDesc() {
|
||||
return RandomUtil.randomString(20);
|
||||
}
|
||||
|
||||
@ApiModelProperty("物料类别")
|
||||
private String materialCategoryName;
|
||||
|
||||
public String getMaterialCategoryName() {
|
||||
return RandomUtil.randomString(10);
|
||||
}
|
||||
|
||||
@ApiModelProperty("单位")
|
||||
private String materialUnit;
|
||||
|
||||
public String getMaterialUnit() {
|
||||
return "PC";
|
||||
}
|
||||
|
||||
@ApiModelProperty("单件成本")
|
||||
private BigDecimal price;
|
||||
|
||||
public BigDecimal getPrice() {
|
||||
return RandomUtil.randomBigDecimal(1000, 2);
|
||||
}
|
||||
|
||||
@ApiModelProperty("单层数量")
|
||||
private BigDecimal num;
|
||||
|
||||
public BigDecimal getNum() {
|
||||
return RandomUtil.randomBigDecimal(100, 2);
|
||||
}
|
||||
|
||||
@ApiModelProperty("累乘数量")
|
||||
private BigDecimal totalNum;
|
||||
|
||||
public BigDecimal getTotalNum() {
|
||||
return RandomUtil.randomBigDecimal(1000, 2);
|
||||
}
|
||||
|
||||
@ApiModelProperty("总成本")
|
||||
private BigDecimal totalCost;
|
||||
|
||||
public BigDecimal getTotalCost() {
|
||||
return RandomUtil.randomBigDecimal(100000, 2);
|
||||
}
|
||||
|
||||
@ApiModelProperty("单件材料成本")
|
||||
private BigDecimal materialCost;
|
||||
|
||||
public BigDecimal getMaterialCost() {
|
||||
return RandomUtil.randomBigDecimal(100000, 2);
|
||||
}
|
||||
|
||||
@ApiModelProperty("材料成本")
|
||||
private BigDecimal totalMaterialCost;
|
||||
|
||||
public BigDecimal getTotalMaterialCost() {
|
||||
return RandomUtil.randomBigDecimal(100000, 2);
|
||||
}
|
||||
|
||||
@ApiModelProperty("单件油漆成本")
|
||||
private BigDecimal paintCost;
|
||||
|
||||
public BigDecimal getPaintCost() {
|
||||
return RandomUtil.randomBigDecimal(100000, 2);
|
||||
}
|
||||
|
||||
@ApiModelProperty("油漆成本")
|
||||
private BigDecimal totalPaintCost;
|
||||
|
||||
public BigDecimal getTotalPaintCost() {
|
||||
return RandomUtil.randomBigDecimal(100000, 2);
|
||||
}
|
||||
|
||||
@ApiModelProperty("单件标准人工工资")
|
||||
private BigDecimal standardPieceRateSalary;
|
||||
|
||||
public BigDecimal getStandardPieceRateSalary() {
|
||||
return RandomUtil.randomBigDecimal(100000, 2);
|
||||
}
|
||||
|
||||
@ApiModelProperty("标准人工工资")
|
||||
private BigDecimal totalStandardPieceRateSalary;
|
||||
|
||||
public BigDecimal getTotalStandardPieceRateSalary() {
|
||||
return RandomUtil.randomBigDecimal(100000, 2);
|
||||
}
|
||||
|
||||
@ApiModelProperty("单件辅助费用")
|
||||
private BigDecimal auxiliaryManufacturingCost;
|
||||
|
||||
public BigDecimal getAuxiliaryManufacturingCost() {
|
||||
return RandomUtil.randomBigDecimal(100000, 2);
|
||||
}
|
||||
|
||||
@ApiModelProperty("辅助费用")
|
||||
private BigDecimal totalAuxiliaryManufacturingCost;
|
||||
|
||||
public BigDecimal getTotalAuxiliaryManufacturingCost() {
|
||||
return RandomUtil.randomBigDecimal(100000, 2);
|
||||
}
|
||||
|
||||
@ApiModelProperty("子物料列表")
|
||||
private List<BomCostMultilayerVO> children;
|
||||
private List<BomCostMultilayerVO> children = new ArrayList<>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,320 @@
|
|||
package com.nflg.product.technology.service;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.nflg.product.technology.constant.BomConstant;
|
||||
import com.nflg.product.technology.pojo.BomCostCalculateConfig;
|
||||
import com.nflg.product.technology.pojo.dto.EBomCostCacheDTO;
|
||||
import com.nflg.product.technology.pojo.dto.EBomDTO;
|
||||
import com.nflg.product.technology.pojo.dto.ProductionCostDTO;
|
||||
import com.nflg.product.technology.pojo.entity.*;
|
||||
import com.nflg.product.technology.pojo.query.VirtualWorkingManday;
|
||||
import com.nflg.product.technology.util.JsonUtil;
|
||||
import com.nflg.product.technology.util.VUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class BomCostCalculateService {
|
||||
|
||||
@Resource
|
||||
private EBomService ebomService;
|
||||
|
||||
@Resource
|
||||
private MaterialMainService materialMainService;
|
||||
|
||||
@Resource
|
||||
private SteelsCostConfigService steelsCostConfigService;
|
||||
|
||||
@Resource
|
||||
private PaintCostConfigService paintCostConfigService;
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
/**
|
||||
* 缓存时长
|
||||
*/
|
||||
private static final Duration CACHE_DURATION = Duration.ofHours(1);
|
||||
|
||||
/**
|
||||
* 钢件类别
|
||||
*/
|
||||
private static final List<String> STEELS_CATEGORY_CODE = Arrays.asList("10010101", "10010102", "10010103", "10010104", "10010105", "10010110");
|
||||
|
||||
public List<EBomCostCacheDTO> calculate(String materialNo, BomCostCalculateConfig config) {
|
||||
VUtils.isTure(StrUtil.isBlank(materialNo)).throwMessage("物料编号不能为空");
|
||||
List<EBomDTO> datas = new ArrayList<>();
|
||||
EBomParentEntity parent = ebomService.getParent(materialNo);
|
||||
VUtils.isTure(Objects.isNull(parent)).throwMessage("未找到BOM: " + materialNo);
|
||||
log.debug(StrUtil.format("BOM成本计算 {} 起始节点", materialNo));
|
||||
EBomDTO pDto = convert(parent);
|
||||
datas.add(pDto);
|
||||
getChildren(materialNo, datas);
|
||||
List<EBomCostCacheDTO> result = new ArrayList<>(50);
|
||||
calculateBom(pDto, datas, config, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private EBomCostCacheDTO calculateBom(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)) {
|
||||
EBomCostCacheDTO cdto = new EBomCostCacheDTO();
|
||||
cdto.setMaterialNo(dto.getMaterialNo());
|
||||
cdto.setPurchasedParts(!STEELS_CATEGORY_CODE.contains(dto.getMaterialCategoryCode()));
|
||||
if (CollectionUtil.isEmpty(children)) {
|
||||
//没有子级,直接计算成本
|
||||
log.debug(StrUtil.format("BOM成本计算 {} 直接计算", dto.getMaterialNo()));
|
||||
if (cdto.isPurchasedParts()) {
|
||||
cdto.setPurchasedPartsCost(calculatePurchasedPartsCost(dto));
|
||||
} else {
|
||||
cdto.setSteelsCost(calculateSteelsCost(dto));
|
||||
cdto.setPieceRateSalary(calculatePieceRateSalary(dto, config.getManday()));
|
||||
cdto.setWelfareExpenses(calculateWelfareExpenses(dto, config.getManday()));
|
||||
cdto.setHydropowerCost(calculateHydropowerCost(config.getVirtualWorkings()));
|
||||
cdto.setDepreciationCost(calculateDepreciationCost(config.getVirtualWorkings()));
|
||||
cdto.setWorkshopManagementLaborCost(calculateWorkshopManagementLaborCost(config.getVirtualWorkings()));
|
||||
cdto.setWorkshopOfficeExpenses(calculateWorkshopOfficeExpenses(config.getVirtualWorkings()));
|
||||
cdto.setAuxiliaryDepartmentLaborCost(calculateAuxiliaryDepartmentLaborCost(config.getVirtualWorkings()));
|
||||
cdto.setAuxiliaryDepartmentExpenses(calculateAuxiliaryDepartmentExpenses(config.getVirtualWorkings()));
|
||||
cdto.setPaintCost(calculatePaintCost(dto));
|
||||
cdto.setProductionCosts(calculateProductionCosts(config));
|
||||
}
|
||||
} else {
|
||||
//有子级,先计算子级成本
|
||||
List<EBomCostCacheDTO> childrenCost = children.stream()
|
||||
.map(c -> calculateBom(c, datas, config, result))
|
||||
.collect(Collectors.toList());
|
||||
List<ProductionCostDTO> productionCosts = new ArrayList<>();
|
||||
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.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(cdto.getProductionCosts())) {
|
||||
cdto.getProductionCosts().forEach(pc -> {
|
||||
ProductionCostDTO pdto = productionCosts.stream()
|
||||
.filter(p -> StrUtil.equals(p.getName(), pc.getName()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (Objects.isNull(pdto)) {
|
||||
pdto = new ProductionCostDTO();
|
||||
pdto.setName(pc.getName());
|
||||
productionCosts.add(pdto);
|
||||
}
|
||||
pdto.setCost(pdto.getCost().add(pc.getCost().multiply(dto1.getNum())));
|
||||
});
|
||||
cdto.setProductionCosts(productionCosts);
|
||||
}
|
||||
}
|
||||
log.debug(StrUtil.format("BOM成本计算 {} 根据子级计算", dto.getMaterialNo()));
|
||||
}
|
||||
result.add(cdto);
|
||||
cdata = JsonUtil.toJson(cdto);
|
||||
log.debug(cdata);
|
||||
redisTemplate.opsForValue().set(buildKey(dto), cdata, CACHE_DURATION);
|
||||
return cdto;
|
||||
} else {
|
||||
log.debug(StrUtil.format("BOM成本计算 {} 从缓存读取", dto.getMaterialNo()));
|
||||
log.debug(cdata);
|
||||
EBomCostCacheDTO cdto = JsonUtil.fromJson(cdata, EBomCostCacheDTO.class);
|
||||
result.add(cdto);
|
||||
children.forEach(c -> calculateBom(c, datas, config, result));
|
||||
return cdto;
|
||||
}
|
||||
}
|
||||
|
||||
private List<ProductionCostDTO> calculateProductionCosts(BomCostCalculateConfig config) {
|
||||
List<ProductionCostDTO> productionCosts = new ArrayList<>();
|
||||
BigDecimal hourlyWages;
|
||||
BigDecimal benefit;
|
||||
BigDecimal auxiliaryMaterialsAndConsumables;
|
||||
BigDecimal feeEquipmentDepreciation;
|
||||
BigDecimal feeWorkshopLaborCost;
|
||||
BigDecimal feeWorkshopOffice;
|
||||
BigDecimal auxiliaryDepartmentLaborCosts;
|
||||
BigDecimal assistantFee;
|
||||
for (VirtualWorkingEntity vw : config.getVirtualWorkings()) {
|
||||
ProductionCostDTO dto = new ProductionCostDTO();
|
||||
dto.setName(vw.getName());
|
||||
hourlyWages = Optional.ofNullable(config.getManday().getHourlyWages()).orElse(BigDecimal.ZERO);
|
||||
benefit = Optional.ofNullable(config.getManday().getBenefit()).orElse(BigDecimal.ZERO);
|
||||
auxiliaryMaterialsAndConsumables = Optional.ofNullable(vw.getConsumablesFee()).orElse(BigDecimal.ZERO);
|
||||
feeEquipmentDepreciation = Optional.ofNullable(vw.getEquipmentDepreciationFee()).orElse(BigDecimal.ZERO);
|
||||
feeWorkshopLaborCost = Optional.ofNullable(vw.getWorkshopLaborFee()).orElse(BigDecimal.ZERO);
|
||||
feeWorkshopOffice = Optional.ofNullable(vw.getWorkshopOfficeFee()).orElse(BigDecimal.ZERO);
|
||||
auxiliaryDepartmentLaborCosts = Optional.ofNullable(vw.getAssistantLaborFee()).orElse(BigDecimal.ZERO);
|
||||
assistantFee = Optional.ofNullable(vw.getAssistantFee()).orElse(BigDecimal.ZERO);
|
||||
dto.setCost(hourlyWages.add(benefit).add(auxiliaryMaterialsAndConsumables).add(feeEquipmentDepreciation)
|
||||
.add(feeEquipmentDepreciation).add(feeWorkshopLaborCost).add(feeWorkshopOffice)
|
||||
.add(auxiliaryDepartmentLaborCosts).add(assistantFee)
|
||||
.multiply(getGsForWorkingType(vw.getName())));
|
||||
}
|
||||
return productionCosts;
|
||||
}
|
||||
|
||||
private BigDecimal calculatePaintCost(EBomDTO dto) {
|
||||
String lable = "";// TODO 物料标签对应的油漆标签
|
||||
PaintCostConfigEntity entity = paintCostConfigService.getCost(lable);
|
||||
if (Objects.nonNull(entity)) {
|
||||
return NumberUtil.mul(dto.getUnitWeight(), entity.getCost());
|
||||
} else {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal calculateWorkshopOfficeExpenses(List<VirtualWorkingEntity> virtualWorkings) {
|
||||
BigDecimal cost = BigDecimal.ZERO;
|
||||
for (VirtualWorkingEntity vw : virtualWorkings) {
|
||||
cost = cost.add(vw.getWorkshopOfficeFee().multiply(getGsForWorkingType(vw.getName())));
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
private BigDecimal calculateAuxiliaryDepartmentExpenses(List<VirtualWorkingEntity> virtualWorkings) {
|
||||
BigDecimal cost = BigDecimal.ZERO;
|
||||
for (VirtualWorkingEntity vw : virtualWorkings) {
|
||||
cost = cost.add(vw.getAssistantFee().multiply(getGsForWorkingType(vw.getName())));
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
private BigDecimal calculateAuxiliaryDepartmentLaborCost(List<VirtualWorkingEntity> virtualWorkings) {
|
||||
BigDecimal cost = BigDecimal.ZERO;
|
||||
for (VirtualWorkingEntity vw : virtualWorkings) {
|
||||
cost = cost.add(vw.getAssistantLaborFee().multiply(getGsForWorkingType(vw.getName())));
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
private BigDecimal calculateWorkshopManagementLaborCost(List<VirtualWorkingEntity> virtualWorkings) {
|
||||
BigDecimal cost = BigDecimal.ZERO;
|
||||
for (VirtualWorkingEntity vw : virtualWorkings) {
|
||||
cost = cost.add(vw.getWorkshopLaborFee().multiply(getGsForWorkingType(vw.getName())));
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
private BigDecimal calculateDepreciationCost(List<VirtualWorkingEntity> virtualWorkings) {
|
||||
BigDecimal cost = BigDecimal.ZERO;
|
||||
for (VirtualWorkingEntity vw : virtualWorkings) {
|
||||
cost = cost.add(vw.getEquipmentDepreciationFee().multiply(getGsForWorkingType(vw.getName())));
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
private BigDecimal calculateHydropowerCost(List<VirtualWorkingEntity> virtualWorkings) {
|
||||
BigDecimal cost = BigDecimal.ZERO;
|
||||
for (VirtualWorkingEntity vw : virtualWorkings) {
|
||||
cost = cost.add(vw.getConsumablesFee().multiply(getGsForWorkingType(vw.getName())));
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
private BigDecimal getGsForWorkingType(String type) {
|
||||
//TODO 获取工时类型对应的工时
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
private BigDecimal calculateWelfareExpenses(EBomDTO dto, VirtualWorkingManday manday) {
|
||||
return getTGS().multiply(Optional.ofNullable(manday.getBenefit()).orElse(BigDecimal.ZERO));
|
||||
}
|
||||
|
||||
private BigDecimal calculatePieceRateSalary(EBomDTO dto, VirtualWorkingManday manday) {
|
||||
return getTGS().multiply(Optional.ofNullable(manday.getHourlyWages()).orElse(BigDecimal.ZERO));
|
||||
}
|
||||
|
||||
private BigDecimal getTGS() {
|
||||
// TODO 获取总工时
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
private BigDecimal calculatePurchasedPartsCost(EBomDTO dto) {
|
||||
return Optional.ofNullable(dto.getLastPurchasePrice()).orElse(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
private BigDecimal calculateSteelsCost(EBomDTO dto) {
|
||||
//是钢材
|
||||
// TODO 物料标签是哪个字段?单价是哪个字段?
|
||||
BigDecimal price = Optional.ofNullable(dto.getLastPurchasePrice()).orElse(BigDecimal.ZERO);
|
||||
BigDecimal unitWeight = Optional.ofNullable(dto.getUnitWeight()).orElse(BigDecimal.ZERO);
|
||||
BigDecimal wastage = BigDecimal.ZERO;
|
||||
String lable = "物料标签";
|
||||
if (StrUtil.isNotBlank(lable)) {
|
||||
SteelsCostConfigEntity steelsCostConfigEntity = steelsCostConfigService.getCost(lable);
|
||||
if (Objects.nonNull(steelsCostConfigEntity)) {
|
||||
price = Optional.ofNullable(steelsCostConfigEntity.getCost()).orElse(BigDecimal.ZERO);
|
||||
wastage = Optional.ofNullable(steelsCostConfigEntity.getWastage()).orElse(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
return price.multiply(BigDecimal.ONE.add(wastage).multiply(unitWeight));
|
||||
}
|
||||
|
||||
private String buildKey(EBomDTO dto) {
|
||||
return StrUtil.format("technology:cost:{}:{}", dto.getMaterialNo()
|
||||
, StrUtil.isBlank(dto.getCurrentVersion()) ? "A00" : dto.getCurrentVersion());
|
||||
}
|
||||
|
||||
private void getChildren(String materialNo, List<EBomDTO> datas) {
|
||||
EBomParentEntity parent = ebomService.getParent(materialNo);
|
||||
if (Objects.nonNull(parent)) {
|
||||
List<EBomChildEntity> children = ebomService.getChildren(parent.getRowId());
|
||||
if (CollectionUtil.isNotEmpty(children)) {
|
||||
datas.addAll(convert(children, parent.getMaterialNo()));
|
||||
children.forEach(c -> {
|
||||
getChildren(c.getMaterialNo(), datas);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private EBomDTO convert(EBomParentEntity entity) {
|
||||
List<EBomDTO> mainEntities = materialMainService.getInfos(Collections.singleton(entity.getMaterialNo()));
|
||||
VUtils.isTure(CollectionUtil.isEmpty(mainEntities)).throwMessage("未找到主物料: " + entity.getMaterialNo());
|
||||
EBomDTO dto = mainEntities.get(0);
|
||||
dto.setNum(entity.getNum());
|
||||
dto.setCurrentVersion(entity.getCurrentVersion());
|
||||
return dto;
|
||||
}
|
||||
|
||||
private List<EBomDTO> convert(List<EBomChildEntity> children, String parentMaterialNo) {
|
||||
Set<String> materialNos = children.stream()
|
||||
.filter(c -> !StrUtil.equals(c.getProjectType(), BomConstant.PROJECT_TYPE_TEMPORARY))
|
||||
.map(EBomChildEntity::getMaterialNo)
|
||||
.collect(Collectors.toSet());
|
||||
List<EBomDTO> mainEntities = materialMainService.getInfos(materialNos);
|
||||
materialNos.removeAll(mainEntities.stream().map(EBomDTO::getMaterialNo).collect(Collectors.toSet()));
|
||||
VUtils.isTure(CollectionUtil.isNotEmpty(materialNos)).throwMessage(parentMaterialNo + "的下级物料不在主物料表中: " + String.join(",", materialNos));
|
||||
if (CollectionUtil.isNotEmpty(mainEntities)) {
|
||||
mainEntities.forEach(e -> {
|
||||
//相同编号合并数量
|
||||
e.setNum(children.stream()
|
||||
.filter(c -> StrUtil.equals(c.getMaterialNo(), e.getMaterialNo()))
|
||||
.map(EBomChildEntity::getNum)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
e.setParentMaterialNo(parentMaterialNo);
|
||||
});
|
||||
}
|
||||
return mainEntities;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.nflg.product.technology.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.nflg.product.technology.mapper.master.EBomChildMapper;
|
||||
import com.nflg.product.technology.pojo.entity.EBomChildEntity;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class EBomChildService extends ServiceImpl<EBomChildMapper, EBomChildEntity> {
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.nflg.product.technology.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.nflg.product.technology.mapper.master.EBomParentMapper;
|
||||
import com.nflg.product.technology.pojo.entity.EBomParentEntity;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class EBomParentService extends ServiceImpl<EBomParentMapper, EBomParentEntity> {
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package com.nflg.product.technology.service;
|
||||
|
||||
import com.nflg.product.technology.pojo.entity.EBomChildEntity;
|
||||
import com.nflg.product.technology.pojo.entity.EBomParentEntity;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class EBomService {
|
||||
|
||||
@Resource
|
||||
private EBomParentService ebomParentService;
|
||||
|
||||
@Resource
|
||||
private EBomChildService ebomChildService;
|
||||
|
||||
public EBomParentEntity getParent(String materialNo) {
|
||||
return ebomParentService.lambdaQuery()
|
||||
.eq(EBomParentEntity::getMaterialNo, materialNo)
|
||||
.ge(EBomParentEntity::getStatus, 4)
|
||||
.one();
|
||||
}
|
||||
|
||||
public List<EBomParentEntity> getParents(Set<String> materialNos) {
|
||||
return ebomParentService.lambdaQuery()
|
||||
.in(EBomParentEntity::getMaterialNo, materialNos)
|
||||
.ge(EBomParentEntity::getStatus, 4)
|
||||
.list();
|
||||
}
|
||||
|
||||
public List<EBomChildEntity> getChildren(long parentRowId) {
|
||||
return ebomChildService.lambdaQuery()
|
||||
.eq(EBomChildEntity::getParentRowId, parentRowId)
|
||||
.orderByAsc(EBomChildEntity::getOrderNumber)
|
||||
.list();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.nflg.product.technology.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.nflg.product.technology.mapper.master.MaterialMainMapper;
|
||||
import com.nflg.product.technology.pojo.dto.EBomDTO;
|
||||
import com.nflg.product.technology.pojo.entity.MaterialMainEntity;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class MaterialMainService extends ServiceImpl<MaterialMainMapper, MaterialMainEntity> {
|
||||
|
||||
public List<EBomDTO> getInfos(Set<String> materialNos) {
|
||||
return baseMapper.getInfos(materialNos);
|
||||
}
|
||||
}
|
||||
|
|
@ -53,4 +53,8 @@ public class PaintCostConfigService extends ServiceImpl<PaintCostConfigMapper, P
|
|||
updateBatchById(forUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
public PaintCostConfigEntity getCost(String name) {
|
||||
return lambdaQuery().eq(PaintCostConfigEntity::getName, name).one();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,21 @@
|
|||
package com.nflg.product.technology.service;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.nflg.product.technology.constant.BomConstant;
|
||||
import com.nflg.product.technology.pojo.BomCostCalculateConfig;
|
||||
import com.nflg.product.technology.pojo.dto.EBomCostCacheDTO;
|
||||
import com.nflg.product.technology.pojo.dto.EBomDTO;
|
||||
import com.nflg.product.technology.pojo.entity.EBomChildEntity;
|
||||
import com.nflg.product.technology.pojo.entity.EBomParentEntity;
|
||||
import com.nflg.product.technology.pojo.query.MaterialVersionCostQuery;
|
||||
import com.nflg.product.technology.pojo.query.VirtualWorkingManday;
|
||||
import com.nflg.product.technology.pojo.vo.*;
|
||||
import com.nflg.product.technology.util.MapUtil;
|
||||
import com.nflg.product.technology.util.RandomUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.math.BigDecimal;
|
||||
|
|
@ -13,6 +23,9 @@ import java.time.LocalDateTime;
|
|||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author 曹鹏飞
|
||||
|
|
@ -22,41 +35,138 @@ import java.util.List;
|
|||
@Slf4j
|
||||
public class ProductCostAnalysisService {
|
||||
|
||||
@Resource
|
||||
private BomCostCalculateService bomCostCalculateService;
|
||||
|
||||
@Resource
|
||||
private VirtualWorkingService virtualWorkingService;
|
||||
|
||||
@Resource
|
||||
private MaterialMainService materialMainService;
|
||||
|
||||
@Resource
|
||||
private EBomService ebomService;
|
||||
|
||||
@Resource
|
||||
private TechnologyConfigService technologyConfigService;
|
||||
|
||||
public List<BomCostSingleLayerVO> getBomCostSingleLayer(String materialNo) {
|
||||
// TODO 待实现
|
||||
List<BomCostSingleLayerVO> list = new ArrayList<>();
|
||||
int count = RandomUtil.randomInt(0, 10);
|
||||
for (int i = 0; i < count; i++) {
|
||||
BomCostSingleLayerVO bomCostSingleLayerVO = new BomCostSingleLayerVO();
|
||||
bomCostSingleLayerVO.setMaterialNo("物料编号" + i);
|
||||
bomCostSingleLayerVO.setPrice(RandomUtil.randomBigDecimal(10000, 2));
|
||||
bomCostSingleLayerVO.setNum(RandomUtil.randomBigDecimal(1000, 2));
|
||||
bomCostSingleLayerVO.setTotalPrice(RandomUtil.randomBigDecimal(1000, 2));
|
||||
bomCostSingleLayerVO.setMaterialDesc("物料描述" + i);
|
||||
bomCostSingleLayerVO.setMaterialCategoryName("物料类别" + i);
|
||||
bomCostSingleLayerVO.setMaterialUnit("PC");
|
||||
bomCostSingleLayerVO.setVersion("版本号" + i);
|
||||
bomCostSingleLayerVO.setMaterialTotalPrice(RandomUtil.randomBigDecimal(1000, 2));
|
||||
bomCostSingleLayerVO.setLaborCosts(RandomUtil.randomBigDecimal(1000, 2));
|
||||
bomCostSingleLayerVO.setAuxiliaryManufacturingCost(RandomUtil.randomBigDecimal(1000, 2));
|
||||
list.add(bomCostSingleLayerVO);
|
||||
}
|
||||
return list;
|
||||
BomCostCalculateConfig cnfig = new BomCostCalculateConfig();
|
||||
VirtualWorkingManday manday = new VirtualWorkingManday();
|
||||
manday.setHourlyWages(technologyConfigService.getHourlyWages());
|
||||
manday.setBenefit(technologyConfigService.getBenefit());
|
||||
cnfig.setManday(manday);
|
||||
cnfig.setVirtualWorkings(virtualWorkingService.list());
|
||||
List<EBomCostCacheDTO> datas = bomCostCalculateService.calculate(materialNo, cnfig);
|
||||
EBomParentEntity parent = ebomService.getParent(materialNo);
|
||||
return buildSingleLayerChildren(parent.getRowId(), datas);
|
||||
}
|
||||
|
||||
public List<BomCostSingleLayerVO> buildSingleLayerChildren(long parentRowId, List<EBomCostCacheDTO> datas) {
|
||||
List<EBomChildEntity> children = ebomService.getChildren(parentRowId);
|
||||
Set<String> materialNos = children.stream()
|
||||
.filter(c -> !StrUtil.equals(c.getProjectType(), BomConstant.PROJECT_TYPE_TEMPORARY))
|
||||
.map(EBomChildEntity::getMaterialNo)
|
||||
.collect(Collectors.toSet());
|
||||
List<EBomParentEntity> parents = ebomService.getParents(materialNos);
|
||||
List<BomCostSingleLayerVO> vos = new ArrayList<>(MapUtil.calculateInitialCapacity(children.size()));
|
||||
List<EBomDTO> materials = materialMainService.getInfos(materialNos);
|
||||
children.forEach(child -> {
|
||||
BomCostSingleLayerVO cvo = new BomCostSingleLayerVO();
|
||||
cvo.setMaterialNo(child.getMaterialNo());
|
||||
EBomDTO cpm = materials.stream().filter(m -> StrUtil.equals(m.getMaterialNo(), child.getMaterialNo())).findFirst().orElse(null);
|
||||
if (Objects.nonNull(cpm)) {
|
||||
cvo.setMaterialDesc(cpm.getMaterialDesc());
|
||||
cvo.setMaterialCategoryName(cpm.getCategoryName());
|
||||
cvo.setMaterialUnit(cpm.getMaterialUnit());
|
||||
}
|
||||
EBomParentEntity parent = parents.stream().filter(p -> StrUtil.equals(p.getMaterialNo(), child.getMaterialNo())).findFirst().orElse(null);
|
||||
cvo.setVersion(Objects.isNull(parent) ? "A00" : parent.getCurrentVersion());
|
||||
EBomCostCacheDTO ccost = datas.stream().filter(d -> StrUtil.equals(d.getMaterialNo(), child.getMaterialNo())).findFirst().orElse(null);
|
||||
if (Objects.nonNull(ccost)) {
|
||||
cvo.setPrice(ccost.getTotalCost());
|
||||
cvo.setNum(child.getNum());
|
||||
cvo.setTotalPrice(cvo.getPrice().multiply(cvo.getNum()));
|
||||
cvo.setMaterialTotalPrice(ccost.getMaterialCost().multiply(cvo.getNum()));
|
||||
cvo.setLaborCosts(ccost.getDirectManualProductionCost().multiply(cvo.getNum()));
|
||||
cvo.setAuxiliaryManufacturingCost(ccost.getAuxiliaryManufacturingCost().multiply(cvo.getNum()));
|
||||
}
|
||||
vos.add(cvo);
|
||||
});
|
||||
return vos;
|
||||
}
|
||||
|
||||
public BomCostMultilayerVO getBomCostMultilayer(String materialNo) {
|
||||
// TODO 待实现
|
||||
BomCostCalculateConfig cnfig = new BomCostCalculateConfig();
|
||||
VirtualWorkingManday manday = new VirtualWorkingManday();
|
||||
manday.setHourlyWages(technologyConfigService.getHourlyWages());
|
||||
manday.setBenefit(technologyConfigService.getBenefit());
|
||||
cnfig.setManday(manday);
|
||||
cnfig.setVirtualWorkings(virtualWorkingService.list());
|
||||
List<EBomCostCacheDTO> datas = bomCostCalculateService.calculate(materialNo, cnfig);
|
||||
List<EBomDTO> materials = materialMainService.getInfos(datas.stream().map(EBomCostCacheDTO::getMaterialNo).collect(Collectors.toSet()));
|
||||
EBomParentEntity parent = ebomService.getParent(materialNo);
|
||||
BomCostMultilayerVO vo = new BomCostMultilayerVO();
|
||||
List<BomCostMultilayerVO> list = new ArrayList<>();
|
||||
int count = RandomUtil.randomInt(0, 10);
|
||||
for (int i = 0; i < count; i++) {
|
||||
BomCostMultilayerVO bomCostMultilayerVO = buildEBomCostMultilayerVO();
|
||||
list.add(bomCostMultilayerVO);
|
||||
vo.setMaterialNo(parent.getMaterialNo());
|
||||
EBomDTO pm = materials.stream().filter(m -> StrUtil.equals(m.getMaterialNo(), parent.getMaterialNo())).findFirst().orElse(null);
|
||||
if (Objects.nonNull(pm)) {
|
||||
vo.setMaterialDesc(pm.getMaterialDesc());
|
||||
vo.setMaterialCategoryName(pm.getCategoryName());
|
||||
vo.setMaterialUnit(pm.getMaterialUnit());
|
||||
}
|
||||
vo.setChildren(list);
|
||||
EBomCostCacheDTO cost = datas.stream().filter(d -> StrUtil.equals(d.getMaterialNo(), parent.getMaterialNo())).findFirst().orElse(null);
|
||||
if (Objects.nonNull(cost)) {
|
||||
vo.setPrice(cost.getTotalCost());
|
||||
vo.setNum(BigDecimal.ONE);
|
||||
vo.setTotalNum(BigDecimal.ONE);
|
||||
vo.setTotalCost(vo.getPrice());
|
||||
vo.setMaterialCost(cost.getMaterialCost());
|
||||
vo.setTotalMaterialCost(cost.getMaterialCost());
|
||||
vo.setPaintCost(cost.getPaintCost());
|
||||
vo.setTotalPaintCost(cost.getPaintCost());
|
||||
vo.setStandardPieceRateSalary(cost.getPieceRateSalary());
|
||||
vo.setTotalStandardPieceRateSalary(cost.getPieceRateSalary());
|
||||
vo.setAuxiliaryManufacturingCost(cost.getAuxiliaryManufacturingCost());
|
||||
vo.setTotalAuxiliaryManufacturingCost(cost.getAuxiliaryManufacturingCost());
|
||||
}
|
||||
buildMultilayerChildren(parent.getRowId(), vo, materials, datas);
|
||||
return vo;
|
||||
}
|
||||
|
||||
private void buildMultilayerChildren(long parentRowId, BomCostMultilayerVO pvo, List<EBomDTO> materials, List<EBomCostCacheDTO> datas) {
|
||||
List<EBomChildEntity> children = ebomService.getChildren(parentRowId);
|
||||
children.forEach(child -> {
|
||||
BomCostMultilayerVO cvo = new BomCostMultilayerVO();
|
||||
cvo.setMaterialNo(child.getMaterialNo());
|
||||
EBomDTO cpm = materials.stream().filter(m -> StrUtil.equals(m.getMaterialNo(), child.getMaterialNo())).findFirst().orElse(null);
|
||||
if (Objects.nonNull(cpm)) {
|
||||
cvo.setMaterialDesc(cpm.getMaterialDesc());
|
||||
cvo.setMaterialCategoryName(cpm.getCategoryName());
|
||||
cvo.setMaterialUnit(cpm.getMaterialUnit());
|
||||
}
|
||||
EBomCostCacheDTO ccost = datas.stream().filter(d -> StrUtil.equals(d.getMaterialNo(), child.getMaterialNo())).findFirst().orElse(null);
|
||||
if (Objects.nonNull(ccost)) {
|
||||
cvo.setPrice(ccost.getTotalCost());
|
||||
cvo.setNum(child.getNum());
|
||||
cvo.setTotalNum(cvo.getNum().multiply(pvo.getTotalNum()));
|
||||
cvo.setTotalCost(cvo.getPrice().multiply(cvo.getTotalNum()));
|
||||
cvo.setMaterialCost(ccost.getMaterialCost());
|
||||
cvo.setTotalMaterialCost(ccost.getMaterialCost().multiply(cvo.getTotalNum()));
|
||||
cvo.setPaintCost(ccost.getPaintCost());
|
||||
cvo.setTotalPaintCost(ccost.getPaintCost().multiply(cvo.getTotalNum()));
|
||||
cvo.setStandardPieceRateSalary(ccost.getPieceRateSalary().multiply(cvo.getTotalNum()));
|
||||
cvo.setTotalStandardPieceRateSalary(ccost.getPieceRateSalary());
|
||||
cvo.setAuxiliaryManufacturingCost(ccost.getAuxiliaryManufacturingCost());
|
||||
cvo.setTotalAuxiliaryManufacturingCost(ccost.getAuxiliaryManufacturingCost().multiply(cvo.getTotalNum()));
|
||||
}
|
||||
pvo.getChildren().add(cvo);
|
||||
EBomParentEntity cparent = ebomService.getParent(child.getMaterialNo());
|
||||
if (Objects.nonNull(cparent)) {
|
||||
buildMultilayerChildren(cparent.getRowId(), cvo, materials, datas);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private BomCostMultilayerVO buildEBomCostMultilayerVO() {
|
||||
BomCostMultilayerVO vo = new BomCostMultilayerVO();
|
||||
if (RandomUtil.randomInt(0, 10) >= 7) {
|
||||
|
|
|
|||
|
|
@ -54,4 +54,8 @@ public class SteelsCostConfigService extends ServiceImpl<SteelsCostConfigMapper,
|
|||
updateBatchById(forUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
public SteelsCostConfigEntity getCost(String name) {
|
||||
return lambdaQuery().eq(SteelsCostConfigEntity::getName, name).one();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ public class VirtualWorkingService extends ServiceImpl<VirtualWorkingMapper, Vir
|
|||
@Resource
|
||||
private WorkingTypeService workingTypeService;
|
||||
|
||||
@Resource
|
||||
private TechnologyConfigService technologyConfigService;
|
||||
|
||||
@Transactional()
|
||||
public void save(List<VirtualWorking> list) {
|
||||
if (CollectionUtil.isEmpty(list)) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package com.nflg.product.technology.util;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.nflg.product.base.core.exception.NflgBusinessException;
|
||||
import com.nflg.product.technology.pojo.dto.EBomCostCacheDTO;
|
||||
import nflg.product.common.constant.STATE;
|
||||
|
||||
public class JsonUtil {
|
||||
|
||||
private static final ObjectMapper objectmapper = new ObjectMapper();
|
||||
|
||||
public static <T> T fromJson(String json, Class<T> clazz) {
|
||||
try {
|
||||
return objectmapper.readValue(json, clazz);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new NflgBusinessException(STATE.BusinessError, "JSON反序列化失败");
|
||||
}
|
||||
}
|
||||
|
||||
public static String toJson(EBomCostCacheDTO cdto) {
|
||||
try {
|
||||
return objectmapper.writeValueAsString(cdto);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new NflgBusinessException(STATE.BusinessError, "JSON序列化失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -62,12 +62,13 @@
|
|||
<logger name="org.springframework.web" level="WARN"/>
|
||||
<logger name="org.springframework.jdbc" level="WARN"/>
|
||||
<logger name="io.lettuce.core" level="WARN"/>
|
||||
<logger name="com.nflg.product" level="DEBUG"/>
|
||||
|
||||
<!-- 日志输出级别 -->
|
||||
<root level="ERROR">
|
||||
<appender-ref ref="ErrorFile" />
|
||||
</root>
|
||||
<root level="DEBUG">
|
||||
<root level="INFO">
|
||||
<appender-ref ref="Console" />
|
||||
<appender-ref ref="RollingFileAll" />
|
||||
</root>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
<?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.EBomChildMapper">
|
||||
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?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.EBomParentMapper">
|
||||
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?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.MaterialMainMapper">
|
||||
|
||||
<select id="getInfos" resultType="com.nflg.product.technology.pojo.dto.EBomDTO">
|
||||
select a.material_no AS 'materialNo',a.drawing_no AS 'drawingNo',a.material_desc AS 'materialDesc'
|
||||
,a.material_unit AS 'materialUnit',CONVERT(a.material_weight, DECIMAL(12,4)) AS 'unitWeight'
|
||||
,a.material_category_code AS 'materialCategoryCode',a.last_purchase_price AS 'lastPurchasePrice'
|
||||
,b.rel_category_code AS 'relCategoryCode'
|
||||
,b.category_name AS 'categoryName'
|
||||
from t_material_main a join t_material_category b on a.material_category_code=b.category_code
|
||||
where material_no in
|
||||
<foreach collection="materialNos" item="item" open="(" close=")" separator=",">
|
||||
#{item}
|
||||
</foreach>
|
||||
</select>
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue