taikai2312/ic/src/public/nc/vo/ic/onhand/define/ICBillPickResults.java

497 lines
20 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package nc.vo.ic.onhand.define;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import nc.bs.ic.pub.env.ICBSContext;
import nc.itf.scmpub.reference.uap.group.SysInitGroupQuery;
import nc.vo.ic.general.define.ICBillBodyVO;
import nc.vo.ic.location.ICLocationVO;
import nc.vo.ic.material.define.InvCalBodyVO;
import nc.vo.ic.onhand.entity.OnhandDimVO;
import nc.vo.ic.onhand.entity.OnhandSNVO;
import nc.vo.ic.onhand.pub.OnhandVOTools;
import nc.vo.ic.pub.define.ICPubMetaNameConst;
import nc.vo.ic.pub.lang.OnhandRes;
import nc.vo.ic.pub.util.CollectionUtils;
import nc.vo.ic.pub.util.NCBaseTypeUtils;
import nc.vo.ic.pub.util.StringUtil;
import nc.vo.ic.pub.util.VOEntityUtil;
import nc.vo.ic.pub.util.ValueCheckUtil;
import nc.vo.pub.VOStatus;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.scale.ScaleUtils;
import nc.vo.pubapp.util.VORowNoUtils;
/**
* <p>
* <b>单据现存量捡货结果</b>
*
* @author yangb
* @version 本版本号
* @time 2010-4-16 下午01:05:00
* @since 上一版本号
*/
public class ICBillPickResults implements Serializable {
private static final long serialVersionUID = 201008201108000513L;
// 捡货后的单据表体VO
private ICBillBodyVO[] curbillbodyvos;
private Map<String, ICBillBodyVO[]> mapbodyvos;
// 原始表体的自然序号与捡货结果的对应关系
private transient Map<String, OnhandBalanceResult<ICBillOnhandReq>> maponhandbalanceresult;
// 捡货前的单据表体VO
private ICBillBodyVO[] originbillbodyvos;
// 捡货后结果
private List<OnhandBalanceResult<ICBillOnhandReq>> pickresults;
// 精度的工具类
private transient ScaleUtils scale;
// 标识是否为预留拣货
private boolean isResPick = false;
/**
* @return the isResPick
*/
public boolean isResPick() {
return isResPick;
}
/**
* @param isResPick the isResPick to set
*/
public void setResPick(boolean isResPick) {
this.isResPick = isResPick;
}
/**
* OnhandBalanceResult 的构造子
*/
public ICBillPickResults(boolean isResPick) {
this.isResPick = isResPick;
}
/**
* ICBillPickResults 的构造子
*/
public ICBillPickResults(
List<OnhandBalanceResult<ICBillOnhandReq>> pickresults,
ICBillBodyVO[] originbodyvos) {
this.pickresults = pickresults;
this.originbillbodyvos = originbodyvos;
}
/**
* 获取捡货后的表体ICBillBodyVOs
*/
public ICBillBodyVO[] getPickBodys() {
if (this.curbillbodyvos != null) {
return this.curbillbodyvos;
}
List<ICBillBodyVO> retlist = new ArrayList<ICBillBodyVO>();
ICBillBodyVO[] bodyvos = null;
for (int i = 0; i < this.originbillbodyvos.length; i++) {
bodyvos = this.getPickBodys(i);
if (bodyvos == null || bodyvos.length <= 0) {
// 如果没有拣到返回originvo并在备注上提示现存量不足
this.originbillbodyvos[i].setVnotebody(OnhandRes.getOnhandErro());
retlist.add(this.originbillbodyvos[i]);
continue;
}
// 如果拣货后有对应的数据根据拣货的结果处理拣货行bodyvos上的备注
this.processBodyNote(this.originbillbodyvos[i], bodyvos);
CollectionUtils.addArrayToList(retlist, bodyvos);
}
this.curbillbodyvos = CollectionUtils.listToArray(retlist);
// 捡货后表体数据整理,如换算率 批次 相关
this.processBodyData(this.curbillbodyvos);
return this.curbillbodyvos;
}
/**
* 处理表体备注,如果原始行应发数量大于对应拣货结果总结存,报现存量不足
*
* @param orivo 原始行
* @param curvos 拣货结果
*/
private void processBodyNote(ICBillBodyVO orivo, ICBillBodyVO[] curvos) {
UFDouble shouldNum = orivo.getNshouldnum();
UFDouble shouldasNum = orivo.getNshouldassistnum();
UFDouble totalNum = UFDouble.ZERO_DBL;
UFDouble totalasNum = UFDouble.ZERO_DBL;
for (ICBillBodyVO curvo : curvos) {
totalNum = NCBaseTypeUtils.add(totalNum, curvo.getNnum());
totalasNum = NCBaseTypeUtils.add(totalasNum, curvo.getNassistnum());
}
if (NCBaseTypeUtils.isGtZero(NCBaseTypeUtils.sub(shouldNum, totalNum))
|| NCBaseTypeUtils.isGtZero(NCBaseTypeUtils
.sub(shouldasNum, totalasNum))) {
for (ICBillBodyVO curvo : curvos) {
if (StringUtil.isSEmptyOrNull(curvo.getVnotebody())) {
curvo.setVnotebody(OnhandRes.getOnhandErro());
}
}
}
}
/**
* 获取捡货后的表体ICBillBodyVO
*/
public ICBillBodyVO[] getPickBodys(int row) {
if (this.mapbodyvos != null
&& this.mapbodyvos.containsKey(String.valueOf(row))) {
return this.mapbodyvos.get(String.valueOf(row));
}
OnhandBalanceResult<ICBillOnhandReq> result =
this.getMapResults().get(String.valueOf(row));
if (result == null) {
return null;
}
List<ICBillBodyVO> retlist = new ArrayList<ICBillBodyVO>();
if (result.getResults() == null || result.getResults().size() <= 0) {
ICBillBodyVO[] vos =
(ICBillBodyVO[]) Array.newInstance(result.getOnhandReq().getBodyvo()
.getClass(), 1);
vos[0] = result.getOnhandReq().getBodyvo();
return vos;
}
ICBillBodyVO bodyvo =
(ICBillBodyVO) result.getOnhandReq().getBodyvo().clone();
result.setResults(prepare(result.getResults(), bodyvo));
// 先按现存量维度分组,不包括货位+对应入库单行ID
Map<String, List<BalanceOnhandRes>> mapgroup =
this.groupBalanceOnhandRes(result.getResults());
int rowCount = 0;
for (List<BalanceOnhandRes> lbalances : mapgroup.values()) {
rowCount = rowCount + 1;
if (retlist.size() > 0) {
bodyvo = (ICBillBodyVO) result.getOnhandReq().getBodyvo().clone();
bodyvo.setStatus(VOStatus.NEW);
bodyvo.setCgeneralbid(null);
bodyvo.setCrowno(null);
bodyvo.setPseudoColumn(bodyvo.getPseudoColumn());
// bodyvo.setNshouldnum(null);
// bodyvo.setNshouldassistnum(null);
}
// 因为存在实发数量拣货,需要
this.synBodyData(bodyvo, lbalances.get(0));
ICLocationVO[] locs = null;
List<ICLocationVO> listlocs = new ArrayList<ICLocationVO>();
// 因为存在实发数量拣货,需清除原有的数量
bodyvo.setNnum(null);
bodyvo.setNassistnum(null);
for (BalanceOnhandRes balance : lbalances) {
UFDouble nnum =
NCBaseTypeUtils.add(bodyvo.getNnum(), balance.getNnum());
UFDouble nassistnum =
NCBaseTypeUtils.add(bodyvo.getNassistnum(), balance.getNastnum());
bodyvo.setNnum(this.getScale()
.adjustNumScale(nnum, bodyvo.getCunitid()));
bodyvo.setNassistnum(this.getScale().adjustNumScale(nassistnum,
bodyvo.getCastunitid()));
// 不处理毛重
/*bodyvo.setNgrossnum(NCBaseTypeUtils.add(bodyvo.getNgrossnum(),
balance.getNgrossnum()));*/
locs = balance.getLocatonVO(bodyvo);
if (locs == null || locs.length <= 0) {
continue;
}
CollectionUtils.addArrayToList(listlocs, locs);
}
// 拆行的话需要清空拆出来的行的应发数量
if (rowCount > 1) {
// bodyvo.setNshouldnum(null);
// bodyvo.setNshouldassistnum(null);
// 78--2025年4月9日19点11分--sdlizheng--实发传输到应发,最后一行做合计处理--start
bodyvo.setNshouldnum(retlist.get(0).getNshouldnum());
bodyvo.setNshouldassistnum(retlist.get(0).getNshouldassistnum());
// 78--2025年4月9日19点11分--sdlizheng--实发传输到应发,最后一行做合计处理--start
}
if (listlocs.size() > 0) {
// 清除重复的孙表数据
// listlocs = clearDuplicatelvo(bodyvo, listlocs);
// 处理修改时 带有孙表的自动拣货 重复出库问题 因为拣货把删除的数据给覆盖了 这里补充上
ICLocationVO[] originLocationVos = bodyvo.getLocationVOs();
if (originLocationVos != null && originLocationVos.length > 0) {
for (ICLocationVO lvo : originLocationVos) {
lvo.setStatus(VOStatus.DELETED);
listlocs.add(lvo);
}
}
// 处理修改时 带有孙表的自动拣货 重复出库问题 因为拣货把删除的数据给覆盖了 这里补充上
bodyvo.setLocationVOs(listlocs.toArray((ICLocationVO[]) Array
.newInstance(listlocs.get(0).getClass(), listlocs.size())));
// 检出
this.reCalculateNum(bodyvo);
}
retlist.add(bodyvo);
}
ICBillBodyVO[] retvos = CollectionUtils.listToArray(retlist);
if (this.mapbodyvos == null) {
this.mapbodyvos = new HashMap<String, ICBillBodyVO[]>();
}
this.mapbodyvos.put(String.valueOf(row), retvos);
return retvos;
}
/**
* 预处理拣货结果,序列号拣货的优先,然后在不满足需求的前提下再加上全捡的部分结果
*
* @param resList
* @param bodyvo
*/
private List<BalanceOnhandRes> prepare(List<BalanceOnhandRes> resList, ICBillBodyVO bodyvo) {
List<BalanceOnhandRes> ret = new ArrayList<BalanceOnhandRes>();
String snField = SysInitGroupQuery.isSNEnabled() ? ICPubMetaNameConst.PK_SERIALCODE : OnhandSNVO.VSNCODE;
// 行上没有序列号单位,认为不是序列号管理,不做处理
Map<String, InvCalBodyVO> mapInvvos = new ICBSContext().getInvInfo().getMapInvCalBodyVO(bodyvo.getPk_org(),
new String[]{bodyvo.getCmaterialvid()});
if (mapInvvos == null) {
return resList;
}
InvCalBodyVO invvo = mapInvvos.get(bodyvo.getCmaterialvid());
if (invvo == null || !ValueCheckUtil.isTrue(invvo.getSerialmanaflag())) {
return resList;
}
// if( bodyvo.getCSnunitid() == null) {
// return resList;
// }
// 序列号需求数量的字段
String snNumReqField = invvo.getSernumunit() != null && invvo.getSernumunit().equals(bodyvo.getCastunitid()) ?
ICPubMetaNameConst.NSHOULDASSISTNUM : ICPubMetaNameConst.NSHOULDNUM;
// 获取序列号拣货捡出的序列号集合
Set<String> bySNValues = new HashSet<String>();
// 第一次循环,找出序列号拣货捡出的所有序列号
for (BalanceOnhandRes res : resList) {
if (res.isBySN()) {
List<OnhandSNVO> locs = res.getListsnvo();
if (locs == null || locs.size() <= 0) {
continue;
}
CollectionUtils.addArrayToSet(bySNValues,
(VOEntityUtil.getVOsValueSet(locs.toArray(new OnhandSNVO[0]), snField)).toArray(new String[0]));
}
}
int needNum = ((UFDouble) bodyvo.getAttributeValue(snNumReqField)).intValue() - bySNValues.size();
ICLocationVO[] blvos = getLVOsBySNField(bodyvo, snField);
Set bsns = VOEntityUtil.getVOsValueSet(blvos, snField);
int needsnNum = ((UFDouble) bodyvo.getAttributeValue(snNumReqField)).intValue() - blvos.length;
// 第二次循环,对于非序列号拣货捡出的结果,移除其中已有的序列号结果,如果最终结果为空,则移除这条结果
for (BalanceOnhandRes res : resList) {
if (res.isBySN()) {
ret.add(res);
} else {
List<OnhandSNVO> locs = res.getListsnvo();
if (locs == null || locs.size() <= 0) {
ret.add(res);
continue;
}
List<OnhandSNVO> list = new ArrayList<OnhandSNVO>();
String[] lpks = VOEntityUtil.getVOsValuesNotDel(blvos, ICLocationVO.PK_SERIALCODE, String.class);
for (OnhandSNVO lvo : locs) {
if (needsnNum > 0) {
if (lpks != null) {
if (lvo.getAttributeValue(snField) != null && !Arrays.asList(lpks).contains(lvo.getPk_serialcode())) {
list.add(lvo);
needsnNum--;
}
} else {
if (lvo.getAttributeValue(snField) != null) {
list.add(lvo);
needsnNum--;
}
}
}
}
if (list.size() > 0) {
res.setListsnvo(list);
// 根据孙表数量计算表体数量
UFDouble[] sums = VOEntityUtil.sumVOsFieldValuesNotDel(list.toArray(new OnhandSNVO[0]),
new String[]{OnhandSNVO.NONHANDNUM});
res.setNastnum(new UFDouble(list.size()));
res.setNnum(sums[0]);
ret.add(res);
} else {
res.setListsnvo(null);
}
}
}
return ret;
}
/**
* 有的场景会向后台传序列号的编码,不传序列号的主键,这个时候认为没有传孙表数据
*
* @param bodyvo
* @param snField
* @return
*/
private ICLocationVO[] getLVOsBySNField(ICBillBodyVO bodyvo, String snField) {
if (bodyvo.getLocationVOs() == null) {
return new ICLocationVO[]{};
}
List<ICLocationVO> list = new ArrayList<ICLocationVO>();
for (ICLocationVO lvo : bodyvo.getLocationVOs()) {
if (lvo.getAttributeValue(snField) != null && lvo.getStatus() != VOStatus.DELETED) {
list.add(lvo);
}
}
return list.toArray(new ICLocationVO[0]);
}
private void reCalculateNum(ICBillBodyVO bodyvo) {
ICLocationVO[] locs = bodyvo.getLocationVOs();
String[] vsns = VOEntityUtil.getVOsValuesNotDel(locs, ICLocationVO.VSERIALCODE, String.class);
if (StringUtil.isSEmptyOrNullForAll(vsns)) {
return;
}
// 根据孙表数量计算表体数量
UFDouble[] sums = VOEntityUtil.sumVOsFieldValuesNotDel(locs, new String[]{ICLocationVO.NNUM, ICLocationVO.NASSISTNUM});
bodyvo.setNnum(sums[0]);
bodyvo.setNassistnum(sums[1]);
}
/**
*
*/
private Map<String, OnhandBalanceResult<ICBillOnhandReq>> getMapResults() {
if (this.maponhandbalanceresult == null) {
this.maponhandbalanceresult =
new HashMap<String, OnhandBalanceResult<ICBillOnhandReq>>();
if (this.pickresults != null && this.pickresults.size() > 0) {
for (OnhandBalanceResult<ICBillOnhandReq> result : this.pickresults) {
if (result.getOnhandReq() != null) {
this.maponhandbalanceresult.put(result.getOnhandReq().getRowno(),
result);
}
}
}
}
return this.maponhandbalanceresult;
}
/**
* 按现存量维度分组+对应入库单表体ID不包括货位
*/
private Map<String, List<BalanceOnhandRes>> groupBalanceOnhandRes(
List<BalanceOnhandRes> lbalances) {
String key = null;
Map<String, List<BalanceOnhandRes>> mapgroup =
new HashMap<String, List<BalanceOnhandRes>>();
List<BalanceOnhandRes> lbalance = null;
for (BalanceOnhandRes balance : lbalances) {
key = OnhandVOTools.getAstDimContentKey(balance.getOnhanddimvo());
key = key + balance.getCgeneralbid() + balance.getOnhanddimvo().getClocationid();
lbalance = mapgroup.get(key);
if (lbalance == null) {
lbalance = new ArrayList<BalanceOnhandRes>();
mapgroup.put(key, lbalance);
}
lbalance.add(balance);
}
return mapgroup;
}
/**
* 捡货后表体数据整理,如换算率 批次 相关
*/
private ICBillBodyVO[] processBodyData(ICBillBodyVO[] bodyvos) {
if (bodyvos == null || bodyvos.length <= 0) {
return bodyvos;
}
// 处理行号
VORowNoUtils.setVOsRowNoByRule(bodyvos, ICPubMetaNameConst.CROWNO);
// ScaleUtils scaleutils = ScaleUtils.getScaleUtilAtBS();
// TODO 精度未处理 等待公共方法
ICBSContext context = new ICBSContext();
for (int i = 0; i < bodyvos.length; i++) {
UFDouble ncostprice = (bodyvos[i].getNcostprice() == null) ? UFDouble.ZERO_DBL : bodyvos[i].getNcostprice();
bodyvos[i].setNcostmny(NCBaseTypeUtils.mult(ncostprice,
bodyvos[i].getNnum()));
bodyvos[i].setNplannedmny(NCBaseTypeUtils.mult(
bodyvos[i].getNplannedprice(), bodyvos[i].getNnum()));
// 实发数量和主数量都为空时,不补业务日期
if (bodyvos[i].getNnum() == null && bodyvos[i].getNassistnum() == null) {
continue;
}
// 如果业务日期为空的话,补充 modify by guozhq
if (bodyvos[i].getDbizdate() == null) {
bodyvos[i].setDbizdate(context.getBizDate());
}
}
return bodyvos;
}
/**
* 设置捡货后的货位数据
*/
// private void synLocData(ICBillBodyVO bodyvo,BalanceOnhandRes
// balance,ICLocationVO locvo) {
// locvo.setCgeneralbid(bodyvo.getCgeneralbid());
// locvo.setPk_group(bodyvo.getPk_group());
// locvo.setCorpoid(bodyvo.getCorpoid());
// locvo.setCorpvid(bodyvo.getCorpvid());
// locvo.setNinspacenum(balance.getNnum());
// locvo.setNinspaceassistnum(balance.getNastnum());
// locvo.setNingrossnum(balance.getNgrossnum());
// }
/**
* 设置捡货后的表体数据
*/
private void synBodyData(ICBillBodyVO bodyvo, BalanceOnhandRes res) {
if (bodyvo == null || res == null) {
return;
}
// 现存量维度的单位和单据界面的辅单位不能同步
String[] onhandDims = StringUtil.getArrayWithOutStr(OnhandDimVO.getDimContentFields(),
OnhandDimVO.CASTUNITID);
OnhandDimVO handdimvo = res.getOnhanddimvo();
for (String field : OnhandDimVO.getDimContentFields()) {
if (field.equals(OnhandDimVO.VCHANGERATE)) {
String vchangerate = handdimvo.getVchangerate();
// 如果换算率不记结存,不同步换算率
if (StringUtil.isSEmptyOrNull(vchangerate)) {
onhandDims =
StringUtil
.getArrayWithOutStr(onhandDims, OnhandDimVO.VCHANGERATE);
}
break;
}
}
VOEntityUtil.copyVOByVO(bodyvo, onhandDims,
res.getOnhanddimvo(), onhandDims);
bodyvo.setCcorrespondtype(res.getCbilltype());
bodyvo.setCcorrespondtranstype(res.getVtrantypecode());
bodyvo.setCcorrespondcode(res.getVbillcode());
bodyvo.setCcorrespondhid(res.getCgeneralhid());
bodyvo.setCcorrespondbid(res.getCgeneralbid());
bodyvo.setCcorrespondrowno(res.getCrowno());
}
private ScaleUtils getScale() {
if (this.scale == null) {
this.scale = ScaleUtils.getScaleUtilAtBS();
}
return this.scale;
}
}