Browse Source

调试修改账套

koul 4 years ago
parent
commit
72a4514a5b

+ 217 - 6
src/main/java/com/uas/eis/dao/BaseDao.java

@@ -4,13 +4,10 @@ import java.sql.CallableStatement;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 import com.uas.eis.entity.Configs;
+import com.uas.eis.entity.Employee;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.DataAccessException;
 import org.springframework.dao.EmptyResultDataAccessException;
@@ -261,7 +258,68 @@ public class BaseDao{
 		}
 		return null;
 	}
-	
+
+	/**
+	 * 多个字段,<=1条结果
+	 *
+	 * @param tableName
+	 *            对应要查询的表
+	 * @param fields
+	 *            要查询的字段集合
+	 * @param condition
+	 *            查询条件
+	 * @return fields对应的数据
+	 */
+	public Object[] getFieldsDataByCondition(String tableName, String[] fields, String condition) {
+		StringBuffer sql = new StringBuffer("SELECT ");
+		sql.append(BaseUtil.parseArray2Str(fields, ","));
+		sql.append(" FROM ");
+		sql.append(tableName);
+		sql.append(" WHERE ");
+		sql.append(condition);
+		List<Map<String, Object>> list = getJdbcTemplate().queryForList(sql.toString());
+		Iterator<Map<String, Object>> iter = list.iterator();
+		int length = fields.length;
+		Object[] results = new Object[length];
+		Object value = null;
+		if (iter.hasNext()) {
+			Map<String, Object> m = iter.next();
+			for (int i = 0; i < length; i++) {
+				String upperField = fields[i].toUpperCase();
+				if (upperField.indexOf(" AS ") > 0) {
+					upperField = upperField.split(" AS ")[1].trim();
+				}
+				value = m.get(upperField);
+				if (value != null && value.getClass().getSimpleName().toUpperCase().equals("TIMESTAMP")) {
+					Timestamp time = (Timestamp) value;
+					try {
+						value = DateUtil.parseDateToString(new Date(time.getTime()), Constant.YMD_HMS);
+					} catch (Exception e) {
+						e.printStackTrace();
+					}
+				}
+				results[i] = value;
+			}
+			return results;
+		}
+		return null;
+	}
+
+
+	/**
+	 * 查询结果集
+	 *
+	 * @param sql
+	 *            查询语句
+	 * @param arg
+	 *            参数
+	 */
+	public SqlRowList queryForRowSet(String sql, Object arg) {
+		SqlRowList rs = new SqlRowList();
+		rs.setResultList(getJdbcTemplate().queryForList(sql, arg));
+		return rs;
+	}
+
 	/**
 	 * 多个字段,多条结果
 	 * 
@@ -681,4 +739,157 @@ public class BaseDao{
 		return 0;
 	}
 
+	public String getBatchCode(String caller, String field) {
+		SqlRowList rs = queryForRowSet("select ds_inorout from DOCUMENTSETUP where ds_table=?", caller);
+		String finalCode = null;
+		if (rs.next()) {
+			String Code = rs.getObject("ds_inorout").toString();
+			if (Code.equals("IN") || Code.equals("-OUT")) {
+				finalCode = sGetMaxNumber("ProdIOut", 2);
+			}
+		}
+		return finalCode;
+	}
+
+	public boolean isProdIn(String caller){
+		boolean isProdIn=false;
+		SqlRowList rs = queryForRowSet("select ds_inorout from DOCUMENTSETUP where ds_table=?", caller);
+		if (rs.next()) {
+			isProdIn= "IN".equals(rs.getString(1)) || "-OUT".equals(rs.getString(1));
+		}
+		return isProdIn;
+	}
+
+	/**
+	 * 获取入库单批号
+	 */
+	public String getBatchcode(String caller) {
+		if (isProdIn(caller)) {
+			/**
+			 * procedure utl_rseq
+			 *
+			 * @param seq_name
+			 *            序列名,支持自动创建,格式{@code seq_name}_rseq
+			 * @param seq_rule
+			 *            {prefix}/{time format}/{length of pad and nextval}
+			 * @return seq_val
+			 */
+			return callProcedure("utl_rseq", "BatchCode", "/yyMMdd/5");
+		}
+		return null;
+	}
+
+	/**
+	 * 查询结果集
+	 *
+	 * @param sql
+	 *            查询语句
+	 * @param args
+	 *            参数
+	 */
+	public SqlRowList queryForRowSet(String sql, Object... args) {
+		SqlRowList rs = new SqlRowList();
+		rs.setResultList(getJdbcTemplate().queryForList(sql, args));
+		return rs;
+	}
+
+	/**
+	 * 取指定系统参数设置
+	 *
+	 * @param code
+	 */
+	public String getDBSetting(String caller,String code) {
+		int count = getCount("select count(1) from configs where caller='" + caller + "' and code='" + code + "'");
+		if (count>0) {
+			Configs config = getJdbcTemplate().queryForObject("select *  from configs where caller=? and code=?",
+					new BeanPropertyRowMapper<Configs>(Configs.class), caller, code);
+			if (config != null) {
+				return config.getData();
+			}
+		}
+		return null;
+	}
+
+	public boolean isIn(String caller) {
+		SqlRowList rs = queryForRowSet("select ds_inorout from DOCUMENTSETUP where ds_table=?", caller);
+		if (rs.next()) {
+			return "IN".equals(rs.getString(1)) || "-OUT".equals(rs.getString(1));
+		}
+		return false;
+	}
+
+	public boolean isOut(String caller) {
+		SqlRowList rs = queryForRowSet("select ds_inorout from DOCUMENTSETUP where ds_table=?", caller);
+		if (rs.next()) {
+			return "-IN".equals(rs.getString(1)) || "OUT".equals(rs.getString(1));
+		}
+		return false;
+	}
+
+	public Double getSummaryByField(String tablename, String summaryField, String condition) {
+		SqlRowList rs = queryForRowSet("SELECT sum(nvl(" + summaryField + ",0)) FROM " + tablename + " WHERE " + condition);
+		if (rs.next()) {
+			return rs.getGeneralDouble(1, 6);
+		}
+		return 0.0;
+	}
+
+	public Map<String, Object> changeKeyToLowerCase(Map<String, Object> map) {
+		Map<String, Object> map1 = new HashMap<String, Object>();
+		Iterator<String> it = map.keySet().iterator();
+		while (it.hasNext()) {
+			String key = it.next();
+			map1.put(key.toLowerCase(), map.get(key));
+		}
+		return map1;
+	}
+
+	public List<Map<String, Object>> changeKeyToLowerCase(List<Map<String, Object>> list) {
+		Map<String, Object> map = new HashMap<String, Object>();
+		List<Map<String, Object>> datas = new ArrayList<Map<String, Object>>();
+		Iterator<Map<String, Object>> iter = list.iterator();
+		map = null;
+		while (iter.hasNext()) {
+			Map<String, Object> map1 = new HashMap<String, Object>();
+			map = iter.next();
+			Iterator<String> it = map.keySet().iterator();
+			while (it.hasNext()) {
+				String key = it.next();
+				map1.put(key.toLowerCase(), map.get(key));
+			}
+			datas.add(map1);
+		}
+		return datas;
+	}
+
+	/**
+	 * 根据物料中的有效期天数更新有效期止
+	 */
+	public void getEndDate(String caller, Object id) {
+		SqlRowList rs = queryForRowSet("select ds_inorout from DOCUMENTSETUP where ds_table=?", caller);
+		if (rs.next()) {
+			String Code = rs.getObject("ds_inorout").toString();
+			if (Code.equals("IN") || Code.equals("-OUT")) {
+				execute("update prodiodetail set pd_replydate=pd_prodmadedate + (select nvl(pr_validdays,0) from product where  pd_prodcode=pr_code) where pd_piid=? and pd_prodmadedate is not null",
+						id);
+			}
+		}
+	}
+
+	/**
+	 * 修改单据为已审核(包括审核人+审核日期)
+	 *
+	 * @param tableName
+	 * @param condition
+	 * @param statusField
+	 * @param statusCodeField
+	 * @param auditdateField
+	 * @param auditorField
+	 */
+	public void audit(String tableName, String condition, String statusField, String statusCodeField, String auditdateField,
+					  String auditorField,Employee employee) {
+		updateByCondition(tableName, statusCodeField + "='AUDITED'," + statusField + "='已审核',"
+				+ auditdateField + "=" + DateUtil.parseDateToOracleString(Constant.YMD_HMS, new Date()) + "," + auditorField + "='"+employee.getEm_name()+"'", condition);
+	}
+
 }

+ 9 - 0
src/main/java/com/uas/eis/entity/MakeMaterial.java

@@ -53,6 +53,15 @@ public class MakeMaterial {
     private String mesPwd;
     @JSONField(name = "flag")
     private int flag;
+    private int id;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
 
     public int getErpid() {
         return erpid;

+ 1 - 1
src/main/java/com/uas/eis/service/Impl/ERPServiceImpl.java

@@ -69,7 +69,7 @@ public class ERPServiceImpl implements ERPService {
         Map<Object, Object> store = BaseUtil.parseFormStoreToMap(data);
         VerifyApply verifyApply = baseDao.getJdbcTemplate().queryForObject("select va_id,va_mescode,va_code,to_char" +
                         "(va_date,'yyyy-MM-dd HH24:mi:ss') va_date,va_vendcode,va_vendname,va_currency,va_rate,va_paymentscode,va_payments,va_transport,va_sendcode,va_emcode,va_emname,va_departmentcode,va_department,va_recorder,nvl(va_cop,'BYT') va_cop,va_remark,va_ancode,va_factory,0 version,va_type,va_pucode,case when nvl(va_pucode,' ')=' ' then 0 else (select pu_id from purchase " +
-                        "where pu_code=va_pucode) end pu_id,va_status,1 posted,to_char(va_auditdate,'yyyy-MM-dd HH24:mi:ss') va_auditdate,va_auditman from VerifyApply where va_statuscode='AUDITED' and va_id=?",
+                        "where pu_code=va_pucode) end pu_id,va_status,1 posted,to_char(va_auditdate,'yyyy-MM-dd HH24:mi:ss') va_auditdate,va_auditman from VerifyApply where va_id=?",
                 new BeanPropertyRowMapper<VerifyApply>(VerifyApply.class), store.get("va_id"));
         SqlRowList rs = baseDao.queryForRowSet("select case when pr_kh_user='柏英特' or nvl(pr_kh_user,' ')=' ' then 'BYT' else nvl(cu_mescode,cu_code) end cu_code,cu_name from verifyapplydetail left join product on vad_prodcode=pr_code left join customer on cu_shortname=pr_kh_user where vad_vaid=114192 order by vad_detno");
         if (rs.next()){

+ 2219 - 11
src/main/java/com/uas/eis/service/Impl/MESServiceImpl.java

@@ -15,6 +15,7 @@ import com.uas.eis.utils.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
@@ -70,11 +71,11 @@ public class MESServiceImpl implements MESService {
             if ("".equals(mesCode)){
                 return ApiResponse.failRsp("10011",request.getHeader("RequestId"),"ERP单据编号不能为空!");
             }
-            int count = baseDao.getCountByCondition("verifyApply", "va_statuscode='AUDITED' and va_code='" + mesCode + "'");
+            int count = baseDao.getCountByCondition("verifyApply", "va_statuscode='AUDITED' and va_mescode='" + mesCode + "'");
             if (count<1){
                 return ApiResponse.failRsp("10012",request.getHeader("RequestId"),"单据未审核或不存在,请确认!");
             }
-            vaid = baseDao.getFieldDataByCondition("verifyApply", "va_id", "va_statuscode='AUDITED' and va_code='" + mesCode + "'");
+            vaid = baseDao.getFieldDataByCondition("verifyApply", "va_id", "va_statuscode='AUDITED' and va_mescode='" + mesCode + "'");
             int count1 = baseDao.getCount("select count(1) from VerifyApplyDetail where nvl(vad_pucode,' ')<>' ' and " +
                     "vad_vaid=" + vaid);
             if (count1>0){
@@ -170,6 +171,11 @@ public class MESServiceImpl implements MESService {
         // 修改收料状态
         baseDao.updateByCondition("VerifyApplyDetail", "vad_yqty=vad_qty", "vad_vaid=" + vaid);
         baseDao.updateByCondition("VerifyApply", "va_turnstatuscode='TURNIN',va_turnstatus='已入库'", "va_id=" + vaid);
+        String s = postProdInOut(piid, caller, employee);
+        System.err.println(s);
+        if (s!=null){
+            return ApiResponse.successRsp("0",request.getHeader("RequestId"),type+":"+key.getCode()+",过账失败,请在ERP重新过账!");
+        }
         return ApiResponse.successRsp("0",request.getHeader("RequestId"),type+":"+key.getCode()+",请在ERP查看!");
     }
 
@@ -377,7 +383,7 @@ public class MESServiceImpl implements MESService {
             }
             String qty = StringUtil.nvl(object.get("FAuxQtyMust"), "");
             if ("".equals(qty)){
-                return ApiResponse.failRsp("10032",request.getHeader("RequestId"),"实出数量数量不能为空!");
+                return ApiResponse.failRsp("10032",request.getHeader("RequestId"),"实出数量不能为空!");
             }
             String fnote = StringUtil.nvl(object.get("Fnote"), "");
             Map<Object, Object> map1 = JSONUtil.toMap(StringUtil.valueOf(object.get("FDCStockID1")));
@@ -457,6 +463,8 @@ public class MESServiceImpl implements MESService {
         }*/
 
         JSONArray array = data.get("detail");
+        Object[] warehouses=null;
+        Object[] warehouses2=null;
         int detno=1;
         for (int i = 0; i <array.size(); i++) {
             JSONObject object = JSON.parseObject(StringUtil.nvl(array.get(i), "{}"));
@@ -479,7 +487,7 @@ public class MESServiceImpl implements MESService {
             if (count<=0){
                 return ApiResponse.failRsp("10044",request.getHeader("RequestId"),"MES仓库编号在ERP没有对应关系,请联系管理员新增!");
             }
-            Object[] warehouses = baseDao.getFieldsDataByCondition("customtabledetail left join customtable on cd_ctid=ct_id left join Warehouse on cd_varchar50_3=wh_code", "cd_varchar50_3,wh_description", "cd_varchar50_1='" + whcode + "'");
+            warehouses = baseDao.getFieldsDataByCondition("customtabledetail left join customtable on cd_ctid=ct_id left join Warehouse on cd_varchar50_3=wh_code", "cd_varchar50_3,wh_description", "cd_varchar50_1='" + whcode + "'");
             String fSourceInterId = StringUtil.nvl(object.get("FSourceInterId"), "");
             String ficmoBillNo = StringUtil.nvl(object.get("FICMOBillNo"), "");
             Map<Object, Object> map2 = JSONUtil.toMap(StringUtil.nvl(object.get("FSCStockID2"), "{}"));
@@ -494,7 +502,7 @@ public class MESServiceImpl implements MESService {
             if (count2<=0){
                 return ApiResponse.failRsp("10044",request.getHeader("RequestId"),"MES仓库编号在ERP没有对应关系,请联系管理员新增!");
             }
-            Object[] warehouses2 = baseDao.getFieldsDataByCondition("customtabledetail left join customtable on " +
+            warehouses2 = baseDao.getFieldsDataByCondition("customtabledetail left join customtable on " +
                     "cd_ctid=ct_id left join Warehouse on cd_varchar50_3=wh_code", "cd_varchar50_3,wh_description",
                     "cd_varchar50_1='" + whcode2 + "'");
 
@@ -502,9 +510,9 @@ public class MESServiceImpl implements MESService {
             Object mmdetno = baseDao.getFieldDataByCondition("MakeMaterial", "mm_detno", "mm_id in (" + lineId+")");
             if(bccode!=null) {
                 sqls.add("insert into prodiodetail (pd_id,pd_piid,pd_inoutno,pd_piclass,pd_pdno,pd_prodcode," +
-                        "pd_outqty,pd_whcode,pd_whname,pd_inwhcode,pd_inwhname) " +
+                        "pd_outqty,pd_whcode,pd_whname,pd_inwhcode,pd_inwhname,pd_macode,pd_madetno) " +
                         "values (PRODIODETAIL_SEQ.nextval," + bcpiid + ",'" + bccode + "','"+bcpiclass+"'," + detno + ",'" + itemNo +
-                        "'," + qty + ",'" + warehouses2[0] + "','" + warehouses2[1] + "','" + warehouses[0] + "','" + warehouses[1] + "')");
+                        "'," + qty + ",'" + warehouses2[0] + "','" + warehouses2[1] + "','" + warehouses[0] + "','" + warehouses[1] + "','"+ficmoBillNo+"',"+mmdetno+")");
             }
             sqls.add("insert into prodiodetail (pd_id,pd_piid,pd_inoutno,pd_piclass,pd_pdno,pd_prodcode," +
                     "pd_outqty,pd_whcode,pd_whname,pd_ordercode,pd_orderdetno) " +
@@ -512,6 +520,12 @@ public class MESServiceImpl implements MESService {
                     "'," + qty + ",'" + warehouses[0] + "','" + warehouses[1] + "','"+ficmoBillNo+"',"+mmdetno+")");
             detno++;
         }
+        if (warehouses2!=null){
+            sqls.add("update prodinout set pi_whcode='"+warehouses2[0]+"',pi_whname='"+warehouses2[1]+"' where " + "pi_id="+bcpiid);
+        }
+        if (warehouses!=null){
+            sqls.add("update prodinout set pi_purpose='"+warehouses[0]+"',pi_purposename='"+warehouses[1]+"' where pi_id="+bcpiid);
+        }
         baseDao.execute(sqls);
         return ApiResponse.successRsp("0",request.getHeader("RequestId"),"生产领料单:"+llcode+",拨出单:"+bccode+",请在ERP查看!");
     }
@@ -539,6 +553,8 @@ public class MESServiceImpl implements MESService {
                     "values ("+id+",'"+code+"','拨出单',to_date('"+jsonObject2.get("Fdate")+"','yyyy-MM-dd HH24:mi:ss')," +
                     "'UNPOST','未过账','"+map1.get("FNumber")+"','"+map1.get("FName")+"','"+map4.get("FNumber")+"','"+map4.get("FName")+"','ENTERING','在录入','"+map5.get("FName")+"',to_date('"+jsonObject2.get("Fdate")+"','yyyy-MM-dd HH24:mi:ss'),'UNPRINT','未打印','"+map3.get("FName")+"','库存转移')");
         }
+        Object[] warehouses=null;
+        Object[] warehouses2=null;
         JSONArray array = data.get("detail");
         int detno=1;
         for (int i = 0; i <array.size(); i++) {
@@ -563,7 +579,7 @@ public class MESServiceImpl implements MESService {
             if (count<=0){
                 return ApiResponse.failRsp("10054",request.getHeader("RequestId"),"MES仓库编号在ERP没有对应关系,请联系管理员新增!");
             }
-            Object[] warehouses = baseDao.getFieldsDataByCondition("customtabledetail left join customtable on cd_ctid=ct_id left join Warehouse on cd_varchar50_3=wh_code", "cd_varchar50_3,wh_description", "cd_varchar50_1='" + whcode + "'");
+            warehouses = baseDao.getFieldsDataByCondition("customtabledetail left join customtable on cd_ctid=ct_id left join Warehouse on cd_varchar50_3=wh_code", "cd_varchar50_3,wh_description", "cd_varchar50_1='" + whcode + "'");
             Map<Object, Object> map2 = JSONUtil.toMap(StringUtil.nvl(object.get("FSCStockID2"), "{}"));
             String whcode2 = StringUtil.nvl(map2.get("FNumber"), "");
             String whname2 = StringUtil.nvl(map2.get("FName"), "");
@@ -576,7 +592,7 @@ public class MESServiceImpl implements MESService {
             if (count2<=0){
                 return ApiResponse.failRsp("10074",request.getHeader("RequestId"),"MES仓库编号在ERP没有对应关系,请联系管理员新增!");
             }
-            Object[] warehouses2 = baseDao.getFieldsDataByCondition("customtabledetail left join customtable on " +
+            warehouses2 = baseDao.getFieldsDataByCondition("customtabledetail left join customtable on " +
                     "cd_ctid=ct_id left join Warehouse on cd_varchar50_3=wh_code", "cd_varchar50_3,wh_description",
                     "cd_varchar50_1='" + whcode2 + "'");
 
@@ -589,6 +605,12 @@ public class MESServiceImpl implements MESService {
                     "values (PRODIODETAIL_SEQ.nextval,"+id+",'"+code+"','拨出单',"+detno+",'"+itemNo+"',"+qty+",'"+warehouses[0]+"','"+warehouses[1]+"','"+warehouses2[0]+"','"+warehouses2[1]+"')");
             detno++;
         }
+        if (warehouses!=null){
+            sqls.add("update prodinout set pi_whcode='"+warehouses[0]+"',pi_whname='"+warehouses[1]+"' where pi_id="+id);
+        }
+        if (warehouses2!=null){
+            sqls.add("update prodinout set pi_purpose='"+warehouses2[0]+"',pi_purposename='"+warehouses2[1]+"' where pi_id="+id);
+        }
         baseDao.execute(sqls);
         return ApiResponse.successRsp("0",request.getHeader("RequestId"),"生产退料单:"+code+",请在ERP查看!");
     }
@@ -616,6 +638,8 @@ public class MESServiceImpl implements MESService {
                     "'UNPOST','未过账','"+map1.get("FNumber")+"','"+map1.get("FName")+"','"+map4.get("FNumber")+"','"+map4.get("FName")+"','ENTERING','在录入','"+map5.get("FName")+"',to_date('"+jsonObject2.get("Fdate")+"','yyyy-MM-dd HH24:mi:ss'),'UNPRINT','未打印','"+map2.get("FName")+"','"+map3.get("FName")+"')");
         }
         JSONArray array = data.get("detail");
+        Object[] warehouses=null;
+        Object[] warehouses2=null;
         int detno=1;
         for (int i = 0; i <array.size(); i++) {
             JSONObject object = JSON.parseObject(StringUtil.nvl(array.get(i), "{}"));
@@ -640,7 +664,7 @@ public class MESServiceImpl implements MESService {
             if (count<=0){
                 return ApiResponse.failRsp("10064",request.getHeader("RequestId"),"MES仓库编号在ERP没有对应关系,请联系管理员新增!");
             }
-            Object[] warehouses = baseDao.getFieldsDataByCondition("customtabledetail left join customtable on " +
+            warehouses = baseDao.getFieldsDataByCondition("customtabledetail left join customtable on " +
                             "cd_ctid=ct_id left join Warehouse on cd_varchar50_3=wh_code", "cd_varchar50_3,wh_description",
                     "cd_varchar50_1='" + whcode + "'");Map<Object, Object> map2 = JSONUtil.toMap(StringUtil.valueOf(object.get("FDCStockID1")));
             String whcode2 = StringUtil.nvl(map2.get("FNumber"), "");
@@ -654,13 +678,19 @@ public class MESServiceImpl implements MESService {
             if (count2<=0){
                 return ApiResponse.failRsp("10066",request.getHeader("RequestId"),"MES仓库编号在ERP没有对应关系,请联系管理员新增!");
             }
-            Object[] warehouses2 = baseDao.getFieldsDataByCondition("customtabledetail left join customtable on " +
+            warehouses2 = baseDao.getFieldsDataByCondition("customtabledetail left join customtable on " +
                     "cd_ctid=ct_id left join Warehouse on cd_varchar50_3=wh_code", "cd_varchar50_3,wh_description",
                     "cd_varchar50_1='" + whcode2 + "'");
             sqls.add("insert into prodiodetail (pd_id,pd_piid,pd_inoutno,pd_piclass,pd_pdno,pd_prodcode," +
                     "pd_outqty,pd_whcode,pd_whname,pd_inwhcode,pd_inwhname) values (PRODIODETAIL_SEQ.nextval,"+id+",'"+code+"','拨出单',"+detno+",'"+itemNo+"',"+qty+",'"+warehouses[0]+"','"+warehouses[1]+"','"+warehouses2[0]+"','"+warehouses2[1]+"')");
             detno++;
         }
+        if (warehouses!=null){
+            sqls.add("update prodinout set pi_whcode='"+warehouses[0]+"',pi_whname='"+warehouses[1]+"' where " + "pi_id="+id);
+        }
+        if (warehouses2!=null){
+            sqls.add("update prodinout set pi_purpose='"+warehouses2[0]+"',pi_purposename='"+warehouses2[1]+"' where pi_id="+id);
+        }
         baseDao.execute(sqls);
         return ApiResponse.successRsp("0",request.getHeader("RequestId"),"拨出单:"+code+",请在ERP查看!");
     }
@@ -704,4 +734,2182 @@ public class MESServiceImpl implements MESService {
         }
         return jsonObject;
     }
+
+    private synchronized String postProdInOut(int pi_id, String caller,Employee employee) {
+    // 增加系统参数 出入库日期小于等于当前日期才允许过账 maz 2018020006
+		if (baseDao.isDBSetting("sys", "limitPostAfter")) {
+        Object pi_date = baseDao.getFieldDataByCondition("ProdInOut", "pi_date", "pi_id=" + pi_id);
+        String sysdate = DateUtil.getCurrentDate();
+        int sign = 0;
+        sign = DateUtil.compare(pi_date.toString(), sysdate);
+        if (sign == 1) {
+            return "单据日期大于当前日期,不能过账";
+        }
+    }
+    // 只能对状态为[未过账]的单据进行过账操作!
+    Object[] status = baseDao.getFieldsDataByCondition("ProdInOut", new String[] { "pi_statuscode", "pi_invostatuscode", "pi_date", "pi_class", "pi_recordman", "pi_inoutno" }, "pi_id=" + pi_id);
+		if (status[0].equals("POSTED")) {
+            return "只能对未过账的" + status[3] + "[" + status[5] + "]进行过账操作!";
+    }
+    // 2018030244 maz 送货单号不一致不允许提交
+		if ("ProdInOut!PurcCheckin".equals(caller) || "ProdInOut!DefectIn".equals(caller)) {
+        if (baseDao.isDBSetting("VerifyApplyDetail!Deal", "turnByDeliver")) {
+            SqlRowList rs = baseDao
+                    .queryForRowSet("select pd_pdno from prodinout left join prodiodetail on pi_id=pd_piid left join VerifyApply on va_code=pd_vacode where pi_id="
+                            + pi_id + " and nvl(pi_sendcode,' ')<>nvl(va_sendcode,' ')");
+            if (rs.next()) {
+                return "行号:" + rs.getInt("pd_pdno") + "送货单号不一致,不允许操作";
+            }
+        }
+    }
+    // 明细中如果有属于物料等级属于库存不可用的,就提示这些物料当前等级库存不可用
+    SqlRowList rowList = baseDao
+            .queryForRowSet(
+                    "select wm_concat(pd_prodcode)  prodcode from (select distinct pd_prodcode from prodiodetail "
+                            + "left join product on pd_prodcode=pr_code left join productlevel on pr_level=pl_levcode where pd_piid=? and pl_id>0 "
+                            + "and pl_isuseable=0 ) where rownum<=20", pi_id);
+		if (rowList.next()) {
+        if (rowList.getString("prodcode") != null) {
+            return "这些物料当前等级库存不可用,物料编号:" + rowList.getString("prodcode");
+        }
+    }
+		baseDao.execute("update prodinout set (pi_whcode,pi_whname)=(select pd_whcode,pd_whname from prodiodetail where pd_piid=pi_id and nvl(pd_whcode,' ')<>' ' and rownum<2) where pi_id="
+                + pi_id + " and nvl(pi_whcode,' ')= ' '");
+    // 判断已审核才允许过账
+		if (baseDao.isDBSetting(caller, "postNeedAudit")) {
+        if (!status[1].equals("AUDITED")) {
+            return status[3] + "[" + status[5] + "]未审核,不允许过账!";
+        }
+    }
+    String dets = baseDao
+            .getJdbcTemplate()
+            .queryForObject(
+                    "select wm_concat(distinct pi_class||'['||pi_inoutno||']') from prodinout left join prodiodetail a on pi_id=pd_piid where exists (select 1 from prodiodetail B WHERE B.PD_IOID=A.PD_ID AND B.PD_PIID=?) AND Pi_STATUSCODE='UNPOST'",
+                    String.class, pi_id);
+		if (dets != null) {
+            return "来源的" + dets + "未过账,本单据不允许过账!";
+    }
+    // 无来源订单不能直接过账
+		if (baseDao.isDBSetting(caller, "isWuPO")) {
+        int count = baseDao
+                .getCount("select count(*) from ProdIODetail where (pd_ordercode is null or pd_orderdetno is null) and  pd_piid="
+                        + pi_id);
+        if (!status[1].equals("AUDITED") && count != 0) {
+            return "无来源订单审核后才能过账";
+        }
+    }
+		boolean isProdIn=baseDao.isProdIn(caller);
+        if (isProdIn) {
+        // 检测入库单明细生产日期是否大于系统时间
+            if (baseDao.isDBSetting("sys","inOverNow")) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(PD_PDNO) from ProdIODetail left join ProdInOut on pd_piid=pi_id where pi_id=? and pd_prodmadedate is not null and to_char(pd_prodmadedate,'yyyy-mm') > to_char(sysdate,'yyyy-mm') ",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "行:" + dets + ",明细生产日期不能大于系统日期所在年月!";
+                }
+            }
+        SqlRowList rs = null;
+        // 入库类单据:如果pd_location为空,默认等于物料资料里的仓位pr_location
+        baseDao.execute(
+                "update prodiodetail set pd_location=(select pr_location from product where pr_code=pd_prodcode) where pd_piid=? and nvl(pd_location,' ')=' '",
+                pi_id);
+
+        rs = baseDao.queryForRowSet("SELECT pd_id FROM ProdioDetail where pd_piid=? and nvl(pd_batchcode,' ')=' '", pi_id);
+        while (rs.next()) {
+            baseDao.execute("update prodiodetail set pd_batchcode=? where pd_id=?", baseDao.getBatchcode(caller), rs.getInt("pd_id"));
+        }
+
+        // 入库单有生成条码但条码对应的物料或数量或批次号与明细行不一致则不允许过账
+        rs = baseDao.queryForRowSet(
+                        "select wm_concat(pd_pdno)no,count(1)cn from prodiodetail left join (select sum(bi_inqty)inqty,bi_pdno,max(bi_prodcode)bi_prodcode,max(bi_batchcode)bi_batchcode from barcodeio"
+                                + " where bi_piid=? group by bi_pdno) on bi_pdno=pd_pdno where pd_piid=? and pd_inqty>0 and inqty>0 "
+                                + " and (nvl(inqty,0)<>pd_inqty or bi_prodcode<>pd_prodcode or bi_batchcode<>pd_batchcode) and rownum<30",
+                        pi_id, pi_id);
+        if (rs.next() && rs.getInt("cn") > 0) {
+            return "条码与明细行中的物料或数量或批次号不一致,不允许过账,请先清除不一致条码!行号:" + rs.getString("no");
+        }
+    } else {
+        SqlRowList rs = null;
+        rs = baseDao
+                .queryForRowSet(
+                        "SELECT pd_id,ba_purcrate FROM ProdioDetail,batch where pd_batchid=ba_id and pd_piid=? and nvl(pd_batchid,0)<>0 and nvl(pd_outqty,0)>0",
+                        pi_id);
+        while (rs.next()) {
+            if (rs.getGeneralDouble("ba_purcrate") != 0) {
+                baseDao.execute("update prodiodetail set pd_purcoutqty=round(nvl(pd_outqty,0)/" + rs.getGeneralDouble("ba_purcrate")
+                        + ",8) where pd_id=" + rs.getObject("pd_id"));
+            } else {
+                baseDao.execute("update prodiodetail set pd_purcoutqty=nvl(pd_outqty,0) where pd_id=" + rs.getObject("pd_id"));
+            }
+        }
+
+    }
+    useDefaultTax(caller, pi_id);
+        String s = allowZeroTax(caller, pi_id);
+        if (s!=null){
+            return s;
+        }
+        String s1 = checkFreezeMonth(caller, status[2]);
+        if (s1!=null){
+            return s1;
+        }
+        String s2 = checkCloseMonth(status[2]);
+        if (s2!=null){
+            return s2;
+        }
+        String s3 = checkFirstMonth(caller, status[2]);
+        if (s3!=null){
+            return s3;
+        }
+        String s4 = checkCommit(caller, pi_id);
+        if (s4!=null){
+            return s4;
+        }
+        String s5 = checkBatch(caller, pi_id);
+        if (s5!=null){
+            return s5;
+        }
+        String copcheck = copcheck(pi_id, caller);
+        if (copcheck!=null){
+            return copcheck;
+        }
+        String factorycheck = factorycheck(pi_id, caller);
+        if (factorycheck!=null){
+            return factorycheck;
+        }
+        // 制造工单加工类型
+		if ("ProdInOut!Make!In".equals(caller) || "ProdInOut!OutsideCheckIn".equals(caller)) {
+            String s6 = checkMakeKindType(caller, pi_id);
+            if (s6!=null){
+                return s6;
+            }
+        }
+    // 暂时不启用平台 销售仓模式checkWhIsB2C(caller, pi_id);
+    /**
+     * 委外验收单,委外验退单 过账限制,判断明细行中的应付供应商或币别与主表是否一致,不一致则不允许过账;
+     */
+		if ("ProdInOut!OutsideCheckIn".equals(caller) || "ProdInOut!OutesideCheckReturn".equals(caller)) {
+        SqlRowList rs = baseDao
+                .queryForRowSet(
+                        "select wm_concat(pd_pdno) c from (select nvl(nvl(ma_apvendcode,ve_apvendcode),ve_code) apvendcode, pi_receivecode,pd_pdno "
+                                + "from prodiodetail left join prodinout on pd_piid=pi_id left join make on ma_code=pd_ordercode left join vendor "
+                                + "on ma_vendcode=ve_code where pi_id=?) t where t.apvendcode <> t.pi_receivecode and rownum<30", pi_id);
+        if (rs.next()) {
+            if (rs.getObject("c") != null) {
+                return "明细行中委外加工单的应付供应商与主表中的应付供应商不一致!";
+            }
+        }
+        SqlRowList rs2 = baseDao.queryForRowSet("select wm_concat(pd_pdno) x from (select ma_currency,pi_currency,pd_pdno"
+                + " from prodiodetail left join prodinout on pd_piid=pi_id left join make on ma_code=pd_ordercode"
+                + " where pi_id=?) t where t.ma_currency <> t.pi_currency and rownum<30", pi_id);
+        if (rs2.next()) {
+            if (rs2.getObject("x") != null) {
+                return "明细行中委外加工单的币别与主表中的币别不一致!";
+            }
+        }
+    }
+    // 完工入库,委外验收限制,入库数量不允许大于到当前pi_date的月份为止的(制造单生产的总数数量-已入库总数)
+		if ("ProdInOut!Make!In".equals(caller) || "ProdInOut!OutsideCheckIn".equals(caller)) {
+        // 存在pi_date 年月之后的 出入库单
+        int ym = DateUtil.getYearmonth(status[2].toString());
+        SqlRowList rs = baseDao
+                .queryForRowSet(
+                        "select A.pd_ordercode pd_ordercode,sum(A.pd_inqty)inqty from prodiodetail A left join make on ma_code=A.pd_ordercode left join makekind ON mk_name=ma_Kind"
+                                + " where A.pd_piid=? AND NVL(mk_finishunget, 0) = 0 and exists (select 1 from prodiodetail B left join prodinout on pi_id=B.pd_piid "
+                                + " where A.pd_ordercode=B.pd_ordercode and  to_char(pi_date,'yyyyMM')>? and "
+                                + " pi_class in('生产领料单','生产退料单','生产补料单','委外补料单','委外领料单','委外退料单') and B.pd_status=99) group by A.pd_ordercode",
+                        pi_id, ym);
+        while (rs.next()) {
+            Object[] obs = baseDao
+                    .getFieldsDataByCondition(
+                            "make left join makematerial on mm_maid=ma_id",
+                            new String[] {
+                                    " nvl(min(case when mm_oneuseqty*ma_qty>mm_qty+0.1 then ma_qty else ceil((nvl(mm_havegetqty, 0)-(select sum(nvl(pd_outqty,0)-nvl(pd_inqty,0)) from prodinout left join prodiodetail on pd_piid=pi_id "
+                                            + " where to_char(pi_date,'yyyyMM')>'"
+                                            + ym
+                                            + "' and pd_ordercode=ma_code and pd_orderdetno=mm_detno  and pi_class in('生产领料单','生产退料单','生产补料单','委外补料单','委外领料单','委外退料单'))"
+                                            + " -nvl(mm_scrapqty,0))*1.0/mm_oneuseqty)end),0) as canmadeqty",
+                                    "nvl(max(ma_madeqty),0) -"
+                                            + "nvl(max((select SUM(NVL(pd_inqty,0)-NVL(pd_outqty,0)) from prodinout LEFT JOIN prodiodetail ON pd_piid=pi_id "
+                                            + " WHERE TO_CHAR(pi_date,'yyyyMM')>'" + ym + "' and pd_ordercode='"
+                                            + rs.getString("pd_ordercode")
+                                            + "' and pi_class in('完工入库单','委外验收单','委外验退单'))),0) as madeqty" },
+                            " mm_code='" + rs.getString("pd_ordercode") + "' and nvl(mm_materialstatus,' ')=' ' and mm_oneuseqty>0");
+            if (obs != null) {// 比较
+                if (rs.getDouble("inqty") > (Double.valueOf(obs[0].toString()).doubleValue() - Double.valueOf(obs[1].toString())
+                        .doubleValue())) {
+                    return "工单[" + rs.getString("pd_ordercode") + "]当前月份领料套数(" + obs[0] + ")不足完工数";
+                }
+            }
+        }
+    }
+
+    /**
+     * 采购验收单、委外验收单 从表单位pr_unit与采购单位pr_purcunit不一致的时候,
+     * 数量pd_inqty与采购单位入库数量pd_purcinqty不能一致,否则无法提交、过账
+     */
+		if (baseDao.isDBSetting("sys","usePurcUnit") && ("ProdInOut!PurcCheckin".equals(caller) || ("ProdInOut" +
+                "!OutsideCheckIn").equals(caller))) {
+        String dets1 = baseDao.getJdbcTemplate().queryForObject(
+                "select wm_concat(pd_pdno)  from ProdIODetail left join Product on pd_prodcode=pr_code  where pd_piid=?  "
+                        + "and PR_UNIT is not null  and pr_purcunit is not null "
+                        + "and (nvl(pd_inqty,0)>0) and (nvl(pd_purcinqty,0)>0)  "
+                        + "and nvl(PR_UNIT,'')<>nvl(pr_purcunit,'') and nvl(pd_inqty,0)=nvl(pd_purcinqty,0)", String.class, pi_id);
+        if (dets1 != null) {
+            return "行" + dets1 + ",明细入库数量和采购单位入库数量需不一致,否则无法过账!";
+        }
+    }
+    /**
+     * 新增生产退料和委外退料判断,替代料退料数量不能大于替代料已领数量,禁用物料判断mm_updatetype='R',
+     *
+     * @date 2016年10月17日 下午12:30:58
+     */
+		if (("ProdInOut!Make!Return").equals(caller) || ("ProdInOut!OutsideReturn").equals(caller)) {
+        checkRepQty(pi_id);
+        /**
+         * 生产退料单,委外退料单  校验退料数量不能大于截止到单据日期月份 已过账的领料-退料-报废+补料-完工数*单位用量
+         */
+        checkMmBackOver(caller,pi_id);
+    }
+    /**
+     * 新增限制,拆件类型制造单不允许走完工入库单
+     *
+     * @author XiaoST 2016年12月9日 下午4:26:34
+     */
+		if ("ProdInOut!Make!In".equals(caller) || "ProdInOut!OutsideCheckIn".equals(caller)) {
+        dets = baseDao
+                .getJdbcTemplate()
+                .queryForObject(
+                        "select wm_concat('行号:'||pd_pdno||'工单:'||pd_ordercode) from ProdIODetail left join make on ma_code=pd_ordercode left join makekind ON mk_name=ma_kind where pd_piid=? and  mk_type='D' and rownum<20",
+                        String.class, pi_id);
+        if (dets != null) {
+            return "拆件工单必须走拆件入库单!" + dets;
+        }
+    }
+		baseDao.getEndDate(caller, pi_id);
+        String res = null;
+        // 平台生成的销售订单转出货单过账必须等于销售订单明细序号和数量
+		if ("ProdInOut!Sale".equals(caller)) {
+        SqlRowList rs = baseDao
+                .queryForRowSet(
+                        "select distinct sa_code,sum(pd_outqty) out_qty,pd_orderdetno from prodiodetail left join sale on sa_code=pd_ordercode where sa_ordertype='B2C' and nvl(sa_b2ccode,' ')<>' ' and pd_piid=? group by sa_code,pd_orderdetno",
+                        pi_id);
+        while (rs.next()) {
+            rs = baseDao
+                    .queryForRowSet(
+                            "select distinct pd_ordercode pd_ordercode from prodiodetail where pd_piid=? and (pd_orderdetno not in (select sd_detno from saledetail where sd_code=?))"
+                                    + " OR "
+                                    + rs.getDouble("out_qty")
+                                    + " <>(select sd_qty from saledetail where sd_code=? and sd_detno=?) and  pd_ordercode =?", pi_id,
+                            rs.getString("sa_code"), rs.getString("sa_code"), rs.getString("pd_orderdetno"), rs.getString("sa_code"));
+            if (rs.next()) {
+                return "通过优软商城平台生成的发货单必须一次性发货,销售单号[" + rs.getString("pd_ordercode") + "]";
+            }
+            // 维护物流公司和物流单号
+            Object[] obs = baseDao.getFieldsDataByCondition("prodinout", new String[] { "pi_logisticscompany", "pi_logisticscode" },
+                    "pi_id=" + pi_id);
+            if (obs[0] == null || obs[1] == null) {
+                return "请维护出货单的物流公司和物料单号信息!";
+            }
+        }
+    }
+    // 委外领、退、补单过账前
+		if ("ProdInOut!OutsidePicking".equals(caller) || "ProdInOut!OutsideReturn".equals(caller) || "ProdInOut!OSMake!Give".equals(caller)) {
+        // 更新:如果主表的应付供应商空,则取第一个工单的应付供应商ma_apvendcode,空则取工单供应商ma_vendcode
+        baseDao.execute("update prodinout  set (pi_receivecode,pi_receivename)=(select code,ve_name from "
+                + "(select nvl(ma_apvendcode,ma_vendcode)code,ve_name from prodiodetail left join make on "
+                + "pd_ordercode=ma_code left join  vendor on nvl(ma_apvendcode,ma_vendcode)=ve_code "
+                + "where pd_piid=? order by pd_pdno) where rownum=1 )" + "where nvl(pi_receivecode,' ')=' ' and pi_id=?", pi_id, pi_id);
+        // 判断主表应付供应商与从表工单应付供应商是否一致
+        SqlRowList pdnos = baseDao
+                .queryForRowSet(
+                        "select wm_concat(pd_pdno) c from (select nvl(nvl(ma_apvendcode,ve_apvendcode),ve_code) apvendcode, pi_receivecode,pd_pdno "
+                                + "from prodiodetail left join prodinout on pd_piid=pi_id left join make on ma_code=pd_ordercode left join vendor "
+                                + "on ma_vendcode=ve_code where pi_id=?) t where t.apvendcode <> t.pi_receivecode and rownum<30", pi_id);
+        if (pdnos.next()) {
+            if (pdnos.getObject("c") != null) {
+                return "行" + pdnos.getObject("c") + "工单应付供应商与主表应付供应商不一致,不能过账";
+            }
+        }
+    }
+    // @add20171103
+		if ("ProdInOut!PurcCheckin".equals(caller)) {// 采购验收单根据采购单号、序号,更新入库销售单号、序号
+        baseDao.execute(
+                "update prodiodetail set (pd_salecode,pd_saledetno,pd_topmothercode)=(select d.pd_salecode,d.pd_saledetno,d.pd_topmothercode from purchase left join purchasedetail d on pu_id=pd_puid where "
+                        + " pd_ordercode=pu_code and pd_orderdetno=pd_detno) where pd_piid=?", pi_id);
+    }
+    // 生产退料单、委外退料单、拆件入库单、完工入库单、委外验收单,根据工单的订单号、订单序号能匹配到销售单号和序号(如果是预测单则不锁批记录)则更新到入库单明细的销售单号、序号
+		if ("ProdInOut!OutsideReturn".equals(caller) || "ProdInOut!OutsideCheckIn".equals(caller) || "ProdInOut!Make!In".equals(caller)
+				|| "ProdInOut!PartitionStockIn".equals(caller) || "ProdInOut!Make!Return".equals(caller)) {
+        baseDao.execute(
+                "update prodiodetail set (pd_salecode,pd_saledetno,pd_topmothercode)=(select ma_salecode,ma_saledetno,nvl(ma_topmothercode,ma_prodcode)topmothercode from make where pd_ordercode=ma_code)"
+                        + " where pd_piid=? and exists (select 1 from make left join sale on sa_code=ma_salecode left join saledetail on sd_said=sa_id and sd_detno=ma_saledetno where pd_ordercode=ma_code and sd_detno>0)",
+                pi_id);
+
+    }
+    // 销售退货明细客户为空时=主表客户
+		if ("ProdInOut!SaleReturn".equals(caller)) {
+        baseDao.execute(
+                "update prodiodetail set (pd_custcode,pd_custname)=(select pi_cardcode,pi_title from prodinout where pd_piid=pi_id)"
+                        + " where pd_piid=? and nvl(pd_custcode,' ')=' '", pi_id);
+
+    }
+    /*
+     * 退料数量不能大于维护的可退数量 String SQLStr_s = ""; SqlRowList rs_s; SQLStr_s=
+     * "select * from ProdIODetail left join make on ma_code=pd_ordercode"
+     * +" left join IO_MAKEMATERIAL_DETNO_VIEW on pd_orderdetno = mm_detno"
+     * +" where ma_id=mm_maid and pd_piid= '"+pi_id+"'"; rs_s =
+     * baseDao.queryForRowSet(SQLStr_s); if(rs_s.next()){ if
+     * (rs_s.getInt("pd_inqty")>rs_s.getInt("mm_havegetqty")) {
+     * BaseUtil.showError("工单序号[" + rs_s.getString("pd_orderdetno") +
+     * "]的退料数量不能大于维护的可退数量!'"); } }
+     */
+    // 过账前的其它逻辑
+    getTotal(pi_id, caller);// 调用过账存储过程前后都掉用一次gettotal方法,解决出入库单税率与发票不一致
+    getQtyTotal(pi_id, caller);
+    // 执行过账操作
+    Object[] objs = baseDao.getFieldsDataByCondition("ProdInOut", new String[] { "pi_class", "pi_inoutno" }, "pi_id=" + pi_id);
+		if ("ProdInOut!CostChange".equals(caller)) {
+        res = baseDao.callProcedure("SP_PRODUCTCOSTADJUST", new Object[] { objs[0].toString(), objs[1].toString(), "" });
+        if (res != null && !res.trim().equals("")) {
+            return res;
+        }
+    } else {
+        baseDao.procedure("SP_GetCostPrice", new Object[] { objs[0].toString(), objs[1].toString() });
+        if (baseDao.isDBSetting("sys","SplitprodoutByseller")) {// 出单过账前取批号按照业务员pi_sellercode获取
+            res = baseDao.callProcedure("Sp_Splitprodout_Byseller",
+                    new Object[] { objs[0].toString(), objs[1].toString(),employee.getEm_name()});
+        } else {
+            res = baseDao.callProcedure("Sp_SplitProdOut",
+                    new Object[] { objs[0].toString(), objs[1].toString(),employee.getEm_name()});
+        }
+
+        if (res != null && !res.trim().equals("")) {
+            // 重新添加提示限制信息
+            return res + "  " + objs[0].toString() + objs[1].toString() + ",过账失败";
+            // BaseUtil.showError(res);
+        }
+        // @add 20170614 抓取批次号成功之后更新出库单据的备料状态
+        updatePdaStatus(caller, pi_id);
+        if (baseDao.isDBSetting(caller, "ifBatchCodeNotChange") && baseDao.isDBSetting(caller, "autoPostIn")) {
+            // 拨出单过帐后产生的拨入单批号不变,同一物料同仓库不能同时入两次相同的批号
+            SqlRowList rs1 = baseDao
+                    .queryForRowSet("select  count(1)n, wm_concat(pd_pdno)detno from (select pd_batchcode,pd_inwhcode,pd_prodcode,min(pd_pdno)pd_pdno,count(1)c from  ProdIODetail where pd_piid="
+                            + pi_id + " and pd_batchcode<>' ' group by pd_batchcode,pd_inwhcode,pd_prodcode ) where c> 1");
+            if (rs1.next()) {
+                if (rs1.getInt("n") > 0) {
+                    return "拨出单过帐后产生的拨入单批号不变,同一物料同拨入仓库批号不能相同!行号:" + rs1.getString("detno");
+                }
+            }
+        }
+            String s7 = checkBatchRemain(pi_id);
+            if (s7!=null){
+                return s7;
+            }
+            dets = baseDao
+                .getJdbcTemplate()
+                .queryForObject(
+                        "select wmsys.wm_concat(a2.pd_pdno) from prodinout a1 left join prodiodetail a2 on a1.pi_id=a2.pd_piid " +
+                                "left join prodiodetail b2 on a2.pd_batchcode=b2.pd_batchcode and a2.pd_prodcode=b2.pd_prodcode and a2.pd_whcode=b2.pd_whcode " +
+                                "left join prodinout b1 on b2.pd_piid=b1.pi_id where a2.pd_piid=? and nvl(b2.pd_inqty,0)>0 and nvl(a2.pd_outqty,0)>0 " +
+                                "and to_char(a1.pi_date,'yyyymm')<to_char(b1.pi_date,'yyyymm') and rownum<20",
+                        String.class, pi_id);
+        if (dets != null) {
+            return "出库单据日期所在期间小于批次入库日期所在期间,不能过账!行号:" + dets;
+        }
+        // 存储过程
+        res = baseDao.callProcedure("Sp_CommitProdInout",
+                new Object[] { objs[0].toString(), objs[1].toString(), employee.getEm_name()});
+        if (res != null && !res.trim().equals("")) {
+            return res;
+        }
+        if (baseDao.isDBSetting("sys","autoCreateApBill")) {
+            if ("采购验收单".equals(status[3]) || "采购验退单".equals(status[3]) || "委外验收单".equals(status[3]) || "委外验退单".equals(status[3])
+                    || "用品验收单".equals(status[3]) || "用品验退单".equals(status[3])) {
+                dets = baseDao.queryForObject("select wm_concat(ab_code) from apbill where ab_source=? and ab_statuscode<>'POSTED'",
+                        String.class, status[5]);
+                if (dets != null) {
+                    return "发票" + dets + "未过账成功,请手工过账!";
+                }
+            }
+        }
+        if (baseDao.isDBSetting("sys","autoCreateArBill")) {
+            if ("出货单".equals(status[3]) || "销售退货单".equals(status[3])) {
+                dets = baseDao.queryForObject(
+                        "select wm_concat(ab_code) from arbill where AB_SOURCECODE=? and ab_statuscode<>'POSTED'", String.class,
+                        status[5]);
+                if (dets != null) {
+                    return "发票" + dets + "未过账成功,请手工过账!";
+                }
+            }
+        }
+    }
+
+		getTotal(pi_id, caller);
+		getQtyTotal(pi_id, caller);
+		baseDao.updateByCondition("ProdInOut", "pi_statuscode='POSTED',pi_status='已过帐',pi_inoutman='"+employee.getEm_name()+"'," +
+                "pi_date1=sysdate,pi_sendstatus='待上传'", "pi_id=" + pi_id);
+		if (!baseDao.isIn(caller)) {// 出库类单据过账时,根据批号抓取batch.ba_vendorrate到prodiodetail.pd_vendorrate
+        baseDao.execute("update prodiodetail set pd_vendorrate=(select ba_vendorrate from batch where ba_code=pd_batchcode"
+                + " and ba_whcode =pd_whcode and ba_prodcode=pd_prodcode ) where pd_piid=" + pi_id + " and nvl(pd_vendorrate,0)=0");
+    }
+		if (baseDao.isDBSetting("sys","updateBusinessChance") && !"ProdInOut!GoodsIn".equals(caller)) {// 更新当前商机阶段
+        Object bsname = baseDao.getFieldDataByCondition("BusinessChanceStage", "bs_name", "bs_relativeitem='Shipment'");
+        Object date = baseDao.getFieldDataByCondition("ProdInOut", "to_char(pi_recorddate,'yyyy-MM-dd')", "pi_id=" + pi_id);
+
+        List<Object[]> data = baseDao.getFieldsDatasByCondition("prodiodetail  left join ProdInOut on pd_piid=pi_id", new String[] {
+                "pd_bcid", "pd_prodcode", "pd_pdno" }, "pd_piid=" + pi_id);
+        for (Object[] os : data) {
+            if (os[0] == null || os[0].equals("") || os[0].equals("0") || Integer.parseInt(os[0].toString()) == 0) {
+                String sql = "update Prodiodetail set pd_bcid=nvl((select sd_bcid from saledetail "
+                        + "where pd_ordercode=sd_code and pd_orderdetno=sd_detno),0) where pd_piid=" + pi_id + " and nvl(pd_bcid,0)=0";
+                baseDao.execute(sql);
+            }
+            Object pd_bcid = baseDao.getFieldDataByCondition("Prodiodetail", "pd_bcid", " pd_prodcode='" + os[1] + "' and pd_piid="
+                    + pi_id);
+            if (pd_bcid == null || pd_bcid.equals("") || pd_bcid.equals("0") || Integer.parseInt(pd_bcid.toString()) == 0) {
+                String sql = "update prodiodetail set pd_bcid=nvl((select max(bc_id) from prodinout,businesschance "
+                        + "where pi_id=pd_piid and pi_cardcode=bc_custcode and pd_prodcode=bc_model and bc_status<>'已结案'),0) where nvl(pd_bcid,0)=0 and pd_piid="
+                        + pi_id + " and nvl(pd_bcid,0)=0";
+                baseDao.execute(sql);
+            }
+            Object bc_id = baseDao.getFieldDataByCondition("Prodiodetail", "pd_bcid", " pd_prodcode='" + os[1] + "' and pd_piid="
+                    + pi_id);
+            Integer bs_detno = baseDao.getFieldValue("businesschancestage", "bs_detno", "bs_name='" + bsname + "'", Integer.class);
+            Integer bs_detno1 = baseDao.getFieldValue("businesschance left join businesschancestage on bs_name=bc_currentprocess",
+                    "nvl(bs_detno,0)", "bc_id=" + bc_id, Integer.class);
+            if (bs_detno != null && bs_detno1 != null) {
+                if (bs_detno >= bs_detno1) {
+                    baseDao.updateByCondition("BusinessChance", "bc_currentprocess='" + bsname + "',bc_desc" + bs_detno + "='" + bsname
+                            + "',bc_date" + bs_detno + "=to_date('" + date.toString() + "','yyyy-MM-dd')", "bc_id=" + bc_id);
+                    if (bsname != null && Integer.parseInt(pd_bcid.toString()) != 0) {
+                        Object bscode = baseDao.getFieldDataByCondition("BusinessChanceStage", "bs_code", "bs_name='" + bsname + "'");
+                        // 插入一条记录到商机动态表
+                        int bcd_id = baseDao.getSeqId("BusinessChanceData_seq");
+                        String link = "jsps/scm/reserve/prodInOut.jsp?whoami=ProdInOut!Sale&formCondition=pi_idIS" + pi_id
+                                + "&gridCondition=pd_piidIS" + pi_id;
+                        String contactSql = "insert into BusinessChanceData (bcd_id,bcd_bcid,bcd_code,bcd_bscode,bcd_bsname,bcd_date,bcd_man,bcd_statuscode,bcd_status,bcd_sourcecode,bcd_sourcelink) values ("
+                                + bcd_id
+                                + ","
+                                + bc_id
+                                + ",'"
+                                + baseDao.sGetMaxNumber("BusinessChanceData", 2)
+                                + "','"
+                                + bscode
+                                + "','"
+                                + bsname
+                                + "',"
+                                + "to_date('"
+                                + date.toString()
+                                + "','yyyy-MM-dd')"
+                                + ",'"
+                                + status[4]
+                                + "','"
+                                + "ENTERING" + "','在录入','" + status[5] + "','" + link + "')";
+                        baseDao.execute(contactSql);
+                    }
+                }
+            }
+
+        }
+
+    }
+    // 调用冲销
+		createSaleClash(pi_id, "ProdInOut",employee);
+		if ("ProdInOut!AppropriationOut".equals(caller) || "ProdInOut!SaleAppropriationOut".equals(caller)) {
+        dets = null;
+        if (baseDao.isDBSetting(caller, "autoPostIn")) {
+            // 过账销售拨入单
+            dets = turnProdIO(pi_id,employee);
+            // 过账失败提醒
+            boolean showTurnProdIOError = baseDao.checkIf("ProdInOut",
+                    "pi_class='拨入单' and pi_statuscode='UNPOST' and pi_inoutno=(select pi_relativeplace from ProdInOut where pi_class='拨出单' and pi_id="
+                            + pi_id + ")");
+            if (showTurnProdIOError) {
+                return "自动过账失败";
+            }
+        }
+        if (dets != null) {
+            return "拨入单明细行仓库对应的仓管员与当前过账人不一致,不允许进行当前操作!行号:" + dets;
+        }
+        if (baseDao.isDBSetting(caller, "autoPostMakeLSSend")) {// MakeSendLS
+            // 拉式发料
+            // 拨出单过账,拨入也过账时自动过账领料单
+            String SQLStr = "";
+            String Outpiclass = "";
+            SQLStr = "select pi_inoutno from prodinout where pi_id=" + pi_id + " and pi_statuscode='POSTED'";
+            SqlRowList rs0 = baseDao.queryForRowSet(SQLStr);
+            if (rs0.next()) {
+                SQLStr = "select pi_id,pi_class,pi_inoutno from prodinout where pi_fromcode='" + rs0.getString("pi_inoutno")
+                        + "' and pi_statuscode='UNPOST' ";
+                SqlRowList rs = baseDao.queryForRowSet(SQLStr);
+                if (rs.next()) {
+                    Outpiclass = rs.getObject("pi_class").toString();
+                    if (Outpiclass.equals("生产领料单")) {
+                        postProdInOut(rs.getInt("pi_id"), "ProdInOut!Picking",employee);
+                    } else if (Outpiclass.equals("委外领料单")) {
+                        postProdInOut(rs.getInt("pi_id"), "ProdInOut!OutsidePicking",employee);
+                    }
+                    SQLStr = "select pi_statuscode from prodinout where pi_id=" + rs.getInt("pi_id") + " and pi_statuscode='POSTED' ";
+                    rs0 = baseDao.queryForRowSet(SQLStr);
+                    if (rs0.next()) {
+                        return Outpiclass + ":" + rs.getString("pi_inoutno") + "过账成功!";
+                    } else {
+                        return Outpiclass + ":" + rs.getString("pi_inoutno") + "过账不成功!";
+                    }
+                }
+            }
+
+        }
+    }
+    // 委外验收,验退,完工入库单,过账更新完工状态
+		if ("ProdInOut!Make!In".equals(caller) || "ProdInOut!OutsideCheckIn".equals(caller)
+				|| "ProdInOut!OutesideCheckReturn".equals(caller)) {
+        SqlRowList rs = baseDao.queryForRowSet(
+                "select distinct ma_id from  prodiodetail left join make on ma_code=pd_ordercode where pd_piid=?", pi_id);
+        while (rs.next()) {// 更新完工状态
+            updateMakeFinishStatus(rs.getInt("ma_id"));
+        }
+    }
+		if ("ProdInOut!AppropriationOut".equals(caller)) {
+        SqlRowList rs3 = baseDao
+                .queryForRowSet(
+                        "select b.pi_id pi_id,a.pi_relativeplace pi_relativeplace from prodinout a left join prodinout  b on a.pi_relativeplace=b.pi_inoutno where a.pi_id=? and b.pi_class='拨入单'",
+                        pi_id);
+        if (rs3.next()) {
+            return "拨出单过账成功!系统产生的拨入单号 "+ rs3.getString("pi_relativeplace");
+        }
+    }
+
+		if ("ProdInOut!PurcCheckin".equals(caller)) {// 采购验收单过账根据采购单+采购单序号更新pd_vendorrate
+        // ba_vendorrate
+        SqlRowList pdRowList = baseDao
+                .queryForRowSet("select pd_id,nvl(pd_batchid,0) pd_batchid,nvl(pd_ordercode,' ') pd_ordercode,nvl(pd_orderdetno,0) pd_orderdetno from prodiodetail where pd_piid="
+                        + pi_id);
+        while (pdRowList.next()) {
+            baseDao.execute("update prodiodetail set pd_vendorrate=(select pd_vendorrate from purchasedetail where pd_code='"
+                    + pdRowList.getObject("pd_ordercode") + "' and pd_detno='" + pdRowList.getObject("pd_orderdetno")
+                    + "') where pd_id=" + pdRowList.getObject("pd_id"));
+            baseDao.execute("update batch set ba_vendorrate=(select pd_vendorrate from purchasedetail where pd_code='"
+                    + pdRowList.getObject("pd_ordercode") + "' and pd_detno='" + pdRowList.getObject("pd_orderdetno")
+                    + "') where ba_id=" + pdRowList.getObject("pd_batchid"));
+        }
+    }
+		if ("ProdInOut!Make!Give".equals(caller) || "ProdInOut!Make!Return".equals(caller) || "ProdInOut!Picking".equals(caller)
+				|| "ProdInOut!OSMake!Give".equals(caller) || "ProdInOut!OutsideReturn".equals(caller)
+				|| "ProdInOut!OutsidePicking".equals(caller)) {
+        changeMaStatus(pi_id);
+    }
+    // 2017-08-30 重新根据pdno更新批号仓库属性
+		if (isProdIn) {
+        baseDao.execute(
+                "update barcodeio set (bi_batchcode,bi_batchid,bi_whcode)=(select pd_batchcode,pd_batchid,pd_whcode from prodiodetail where bi_piid=pd_piid and pd_pdno=bi_pdno) where bi_piid=? and nvl(bi_status,0)=0",
+                pi_id);
+        baseDao.execute(
+                "update batch set ba_hasbarcode=-1 where ba_id in (select pd_batchid from prodiodetail "
+                        + " where pd_piid=?) and NVL(ba_hasbarcode,0)=0 and ba_id in (select bi_batchid from barcodeio where bi_inqty>0 and bi_status=0) ",
+                pi_id);
+    }
+    /**
+     * @author wsy
+     *         其它入库单:如果选择了采购单号、采购序号后,提交、审核的时候要判断采购单号+采购序号+物料编号是否一致,不一致限制提交
+     *         、审核
+     */
+		if ("ProdInOut!OtherIn".equals(caller)) {
+        baseDao.execute("update purchasedetail set pd_beipinacceptqty=(nvl((select sum(nvl(pd_purcinqty,0)) from prodiodetail where pd_piclass='其它入库单' and pd_ordercode=pd_code and pd_orderdetno=pd_detno and pd_status=99),0))where (pd_code,pd_detno) in (select pd_ordercode,pd_orderdetno from prodiodetail where pd_piid="
+                + pi_id + " and pd_piclass='其它入库单')");
+    }
+        prodinout_post_updatesourceqty(pi_id);
+		return null;
+}
+
+    /**
+     * 过账后扣除待检数量、收料数量 scm->prodinout->post->after
+     *
+     * @author madan
+     */
+    public void prodinout_post_updatesourceqty(Integer id) {
+        Object[] piclass = baseDao.getFieldsDataByCondition("ProdInOut", new String[] { "pi_class", "pi_type" }, "pi_id=" + id);
+        if (!(piclass[0].toString().equals("采购验收单") || piclass[0].toString().equals("委外验收单") || piclass[0].toString().equals("不良品入库单"))) {
+            return;
+        }
+        List<Object[]> objs = baseDao.getFieldsDatasByCondition("prodioDetail", new String[] { "pd_orderdetno", "pd_ordercode",
+                "sum(pd_inqty)", "pd_prodcode" }, "pd_piid=" + id + " and pd_qcid>0 group by pd_ordercode, pd_orderdetno, pd_prodcode");
+        for (Object[] obj : objs) {
+            if ("采购验收单".equals(piclass[0].toString())) {
+                baseDao.updateByCondition("PurchaseDetail", "pd_reconhand = nvl(pd_reconhand,0)-" + obj[2]
+                        + ",pd_totested=NVL(pd_totested,0)-" + obj[2], "pd_code='" + obj[1] + "' and pd_detno = " + obj[0]);
+            } else if ("委外验收单".equals(piclass[0].toString()) || "完工入库单".equals(piclass[0].toString())) {
+                baseDao.updateByCondition("Make", "ma_reconhand = nvl(ma_reconhand,0)-" + obj[2] + ",ma_totested=NVL(ma_totested,0)-"
+                        + obj[2], "ma_code='" + obj[1] + "'");
+            } else if ("不良品入库单".equals(piclass[0].toString())) {
+                if ("PURC".equals(piclass[1].toString()) || "采购不良品入库".equals(piclass[1].toString())) {
+                    baseDao.updateByCondition("PurchaseDetail", "pd_reconhand = nvl(pd_reconhand,0)-" + obj[2]
+                            + ",pd_totested=NVL(pd_totested,0)-" + obj[2], "pd_code='" + obj[1] + "' and pd_detno = " + obj[0]);
+                } else {
+                    baseDao.updateByCondition("Make", "ma_reconhand = nvl(ma_reconhand,0)-" + obj[2] + ",ma_totested=NVL(ma_totested,0)-"
+                            + obj[2], "ma_code='" + obj[1] + "'");
+                }
+            }
+            baseDao.updateByCondition("Product", "pr_reconhand = nvl(pr_reconhand,0)-" + obj[2] + ",pr_totested=NVL(pr_totested,0)-"
+                    + obj[2], "pr_code='" + obj[3] + "'");
+        }
+    }
+
+    // 税率强制等于币别表的默认税率
+    private void useDefaultTax(String caller, Object pi_id) {
+        if (baseDao.isDBSetting(caller, "useDefaultTax")) {
+            baseDao.execute("update ProdIODetail set pd_taxrate=(select cr_taxrate from currencys left join ProdInOut on pi_currency=cr_name and cr_statuscode='CANUSE' where pd_piid=pi_id)"
+                    + " where pd_piid=" + pi_id);
+        }
+        String defaultTax = baseDao.getDBSetting(caller, "defaultTax");
+        if (defaultTax != null) {
+            // 税率强制等于币别表的默认税率
+            if ("1".equals(defaultTax)) {
+                baseDao.execute("update ProdIODetail set pd_taxrate=(select cr_taxrate from currencys left join ProdInOut on pi_currency=cr_name and cr_statuscode='CANUSE' where pd_piid=pi_id)"
+                        + " where pd_piid=" + pi_id);
+            }
+            // 税率强制等于供应商资料的默认税率
+            if ("2".equals(defaultTax)) {
+                if ("ProdInOut!PurcCheckin".equals(caller) || "ProdInOut!PurcCheckout".equals(caller)
+                        || "ProdInOut!OutsideCheckIn".equals(caller) || "ProdInOut!OutesideCheckReturn".equals(caller)) {
+                    baseDao.execute("update ProdIODetail set pd_taxrate=(select nvl(ve_taxrate,0) from Vendor left join ProdInOut on pi_cardcode=ve_code and ve_auditstatuscode='AUDITED' where pi_id=pd_piid)"
+                            + " where pd_piid=" + pi_id);
+                }
+                if ("ProdInOut!SaleReturn".equals(caller) || "ProdInOut!Sale".equals(caller)) {
+                    baseDao.execute("update ProdIODetail set pd_taxrate=(select nvl(cu_taxrate,0) from Customer left join ProdInOut on pi_cardcode=cu_code and cu_auditstatuscode='AUDITED' where pi_id=pd_piid)"
+                            + " where pd_piid=" + pi_id);
+                }
+            }
+        }
+    }
+
+    // 本位币允许税率为0
+    private String allowZeroTax(String caller, Object pi_id) {
+        String currency = baseDao.getDBSetting("sys","defaultCurrency");
+        boolean allowZeroTax = baseDao.isDBSetting(caller, "allowZeroTax");
+        if ("ProdInOut!Sale".equals(caller) || "ProdInOut!SaleReturn".equals(caller)) {
+            allowZeroTax = baseDao.isDBSetting("Sale", "allowZeroTax");
+        }
+        if ("ProdInOut!PurcCheckin".equals(caller) || "ProdInOut!PurcCheckout".equals(caller)) {
+            allowZeroTax = baseDao.isDBSetting("Purchase", "allowZeroTax");
+        }
+        if ("ProdInOut!OutsideCheckIn".equals(caller) || "ProdInOut!OutesideCheckReturn".equals(caller)) {
+            allowZeroTax = baseDao.isDBSetting("Make", "allowZeroTax");
+        }
+        if (!allowZeroTax) {
+            String dets = baseDao.getJdbcTemplate().queryForObject(
+                    "select WM_CONCAT(pd_pdno) from ProdIODetail left join ProdInOut on pd_piid=pi_id where nvl(pd_taxrate,0)=0 and pi_currency='"
+                            + currency + "' and pi_id=?", String.class, pi_id);
+            if (dets != null) {
+                return "本位币税率为0,不允许进行当前操作!行号:" + dets;
+            }
+        }
+        return null;
+    }
+
+    String checkCloseMonth(Object pidate) {
+        boolean bool = baseDao.checkIf("PeriodsDetail", "pd_code='MONTH-P' and pd_status=99 and pd_detno=to_char(to_date('" + pidate
+                + "','yyyy-mm-dd hh24:mi:ss'), 'yyyymm')");
+        if (bool) {
+            return "单据日期所属期间已结账,不允许进行当前操作!";
+        }
+        return null;
+    }
+
+    String checkMakeKindType(String caller, Object pi_id) {
+        if (baseDao.isDBSetting(caller, "makeKindType")) {
+            String sql = "select count(1)cn from (select count(1) cn,  mk_type from make left join makekind on mk_name =ma_kind"
+                    + " left join prodiodetail on pd_ordercode = ma_code where pd_piid=? group by mk_type) ";
+            SqlRowList sqlRowList = baseDao.queryForRowSet(sql, pi_id);
+            if (sqlRowList.next()) {
+                if (sqlRowList.getInt("cn") > 1) {
+                    return "明细行制造单加工类型不同,不能使用同一张完工入库单";
+                }
+            }
+        }
+        return null;
+    }
+
+    String checkFreezeMonth(String caller, Object pidate) {
+        if (!"ProdInOut!CostChange".equals(caller)) {
+            String freeze = baseDao.getDBSetting("sys","freezeMonth");
+            if (freeze != null && !freeze.equals("")) {
+                if (Integer.parseInt(freeze) == DateUtil.getYearmonth(pidate.toString())) {
+                    return "单据日期所属期间已冻结,不允许进行当前操作!";
+                }
+            }
+        }
+        return null;
+    }
+
+    String checkFirstMonth(String caller, Object pidate) {
+        if ("ProdInOut!ReserveInitialize".equals(caller)) {
+            Object first = baseDao.getFieldDataByCondition("periods", "nvl(PE_FIRSTDAY,0)", "PE_CODE='MONTH-P'");
+            if ("0".equals(first.toString())) {
+                return "请前往【初始化期间设置】确认开账期间!";
+            } else {
+                if (Integer.parseInt(first.toString()) != DateUtil.getYearmonth(pidate.toString())) {
+                    return "库存初始化单据只能发生在库存模块的开账期间!当前库存模块开账期间为[" + first + "],请前往【初始化期间设置】确认开账期间!";
+                }
+            }
+        }
+        return null;
+    }
+
+    /*
+     * 提交,审核,过账之前的限制
+     */
+    private String checkCommit(String caller, Object pi_id) {
+        checkIOMaPick(caller,pi_id);
+        if (!caller.equals("ProdInOut!AppropriationOut") && !caller.equals("ProdInOut!AppropriationIn")) {
+            baseDao.execute("update prodiodetail set pd_whcode=(select pi_whcode from prodinout where pd_piid=pi_id) where pd_piid="
+                    + pi_id + " and NVL(pd_whcode,' ')=' '");
+        }
+        if (caller.equals("ProdInOut!Make!Return") || caller.equals("ProdInOut!OutsideReturn")) {
+            baseDao.execute("update prodiodetail a set pd_prodmadedate=(select min(ba_date) from prodiodetail b left join batch on b.pd_batchid=ba_id where a.pd_ordercode=b.pd_ordercode and a.pd_prodcode=b.pd_prodcode and nvl(b.pd_batchcode,' ')<>' ' and ((b.pd_piclass ='生产领料单' and a.pd_piclass='生产退料单') or (b.pd_piclass ='委外领料单' and a.pd_piclass='委外退料单'))) where pd_piid="
+                    + pi_id + " and pd_prodmadedate is null");
+        }
+        baseDao.execute("update prodiodetail set pd_prodmadedate=(select pi_date from prodinout where pd_piid=pi_id) where pd_piid="
+                + pi_id + " and pd_prodmadedate is null");
+        if ("ProdInOut!CostChange".equals(caller)) {
+            baseDao.execute(
+                    "update prodiodetail set (pd_orderqty,pd_orderprice)=(select ba_remain,ba_price from batch where ba_code=pd_batchcode and pd_prodcode=ba_prodcode and ba_whcode=pd_whcode) where pd_piid=?",
+                    pi_id);
+            baseDao.execute(
+                    "update prodiodetail set pd_total=round(nvl(pd_orderqty,0)*(nvl(pd_price,0)-nvl(pd_orderprice,0)),2) where pd_piid=?",
+                    pi_id);
+        }
+        baseDao.execute("update prodiodetail set pd_qctype=(select ve_class from qua_verifyapplydetail left join qua_verifyapplydetaildet on ved_veid=ve_id where pd_qcid=ved_id) where pd_piid="
+                + pi_id + " and nvl(pd_qcid,0)<>0");
+        String dets = baseDao
+                .getJdbcTemplate()
+                .queryForObject(
+                        "select wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']') from ProdIODetail left  join product on pr_code=pd_prodcode  where pd_piid=? and NVL(pr_statuscode,' ')<>'AUDITED'",
+                        String.class, pi_id);
+        if (dets != null) {
+            return "明细行物料不存在或者状态不等于已审核,不允许进行当前操作!" + dets;
+        }
+        dets = baseDao
+                .getJdbcTemplate()
+                .queryForObject(
+                        "select wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']') from ProdIODetail where pd_piid=? and nvl(pd_whcode,' ')=' '",
+                        String.class, pi_id);
+        if (dets != null) {
+            return "明细行仓库为空,不允许进行当前操作!" + dets;
+        }
+        /**
+         * 限制当仓库编号不为空时,明细行仓库至少有一行与主记录一致;为空则不判断
+         */
+
+        /*
+         * 暂不启用该逻辑限制 int c = baseDao.getCountByCondition(
+         * "ProdInOut left join ProdIODetail on pi_id=pd_piid", "pi_id=" + pi_id
+         * +
+         * " and ((NVL(pd_whcode,' ')=nvl(pi_whcode,' ') AND pi_whcode IS NOT NULL) or pi_whcode is null )"
+         * ); if (c < 1) { BaseUtil.showError("无一明细仓库与主表仓库一致,不允许进行当前操作!"); }
+         */
+        if (!caller.equals("ProdInOut!StockProfit") && !caller.equals("ProdInOut!StockLoss")) {
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail inner join Prodinout on pd_piid=pi_id left join product on pr_code=pd_prodcode where "
+                                    + "pd_piid=? and round(pd_outqty+pd_inqty,0)<>pd_outqty+pd_inqty and pd_status=0 and NVL(pr_precision,0)=0  and NVL(pr_groupcode,' ')<>'用品' ",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "计算精度是0的物料不能以小数出入库!行号:" + dets;
+            }
+        }
+        if (baseDao.isDBSetting("sys","warehouseCheck") || baseDao.isDBSetting(caller, "warehouseCheck")) {
+            // 出入库单主记录与明细行仓库必须一致
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']') from ProdIODetail left join ProdInOut on pd_piid=pi_id where pi_id=? and (nvl(pi_whcode,' ')<>nvl(pd_whcode,' ') or nvl(pi_purpose,' ')<>nvl(pd_inwhcode,' '))",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "明细行仓库与当前单主表仓库不一致,不允许进行当前操作!" + dets;
+            }
+        }
+        dets = baseDao
+                .getJdbcTemplate()
+                .queryForObject(
+                        "select wmsys.wm_concat(pd_piclass||':'||pd_inoutno||',行:'||pd_pdno||',仓库:'||pd_whcode) from prodiodetail left join warehouse on wh_code=pd_whcode where pd_piid=? and nvl(pd_whcode,' ')<>' ' and nvl(wh_statuscode,' ')='DISABLE'",
+                        String.class, pi_id);
+        if (dets != null) {
+            return "仓库已禁用,不允许进行当前操作!" + dets;
+        }
+        dets = baseDao
+                .getJdbcTemplate()
+                .queryForObject(
+                        "select wmsys.wm_concat(pd_piclass||':'||pd_inoutno||',行:'||pd_pdno||',仓库:'||pd_whcode) from prodiodetail left join warehouse on wh_code=pd_whcode where pd_piid=? and nvl(pd_whcode,' ')<>' ' and pd_whcode not in (select wh_code from warehouse)",
+                        String.class, pi_id);
+        if (dets != null) {
+            return "仓库不存在,不允许进行当前操作!" + dets;
+        }
+        String maxprice = baseDao.getDBSetting(caller, "maxPrice");
+        if (maxprice != null) {
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wmsys.wm_concat(pd_piclass||':'||pd_inoutno||',行:'||pd_pdno||',单价:'||pd_price) from prodiodetail where pd_piid=? and nvl(pd_price,0)>?",
+                            String.class, pi_id, maxprice);
+            if (dets != null) {
+                return "单价超过设置上限,不允许进行当前操作!" + dets;
+            }
+        }
+        if ("ProdInOut!Picking".equals(caller) || "ProdInOut!Make!Give".equals(caller) || "ProdInOut!Make!Return".equals(caller)
+                || "ProdInOut!OutsidePicking".equals(caller) || "ProdInOut!OutsideReturn".equals(caller)
+                || "ProdInOut!OSMake!Give".equals(caller) || "ProdInOut!Make!In".equals(caller)
+                || "ProdInOut!PartitionStockIn".equals(caller) || "ProdInOut!OutsideCheckIn".equals(caller)
+                || "ProdInOut!OutesideCheckReturn".equals(caller)) {
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail where pd_piid=? and pd_piclass in ('生产领料单','生产补料单','生产退料单','委外领料单','委外退料单','委外补料单') and not exists (select 1 from make left join makematerial on ma_id=mm_maid where pd_ordercode=ma_code and pd_orderdetno=mm_detno)",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "工单+序号不存在,不允许进行当前操作!行号:" + dets;
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail where pd_piid=? and pd_piclass in ('生产领料单','生产补料单','生产退料单','委外领料单','委外退料单','委外补料单') and not exists (select 1 from make left join makematerial on ma_id=mm_maid where pd_ordercode=ma_code and pd_orderdetno=mm_detno and pd_prodcode=mm_prodcode) and "
+                                    + " not exists(select 1 from make inner join makematerial on ma_id= mm_maid inner join makematerialreplace on mm_id = mp_mmid where pd_ordercode=ma_code and pd_orderdetno=mm_detno and pd_prodcode=mp_prodcode)",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "工单+序号+物料编号不存在,不允许进行当前操作!行号:" + dets;
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join make on ma_code=pd_ordercode where "
+                                    + "pd_piid=? and nvl(pi_cardcode,' ')<>nvl(ma_vendcode,' ') and pd_piclass in ('委外退料单','委外验退单','委外领料单') "
+                                    + "and nvl(pd_ordercode,' ')<>' ' and not exists (select 1 from makecraft where mc_code=pd_jobcode and mc_tasktype='工序委外单')",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "明细委外单委外商与单据委外商不一致,不允许进行当前操作!行号:" + dets;
+            }
+
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail where nvl(pd_jobcode,' ')<>' ' and not exists (select 1 from makecraft where pd_jobcode=mc_code "
+                                    + "and mc_tasktype='工序委外单') and pd_piclass in ('委外退料单','委外验退单','委外领料单') and pd_piid=?", String.class,
+                            pi_id);
+            if (dets != null) {
+                return "明细工序委外单不存在,不允许进行当前操作!行号:" + dets;
+            }
+
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join makecraft on mc_code=pd_jobcode where "
+                                    + "pd_piid=? and nvl(pi_cardcode,' ')<>nvl(mc_vendcode,' ') and pd_piclass in ('委外退料单','委外验退单','委外领料单') "
+                                    + "and nvl(pd_ordercode,' ')<>' ' and exists (select 1 from makecraft where mc_code=pd_jobcode and mc_tasktype='工序委外单') ",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "委外商与工序委外单委外商不一致,不允许进行当前操作!行号:" + dets;
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat('工单:'||pd_ordercode||'序号:'||pd_orderdetno) from (select pd_ordercode,pd_orderdetno,sum(pd_inqty) pd_inqty,max(mm_yqty)mm_yqty,max(mm_gqty)mm_gqty from ProdIODetail left join make on ma_code=pd_ordercode left join makematerial on ma_id=mm_maid and mm_detno=pd_orderdetno where pd_piid=? and pd_piclass='拆件入库单'  group by pd_ordercode,pd_orderdetno)A where mm_yqty+pd_inqty>mm_gqty and mm_gqty>0 ",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "拆件入库数不能大于工单允许可拆件入库数!" + dets;
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat('行号:'||pd_pdno||'工单:'||pd_ordercode) from ProdIODetail left join make on ma_code=pd_ordercode  left join makekind ON mk_name=ma_kind where pd_piid=? and pd_piclass='拆件入库单'  and  mk_type='S'",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "拆件单明细中存在制造单的类型是标准!" + dets;
+            }
+            boolean allowBackAfterFinish = false;
+            if ("ProdInOut!Make!Return".equals(caller)) { // @add xst 20180830
+                // 反馈:2018080651
+                // ,制造单已结案允许退料
+                allowBackAfterFinish = baseDao.isDBSetting("Make!Base", "allowBackAfterFinish");
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from prodinout left join  ProdIODetail  on pd_piid=pi_id  left join make on ma_code=pd_ordercode  where  pd_piid=? and (NVL(ma_statuscode,' ')<>'AUDITED' AND ('"
+                                    + allowBackAfterFinish
+                                    + "'='false' or (pd_piclass='生产退料单' and ma_statuscode<>'FINISH'))) and pi_statuscode='UNPOST' and pd_piclass in ('完工入库单','拆件入库单','委外验收单','生产领料单','生产补料单','生产退料单','委外领料单','委外退料单','委外补料单') and nvl(pd_ordercode,' ')<>' ' ",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "工单不存在或者状态不等于已审核,不允许进行当前操作!行号:" + dets;
+            }
+
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join make on ma_code=pd_ordercode  left join MakeKind on mk_name=ma_kind "
+                                    + "where pd_piid=? and nvl(pd_whcode,' ')<>' ' and nvl(mk_whcodes,' ')<>' ' and pd_whcode not in (select column_value from table(parsestring(mk_whcodes,'#'))) "
+                                    + "and pd_piclass in ('完工入库单','委外验收单') and nvl(pd_ordercode,' ')<>' ' and nvl(ProdIODetail.pd_status,0)=0",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "明细仓库与工单类型允许入库仓库不一致,不允许进行当前操作!行号:" + dets;
+            }
+        }
+        if ("ProdInOut!OutesideCheckReturn".equals(caller)) {
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail where pd_piid=? and pd_piclass in ('委外验退单') and not exists (select 1 from make where pd_ordercode=ma_code and pd_prodcode=ma_prodcode) "
+                                    + "and not exists (select 1 from makecraft where pd_jobcode=mc_code and mc_tasktype='工序委外单' and pd_prodcode=mc_prodcode)",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "委外单+物料编号不存在,不允许进行当前操作!行号:" + dets;
+            }
+
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join Make on ma_code=pd_ordercode where pd_piid=? and nvl(pi_currency,' ')<>nvl(ma_currency,' ')"
+                                    + " and not exists (select 1 from makecraft where pd_jobcode=mc_code and mc_tasktype='工序委外单')"
+                                    + " and pd_piclass in ('委外验退单') and nvl(pd_ordercode,' ')<>' '", String.class, pi_id);
+            if (dets != null) {
+                return "明细委外单与单据币别不一致,不允许进行当前操作!行号:" + dets;
+            }
+
+            dets = baseDao.getJdbcTemplate().queryForObject(
+                    "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join MakeCraft on mc_makecode=pd_ordercode "
+                            + " and mc_code =pd_jobcode where pd_piid=? and nvl(pi_currency,' ')<>nvl(mc_currency,' ')"
+                            + " and exists (select 1 from makecraft where pd_jobcode=mc_code and mc_tasktype='工序委外单')"
+                            + " and pd_piclass in ('委外验退单') and nvl(pd_ordercode,' ')<>' '", String.class, pi_id);
+            if (dets != null) {
+                return "明细委外单与单据币别不一致,不允许进行当前操作!行号:" + dets;
+            }
+        }
+        if ("ProdInOut!PurcCheckin".equals(caller) || "ProdInOut!PurcCheckout".equals(caller) || "ProdInOut!DefectIn".equals(caller)
+                || "ProdInOut!DefectOut".equals(caller)) {
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pi_inoutno) from ProdInOut where pi_id=? and pi_class in ('采购验收单','采购验退单') and (pi_cardcode,pi_title) not in (select ve_code,ve_name from vendor)",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "单据中供应商编号,供应商名称在供应商资料中不存在!";
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pi_inoutno) from ProdInOut where pi_id=? and pi_class in ('采购验收单','采购验退单') and (pi_receivecode,pi_receivename) not in (select ve_code,ve_name from vendor)",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "单据中应付供应商编号,应付供应商名称在供应商资料中不存在!";
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail where pd_piid=?"
+                                    + " and pd_piclass in ('采购验收单','采购验退单') and nvl(pd_ordercode,' ')<>' ' and  not exists (select pd_code,pd_detno from purchasedetail where pd_code=ProdIODetail.pd_ordercode and pd_detno=ProdIODetail.pd_orderdetno)",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "采购单号+采购序号不存在,不允许进行当前操作!行号:" + dets;
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail where pd_piid=?"
+                                    + " and  not exists(select pd_code,pd_detno from purchasedetail p  where p.pd_prodcode=ProdIODetail.pd_prodcode and p.pd_code=ProdIODetail.pd_ordercode and  p.pd_detno=ProdIODetail.pd_orderdetno ) and pd_piclass in ('采购验收单','采购验退单') and nvl(pd_ordercode,' ')<>' ' ",
+                            String.class, pi_id);
+            if (dets != null) {
+                Boolean bo = baseDao.isDBSetting("VerifyApply", "verifyApplyAllowPre"); // 允许收替代料
+                if (bo) {
+                    SqlRowList rsReq = baseDao
+                            .queryForRowSet(
+                                    "select pd_repprodcode,pd_detno,pd_code from purchasedetail A where exists(select 1 from prodiodetail B where B.pd_piid=? and A.pd_code=B.pd_ordercode and A.pd_detno=B.pd_orderdetno )",
+                                    pi_id);
+                    if (!rsReq.hasNext()) {
+                        return "采购单号+采购序号不存在!";
+                    }
+                    while (rsReq.next()) {
+                        if (rsReq.getString("pd_repprodcode") != null && !("").equals(rsReq.getString("pd_repprodcode"))) {
+                            StringBuffer codes = new StringBuffer();
+                            String[] arr = rsReq.getString("pd_repprodcode").split(",");
+                            codes.append("'");
+                            for (int i = 0; i < arr.length; i++) {
+                                if (i < arr.length - 1) {
+                                    codes.append(arr[i] + "','");
+                                } else {
+                                    codes.append(arr[i] + "'");
+                                }
+                            }
+                            dets = baseDao
+                                    .getJdbcTemplate()
+                                    .queryForObject(
+                                            " select wm_concat(pd_pdno) from ProdIODetail where pd_piid=? and pd_ordercode ='"
+                                                    + rsReq.getString("pd_code")
+                                                    + "' and pd_orderdetno="
+                                                    + rsReq.getInt("pd_detno")
+                                                    + " and  not exists(select pd_code,pd_detno from purchasedetail p  where  p.pd_code=ProdIODetail.pd_ordercode and  p.pd_detno=ProdIODetail.pd_orderdetno and (p.pd_prodcode=ProdIODetail.pd_prodcode or ProdIODetail.pd_prodcode in ("
+                                                    + codes + ")) ) and pd_piclass in ('采购验收单','采购验退单') and nvl(pd_ordercode,' ')<>' ' ",
+                                            String.class, pi_id);
+                            if (dets != null) {
+                                return "采购单号+采购序号+物料不存在,不允许进行当前操作!行号:" + dets;
+                            }
+                        }
+                    }
+                }
+                if (dets != null) {
+                    return "采购单号+采购序号+物料不存在,不允许进行当前操作!行号:" + dets;
+                }
+            }
+            dets = baseDao.getJdbcTemplate().queryForObject(
+                    "select wm_concat(pd_pdno) from ProdIODetail left join PurchaseDetail on pd_ordercode=pd_code and pd_orderdetno=pd_detno where "
+                            + "pd_piid=? and nvl(pd_mrpstatuscode,' ') in ('FREEZE','FINISH') and pd_piclass in ('采购验收单','采购验退单') "
+                            + "and nvl(pd_ordercode,' ')<>' '", String.class, pi_id);
+            if (dets != null) {
+                return "采购单明细已冻结或者已结案,不允许进行当前操作!行号:" + dets;
+            }
+            dets = baseDao.getJdbcTemplate().queryForObject(
+                    "select wm_concat(pd_pdno) from ProdIODetail left join PurchaseDetail on pd_ordercode=pd_code and pd_orderdetno=pd_detno where "
+                            + "pd_piid=? and nvl(pd_mrpstatuscode,' ') in ('FREEZE','FINISH') and pd_piclass in ('不良品入库单','不良品出库单') "
+                            + "and nvl(pd_ordercode,' ')<>' ' and nvl(pd_qctype,' ')='采购检验单'", String.class, pi_id);
+            if (dets != null) {
+                return "采购单明细已冻结或者已结案,不允许进行当前操作!行号:" + dets;
+            }
+            dets = baseDao.getJdbcTemplate().queryForObject(
+                    "select wm_concat(pd_pdno) from ProdIODetail left join Make on pd_ordercode=ma_code where "
+                            + "pd_piid=? and nvl(ma_statuscode,' ') in ('FREEZE','FINISH') and pd_piclass in ('不良品入库单','不良品出库单') "
+                            + "and nvl(pd_ordercode,' ')<>' ' and nvl(pd_qctype,' ')='委外检验单'", String.class, pi_id);
+            if (dets != null) {
+                return "明细行委外单已冻结或者已结案,不允许进行当前操作!行号:" + dets;
+            }
+            if (!baseDao.isDBSetting(caller, "noLimitVendor")) {
+                dets = baseDao.getJdbcTemplate().queryForObject(
+                        "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join Purchase on pu_code=pd_ordercode where "
+                                + "pd_piid=? and nvl(pi_cardcode,' ')<>nvl(pu_vendcode,' ') and pd_piclass in ('采购验收单','采购验退单') "
+                                + "and nvl(pd_ordercode,' ')<>' '", String.class, pi_id);
+                if (dets != null) {
+                    return "明细采购单与单据供应商不一致,不允许进行当前操作!行号:" + dets;
+                }
+            }
+            if (!baseDao.isDBSetting(caller, "allowARCust")) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join Purchase on pu_code=pd_ordercode where "
+                                        + "pd_piid=? and nvl(pi_receivecode,' ')<>nvl(pu_receivecode,' ') and pd_piclass in ('采购验收单','采购验退单') and nvl(pd_ordercode,' ')<>' '",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "明细采购单与单据应付供应商不一致,不允许进行当前操作!行号:" + dets;
+                }
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join Purchase on pu_code=pd_ordercode where pd_piid=? and nvl(pi_currency,' ')<>nvl(pu_currency,' ')"
+                                        + " and pd_piclass in ('采购验收单','采购验退单') and nvl(pd_ordercode,' ')<>' '", String.class, pi_id);
+                if (dets != null) {
+                    return "明细采购单与单据币别不一致,不允许进行当前操作!行号:" + dets;
+                }
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat('行号:'||pd_pdno||'收料合格数量:'||ved_okqty) from ProdIODetail left join QUA_VerifyApplyDetailDet on pd_qcid=ved_id where pd_piid=? and nvl(pd_qcid,0)<>0 and nvl(pd_inqty,0)>nvl(ved_okqty,0) and pd_piclass in ('采购验收单')",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "明细行入库数量大于收料合格数量!" + dets;
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat('行号:'||pd_pdno||'收料不合格数量:'||ved_ngqty) from ProdIODetail left join QUA_VerifyApplyDetailDet on pd_qcid=ved_id where pd_piid=? and nvl(pd_qcid,0)<>0 and nvl(pd_inqty,0)>nvl(ved_ngqty,0) and pd_piclass in ('不良品入库单')",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "明细行入库数量大于收料不合格数量!" + dets;
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join Purchase on pu_code=pd_ordercode left join purchasekind on pk_name=pu_kind "
+                                    + "where pd_piid=? and nvl(pd_whcode,' ')<>' ' and nvl(pk_whcodes,' ')<>' ' and pd_whcode not in (select column_value from table(parsestring(pk_whcodes,'#'))) "
+                                    + "and pd_piclass in ('采购验收单') and nvl(pd_ordercode,' ')<>' '", String.class, pi_id);
+            if (dets != null) {
+                return "明细仓库与采购单类型允许入仓库不一致,不允许进行当前操作!行号:" + dets;
+            }
+            if ("ProdInOut!PurcCheckin".equals(caller)) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail left join PurchaseDetail on PurchaseDetail.pd_code=ProdIODetail.pd_ordercode and PurchaseDetail.pd_detno=ProdIODetail.pd_orderdetno "
+                                        + "where pd_piid=? and nvl(PurchaseDetail.pd_yqty,0)>nvl(PurchaseDetail.pd_qty,0)-nvl(PurchaseDetail.pd_frozenqty,0) "
+                                        + "and pd_piclass in ('采购验收单') and nvl(ProdIODetail.pd_ordercode,' ')<>' '", String.class, pi_id);
+                if (dets != null) {
+                    return "明细采购订单已转数大于采购订单数量-已冻结数量,不允许进行当前操作!行号:" + dets;
+                }
+            }
+        }
+        if ("ProdInOut!SaleBorrow".equals(caller) || "ProdInOut!OtherPurcIn".equals(caller)) {
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']') from ProdIODetail left join Prodinout on pd_piid=pi_id left join BorrowCargoType on bt_name=pi_outtype "
+                                    + "where pd_piid=? and nvl(pd_whcode,' ')<>' ' and nvl(bt_whcodes,' ')<>' ' and pd_whcode not in (select column_value from table(parsestring(bt_whcodes,'#'))) "
+                                    + "and pd_piclass in ('借货出货单','其它采购入库单')", String.class, pi_id);
+            if (dets != null) {
+                return "明细仓库与借货类型允许出入仓库不一致,不允许进行当前操作!" + dets;
+            }
+        }
+        if ("ProdInOut!Sale".equals(caller) || "ProdInOut!SaleReturn".equals(caller) || "ProdInOut!OtherOut".equals(caller)
+                || "ProdInOut!ExchangeOut".equals(caller) || "ProdInOut!SaleAppropriationOut".equals(caller)) {
+            if (baseDao.isDBSetting(caller, "allowDifProd")) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail where pd_piid=? and not exists(select sd_code,sd_detno from saledetail where sd_code=pd_ordercode and sd_detno=pd_orderdetno and sd_statuscode='AUDITED')"
+                                        + " and pd_piclass in ('出货单','销售退货单','其它出库单','换货出库单','销售拨出单') and nvl(pd_ordercode,' ')<>' ' and nvl(pd_ioid,0)=0",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "销售单号+销售序号不存在或者状态不等于已审核,不允许进行当前操作!行号:" + dets;
+                }
+            } else if (baseDao.isDBSetting(caller, "SaleWithProdRelation")) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail where pd_piid=? and "
+                                        + "not exists (select sd_code,sd_detno from saledetail left join ProdRelation on (sd_prodcode=prr_soncode or (nvl(prr_ifonewa,0)=0 and sd_prodcode=prr_repcode)) "
+                                        + "where sd_code=pd_ordercode and sd_detno=pd_orderdetno and (nvl(sd_prodcode,' ')=nvl(pd_prodcode,' ') or nvl(prr_repcode ,' ')=nvl(pd_prodcode,' ') or nvl(prr_soncode ,' ')=nvl(pd_prodcode,' ')))"
+                                        + "	and pd_piclass in ('出货单','销售退货单','其它出库单','换货出库单','销售拨出单') and nvl(pd_ordercode,' ')<>' ' and nvl(pd_ioid,0)=0",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "销售单号+销售序号+物料编号不存在或者状态不等于已审核,不允许进行当前操作!行号:" + dets;
+                }
+            } else {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail where pd_piid=? and not exists(select sd_code,sd_detno from saledetail where sd_prodcode=pd_prodcode and sd_code=pd_ordercode and sd_detno=pd_orderdetno )"
+                                        + " and pd_piclass in ('出货单','销售退货单','其它出库单','换货出库单','销售拨出单') and nvl(pd_ordercode,' ')<>' ' and nvl(pd_ioid,0)=0",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "销售单号+销售序号+物料编号不存在,不允许进行当前操作!行号:" + dets;
+                }
+            }
+            if (baseDao.isDBSetting("sys","useMachineNo")) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat('物料'||pd_prodcode||'总数量'||qty||'已采集数'||yqty) from (SELECT pd_piid, pd_prodcode, pd_inoutno, nvl(sum(nvl(pd_inqty,0)+nvl(pd_outqty,0)),0) qty from prodiodetail where pd_piid=? group by pd_piid,pd_inoutno,pd_prodcode) left join (select pim_piid,pim_prodcode,count(1) yqty from prodiomac group by pim_piid,pim_prodcode) on pim_piid=pd_piid and pim_prodcode=pd_prodcode where nvl(qty,0)<>nvl(yqty,0) and nvl(yqty,0)<>0",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "单据+物料数量跟机器号数量不一致,不允许进行当前操作!行号:" + dets;
+                }
+            }
+            if (!(baseDao.isDBSetting("ProdInOut!Sale", "custatus"))) {
+                if (baseDao.isDBSetting("Sale", "zeroOutWhenHung")) {// 客户挂起时,订单单价为0不限制出货
+                    dets = baseDao
+                            .getJdbcTemplate()
+                            .queryForObject(
+                                    "select wm_concat(pi_cardcode) from ProdInOut left join customer on pi_cardcode=cu_code where pi_id = ? and pi_class in ('出货单') "
+                                            + "and cu_status='挂起' and not exists (select 1 from prodiodetail left join saledetail on pd_ordercode=sd_code and pd_orderdetno=sd_detno"
+                                            + " where pd_piid=pi_id and nvl(pd_ordercode,' ')<>' ' and nvl(sd_price,0)=0)", String.class,
+                                    pi_id);
+                    if (dets != null) {
+                        return "客户资料状态为挂起,且订单单价不为0,不允许进行当前操作!客户号:" + dets;
+                    }
+                } else {
+                    dets = baseDao
+                            .getJdbcTemplate()
+                            .queryForObject(
+                                    "select wm_concat(pi_cardcode) from ProdInOut left join customer on pi_cardcode=cu_code where pi_id = ? and pi_class in ('出货单','其它出库单','换货出库单','销售拨出单') and cu_status='挂起'",
+                                    String.class, pi_id);
+                    if (dets != null) {
+                        return "客户资料状态为挂起,不允许进行当前操作!客户号:" + dets;
+                    }
+                }
+
+            }
+            if (!baseDao.isDBSetting(caller, "allowARCust")) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join Sale on sa_code=pd_ordercode where pd_piid=? and nvl(pi_cardcode,' ')<>nvl(sa_custcode,' ')"
+                                        + " and pd_piclass in ('出货单','销售退货单','其它出库单','换货出库单','销售拨出单') and nvl(pd_ordercode,' ')<>' ' and nvl(pd_ioid,0)=0",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "明细销售单与单据客户不一致,不允许进行当前操作!行号:" + dets;
+                }
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join Sale on sa_code=pd_ordercode where pd_piid=? and nvl(pi_arcode,' ')<>nvl(sa_apcustcode,' ')"
+                                        + " and pd_piclass in ('出货单','销售退货单') and nvl(pd_ordercode,' ')<>' '", String.class, pi_id);
+                if (dets != null) {
+                    return "明细销售单与单据应收客户不一致,不允许进行当前操作!行号:" + dets;
+                }
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join Sale on sa_code=pd_ordercode where pd_piid=? and nvl(pi_currency,' ')<>nvl(sa_currency,' ')"
+                                        + " and pd_piclass in ('出货单','销售退货单') and nvl(pd_ordercode,' ')<>' '", String.class, pi_id);
+                if (dets != null) {
+                    return "明细销售单与单据币别不一致,不允许进行当前操作!行号:" + dets;
+                }
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pi_inoutno) from ProdInOut where pi_id=? and pi_class in ('出货单','销售退货单') and (pi_cardcode,pi_title) not in (select cu_code,cu_name from customer)",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "单据中客户编号,客户名称在客户资料中不存在!";
+            }
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pi_inoutno) from ProdInOut where pi_id=? and pi_class in ('出货单','销售退货单') and (pi_arcode,pi_arname) not in (select cu_code,cu_name from customer)",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "单据中应收客户编号,应收客户名称在客户资料中不存在!";
+            }
+            // 销售退货单:退货数量,如退货数量+其它未过账的退货单数量大于销售订单出货数
+            /**
+             * 需考虑状态
+             */
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail b left join SaleDetail on sd_code=pd_ordercode and sd_detno=pd_orderdetno where pd_piid=? and pd_status<99 and pd_piclass='销售退货单' and nvl(pd_ordercode,' ')<>' ' and nvl(pd_inqty,0) + (select nvl(sum(nvl(a.pd_inqty,0)),0) from ProdIODetail a where a.pd_piclass='销售退货单' and a.pd_status<99 and a.pd_ordercode=b.pd_ordercode and a.pd_orderdetno=b.pd_orderdetno and a.pd_id <> b.pd_id) > nvl(sd_sendqty,0)",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "本次退货数+其它退货数合计大于订单的已发货数量,不允许进行当前操作!行号:" + dets;
+            }
+            if ("ProdInOut!SaleAppropriationOut".equals(caller) || "ProdInOut!OtherOut".equals(caller)) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']') from ProdIODetail where pd_piid=? and (pd_plancode,pd_forecastdetno) not in (select sd_code, sd_detno from saleforecastdetail,saleforecast where sf_id=sd_sfid and sf_code=pd_plancode and sd_detno=pd_forecastdetno and sd_statuscode='AUDITED') and nvl(pd_plancode,' ')<>' '",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "明细行预测单号+预测序号不存在或者状态不等于已审核,不允许进行当前操作!!" + dets;
+                }
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']') from ProdIODetail where pd_piid=? and (pd_plancode,pd_forecastdetno) in (select sd_code, sd_detno from saleforecastdetail where nvl(sd_qty,0)=0) and nvl(pd_plancode,' ')<>' '",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "明细行预测单号+预测序号预测数量等于0,不允许进行当前操作!" + dets;
+                }
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']') from ProdIODetail left join SaleDetail on pd_ordercode=sd_code and pd_orderdetno=sd_detno where pd_piid=? and pd_piclass in ('销售拨出单','其它出库单') and nvl(pd_outqty+pd_inqty,0)>nvl(sd_qty,0)-nvl(sd_yqty,0) and nvl(pd_ordercode,' ')<>' ' and nvl(pd_ioid,0)=0 and nvl(pd_snid,0)=0",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "明细行销售单号+销售序号数量大于订单未发货数,不允许进行当前操作!" + dets;
+                }
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']') from ProdIODetail where pd_piid=? and pd_piclass='销售拨出单' and pd_plancode not in (select a.sf_code from saleforecast a left join saleforecastkind b on (a.sf_kind=b.sf_name or a.sf_kind=b.sf_code) where a.sf_code=pd_plancode and sf_clashoption in ('SEND','发货冲销')) and nvl(pd_plancode,' ')<>' '",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "预测单录入错误,该预测类型不属于发货冲销!" + dets;
+                }
+            }
+        }
+//		if ("ProdInOut!AppropriationOut".equals(caller) || "ProdInOut!AppropriationIn".equals(caller)
+//				|| "ProdInOut!SaleAppropriationOut".equals(caller) || "ProdInOut!SaleAppropriationIn".equals(caller)) {
+//			dets = baseDao
+//					.getJdbcTemplate()
+//					.queryForObject(
+//							"select wm_concat(pd_pdno) from ProdIODetail,warehouse w1,warehouse w2 where pd_piid=? and pd_whcode=w1.wh_code and pd_inwhcode=w2.wh_code and nvl(w1.wh_nocost,0)<>nvl(w2.wh_nocost,0)",
+//							String.class, pi_id);
+//			if (dets != null) {
+//				return "有值和无值仓之间不能相互调拨!行号:" + dets);
+//			}
+//		}
+        SqlRowList rs = baseDao.queryForRowSet("select * from prodiodetail where pd_piid=?", pi_id);
+        StringBuffer sb = new StringBuffer();
+        while (rs.next()) {
+            int pdid = rs.getInt("pd_id");
+            int ioid = rs.getGeneralInt("pd_ioid");
+            double tqty = rs.getGeneralDouble("pd_inqty") + rs.getGeneralDouble("pd_outqty");
+            double yqty = 0.0;
+            if (ioid > 0) {
+                yqty = baseDao.getSummaryByField("Prodiodetail", "nvl(pd_outqty,0) + nvl(pd_inqty,0)", "pd_ioid=" + ioid + " and pd_id<>"
+                        + pdid);
+                Object[] source = baseDao.getFieldsDataByCondition("Prodiodetail", new String[] { "nvl(pd_outqty,0)", "nvl(pd_inqty,0)",
+                        "pd_piclass", "pd_inoutno" }, "pd_id=" + ioid);
+                if (source != null) {
+                    if (yqty + tqty > Double.parseDouble(source[0].toString()) + Double.parseDouble(source[1].toString())) {
+                        sb.append("行号:" + rs.getInt("pd_pdno") + ",数量:" + tqty + ",无法转出." + source[2] + "[" + source[3] + "]已转数量:" + yqty
+                                + ",本次数量:" + tqty + "<hr/>");
+                    }
+                }
+            }
+        }
+        if (sb.length() > 0) {
+            return sb.toString();
+        }
+        // 保税信息判断
+        if (baseDao.isDBSetting("sys","ioWHBondedCheck")) {
+            if ("ProdInOut!PurcCheckin".equals(caller) || "ProdInOut!PurcCheckout".equals(caller)) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join PurchaseDetail on pd_code=pd_ordercode and pd_detno=pd_orderdetno left join warehouse on ProdIODetail.pd_whcode=wh_code where pd_piid=? and nvl(PurchaseDetail.pd_bonded,0)<>nvl(wh_bonded,0)"
+                                        + " and pd_piclass in ('采购验收单','采购验退单') and nvl(pd_ordercode,' ')<>' '", String.class, pi_id);
+                if (dets != null) {
+                    return "采购单的保税属性与仓库的保税属性不一致,不允许进行当前操作!行号:" + dets;
+                }
+            }
+            if ("ProdInOut!OutesideCheckReturn".equals(caller) || "ProdInOut!OutsideCheckIn".equals(caller)) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join Make on ma_code=pd_ordercode left join warehouse on pd_whcode=wh_code where pd_piid=? and nvl(ma_bonded,0)<>nvl(wh_bonded,0)"
+                                        + " and pd_piclass in ('委外验退单','委外验收单') and nvl(pd_ordercode,' ')<>' '", String.class, pi_id);
+                if (dets != null) {
+                    return "委外单的保税属性与仓库的保税属性不一致,不允许进行当前操作!行号:" + dets;
+                }
+            }
+            if ("ProdInOut!Make!In".equals(caller) || "ProdInOut!PartitionStockIn".equals(caller)) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail left join Prodinout on pd_piid=pi_id left join Make on ma_code=pd_ordercode left join warehouse on pd_whcode=wh_code where pd_piid=? and nvl(ma_bonded,0)<>nvl(wh_bonded,0)"
+                                        + " and pd_piclass in ('完工入库单','拆件入库单') and nvl(pd_ordercode,' ')<>' '", String.class, pi_id);
+                if (dets != null) {
+                    return "工单的保税属性与仓库的保税属性不一致,不允许进行当前操作!行号:" + dets;
+                }
+            }
+            if ("ProdInOut!Make!Give".equals(caller) || "ProdInOut!Make!Return".equals(caller) || "ProdInOut!Picking".equals(caller)
+                    || "ProdInOut!OSMake!Give".equals(caller) || "ProdInOut!OutsideReturn".equals(caller)
+                    || "ProdInOut!OutsidePicking".equals(caller)) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']') from ProdIODetail left join Prodinout on pd_piid=pi_id left join Make on ma_code=pd_ordercode left join warehouse on pd_whcode=wh_code where pd_piid=? and nvl(ma_bonded,0)=0 and nvl(wh_bonded,0)<>0"
+                                        + " and pd_piclass in ('委外补料单','委外退料单','委外领料单') and nvl(pd_ordercode,' ')<>' '", String.class,
+                                pi_id);
+                if (dets != null) {
+                    return "委外单保税属性是非保税,不能发生仓库保税属性是保税的单据!" + dets;
+                }
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']') from ProdIODetail left join Prodinout on pd_piid=pi_id left join Make on ma_code=pd_ordercode left join warehouse on pd_whcode=wh_code where pd_piid=? and nvl(ma_bonded,0)=0 and nvl(wh_bonded,0)<>0"
+                                        + " and pd_piclass in ('生产补料单','生产退料单','生产领料单') and nvl(pd_ordercode,' ')<>' '", String.class,
+                                pi_id);
+                if (dets != null) {
+                    return "工单保税属性是非保税,不能发生仓库保税属性是保税的单据!" + dets;
+                }
+            }
+            if ("ProdInOut!SaleAppropriationOut".equals(caller) || "ProdInOut!AppropriationOut".equals(caller)) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']') from ProdIODetail left join Prodinout on pd_piid=pi_id left join warehouse a on a.wh_code=pd_whcode left join warehouse b on b.wh_code=pd_inwhcode where pd_piid=? and nvl(a.wh_bonded,0)<>nvl(b.wh_bonded,0)"
+                                        + " and pd_piclass in ('拨出单','销售拨出单') and nvl(pd_whcode,' ')<>' ' and nvl(pd_inwhcode,' ')<>' '",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "拨出仓库与拨入仓库仓库的保税属性不一致,不能进行当前操作!" + dets;
+                }
+            }
+        }
+
+        // @add20180605 Q:2018050126 最后一张完工入库单或者委外验收单,提交、审核、过账之前限制,不允许存在未过账
+        // 领、退、补单据,未审核的报废单,未过账的委外验退单
+        if (("ProdInOut!OutsideCheckIn".equals(caller) || "ProdInOut!Make!In".equals(caller))
+                && baseDao.isDBSetting(caller, "checkRelBillsStatus")) {
+            // 判断哪些工单是最后一张完工入库单
+            rs = baseDao
+                    .queryForRowSet(
+                            "select pd_ordercode,pd_pdno from (select pd_ordercode,sum(pd_inqty)inqty,wm_concat(pd_pdno)pd_pdno from prodiodetail  where "
+                                    + "pd_piid=? and pd_piclass in('完工入库单','委外验收单') group by pd_ordercode) A left join make on ma_code=A.pd_ordercode "
+                                    + "where nvl(ma_madeqty,0)+inqty>=ma_qty", pi_id);
+            String errors = null;
+            while (rs.next()) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pi_class||':'||pi_inoutno) from prodiodetail,ProdInOut WHERE pd_piid=pi_id AND pi_id<>? and pd_ordercode = ? AND pi_statuscode = 'UNPOST' AND pd_status=0 AND (pd_piclass LIKE '生产%' OR pd_piclass LIKE '委外%' OR pd_piclass LIKE '完工%') and rownum<15",
+                                String.class, pi_id, rs.getString("pd_ordercode"));
+                if (dets != null) {
+                    errors = "行号:" + rs.getString("pd_pdno") + ",工单:" + rs.getString("pd_ordercode") + "存在关联未过账单据!" + dets;
+                }
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "SELECT wm_concat(ms_code) FROM MakeScrapdetail,MakeScrap WHERE md_msid=ms_id AND md_mmcode=? AND ms_statuscode in ('ENTERING','COMMITED') AND nvl(md_status,0)=0",
+                                String.class, rs.getString("pd_ordercode"));
+                if (dets != null) {
+                    if (errors != null) {
+                        errors += "<br>未审核的报废单:" + dets;
+                    } else {
+                        errors = "行号:" + rs.getString("pd_pdno") + ",工单:" + rs.getString("pd_ordercode") + "存在关联未审核的报废单:" + dets;
+                    }
+                }
+                if (errors != null && !"".equals(errors)) {
+                    return errors;
+                }
+            }
+        }
+        if (baseDao.isOut(caller)) {
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from (select pd_pdno from ProdIODetail where pd_piid=? and nvl(pd_outqty,0)>0 and nvl(pd_prodcode,' ')<>' ' and nvl(pd_whcode,' ')<>' ' and nvl(pd_batchcode,' ')<>' '"
+                                    + "and not exists(select 1 from batch where pd_prodcode=ba_prodcode and pd_whcode=ba_whcode and pd_batchcode=ba_code) order by pd_pdno)",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "物料编号+仓库编号+批号不存在,不允许进行当前操作!行号:" + dets;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 校验批次是否重复
+     *
+     * @param caller
+     * @param pi_id
+     */
+    private String checkBatch(String caller, Object pi_id) {
+        if (baseDao.isIn(caller)) {
+            // 入库单据,同一物料同仓库不能同时入两次相同的批号
+            SqlRowList rs = baseDao
+                    .queryForRowSet("select  count(1)n, wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']')detno from (select pd_batchcode,pd_whcode,pd_prodcode,min(pd_pdno)pd_pdno,min(pd_inoutno)pd_inoutno,min(pd_piclass)pd_piclass,count(1)c from  ProdIODetail where pd_piid="
+                            + pi_id + " and pd_batchcode<>' ' group by pd_batchcode,pd_whcode,pd_prodcode ) where c> 1");
+            if (rs.next()) {
+                if (rs.getInt("n") > 0) {
+                    return "同一物料同仓库不能同时入两次相同的批号!" + rs.getString("detno");
+                }
+            }
+            rs = baseDao
+                    .queryForRowSet("select count(1) n,wm_concat(pd_piclass||'['||pd_inoutno||']行号['||pd_pdno||']')detno "
+                            + "from (select pd_piclass,pd_inoutno,pd_pdno from ProdIODetail where pd_piid="
+                            + pi_id
+                            + " and pd_batchcode is not null and exists (select 1 from batch where ba_code=pd_batchcode and ba_prodcode=pd_prodcode "
+                            + "and ba_whcode=pd_whcode and (nvl(ba_remain,0)<>0 or nvl(ba_inqty,0)<>0))) where rownum<30");
+            if (rs.next()) {
+                if (rs.getInt("n") > 0) {
+                    return "批号已存在,不能重复入库!" + rs.getString("detno");
+                }
+            }
+        }
+        return null;
+    }
+
+    private String copcheck(int pi_id, String caller) {
+        if (baseDao.isDBSetting("sys","CopCheck")) {
+            // 出入库单:明细行采购单所属公司与当前单所属公司必须一致,可在提交、打印、审核、过账等操作前配置
+            String dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join ProdInOut on pd_piid=pi_id left join Purchase on pd_ordercode=pu_code where pi_id=? and nvl(pu_cop,' ')<>nvl(pi_cop,' ') and nvl(pd_ordercode,' ')<>' ' "
+                                    + " and pd_piclass in ('采购验收单','采购验退单')", String.class, pi_id);
+            if (dets != null) {
+                return "明细行采购单所属公司与当前单所属公司不一致,不允许进行当前操作!行号:" + dets;
+            }
+            // 出入库单:明细行销售单所属公司与当前单所属公司必须一致,可在提交、打印、审核、过账等操作前配置
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join ProdInOut on pd_piid=pi_id left join Sale on pd_ordercode=sa_code where pi_id=? and nvl(sa_cop,' ')<>nvl(pi_cop,' ') and nvl(pd_ordercode,' ')<>' ' "
+                                    + "and pd_piclass in ('出货单','销售退货单','销售拨出单','销售拨入单')", String.class, pi_id);
+            if (dets != null) {
+                return "明细行销售单所属公司与当前单所属公司不一致,不允许进行当前操作!行号:" + dets;
+            }
+            // 出货单:来源单所属公司与当前单所属公司不一致,不允许进行当前操作
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join ProdInOut on pd_piid=pi_id left join Sendnotify on pd_snid=sn_id where pi_id=? and nvl(sn_cop,' ')<>nvl(pi_cop,' ') and nvl(pd_snid,0)<>0 ",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "明细来源通知单所属公司与当前单所属公司不一致,不允许进行当前操作!行号:" + dets;
+            }
+            // 出入库单:明细行制造单所属公司与当前单所属公司必须一致,可在提交、打印、审核、过账等操作前配置
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join ProdInOut on pd_piid=pi_id left join Make on pd_ordercode=ma_code where pi_id=? and nvl(ma_cop,' ')<>nvl(pi_cop,' ') and nvl(pd_ordercode,' ')<>' ' "
+                                    + "and pd_piclass in  ('生产领料单','生产退料单','生产补料单','完工入库单','拆件入库单')", String.class, pi_id);
+            if (dets != null) {
+                return "明细行制造单所属公司与当前单所属公司不一致,不允许进行当前操作!行号:" + dets;
+            }
+            // 出入库单:明细行委外单所属公司与当前单所属公司必须一致,可在提交、打印、审核、过账等操作前配置
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join ProdInOut on pd_piid=pi_id left join Make on pd_ordercode=ma_code where pi_id=? and nvl(ma_cop,' ')<>nvl(pi_cop,' ') and nvl(pd_ordercode,' ')<>' ' "
+                                    + "and pd_piclass in ('委外验收单','委外验退单','委外领料单','委外退料单','委外补料单')", String.class, pi_id);
+            if (dets != null) {
+                return "明细行委外单所属公司与当前单所属公司不一致,不允许进行当前操作!行号:" + dets;
+            }
+            if ("ProdInOut!SaleAppropriationOut".equals(caller) || "ProdInOut!OtherOut".equals(caller)
+                    || "ProdInOut!AppropriationOut".equals(caller)) {
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail left join ProdInOut on pd_piid=pi_id left join SaleForecast on pd_plancode=sf_code where pi_id=? and nvl(sf_cop,' ')<>nvl(pi_cop,' ') and nvl(pd_plancode,' ')<>' ' "
+                                        + "and pd_piclass in  ('销售拨出单','其它出库单')", String.class, pi_id);
+                if (dets != null) {
+                    return "明细行销售预测单所属公司与当前单所属公司不一致,不允许进行当前操作!行号:" + dets;
+                }
+                dets = baseDao
+                        .getJdbcTemplate()
+                        .queryForObject(
+                                "select wm_concat(pd_pdno) from ProdIODetail left join prodinout on pd_piid=pi_id left join Warehouse on pd_inwhcode=wh_code where pi_id=? and pi_class in ('销售拨出单','拨出单') and nvl(pi_cop,' ')<>nvl(wh_cop,' ')",
+                                String.class, pi_id);
+                if (dets != null) {
+                    return "单据所属公司和明细行拨入仓库的所属公司不一致,不允许进行当前操作!行号:" + dets;
+                }
+            }
+            // 出入库单限制界面的所属公司和仓库的所属公司必须一致,可在提交、打印、审核、过账等操作前配置
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join prodinout on pd_piid=pi_id left join Warehouse on pd_whcode=wh_code where nvl(pi_cop,' ')<>nvl(wh_cop,' ') and pi_id=? and pi_class not in ('成本调整单')",
+                            String.class, pi_id);
+            if (dets != null) {
+                return "单据所属公司和明细行仓库的所属公司不一致,不允许进行当前操作!行号:" + dets;
+            }
+        }
+        return null;
+    }
+
+    private String factorycheck(int pi_id, String caller) {
+        if (baseDao.isDBSetting("MpsDesk", "mrpSeparateFactory")) {
+            // 采购验收单、采购验退单:明细行采购单所属工厂与仓库的所属工厂不一致,,不允许进行当前操作
+            String dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join PurchaseDetail on ProdIODetail.pd_ordercode=PurchaseDetail.pd_code and ProdIODetail.pd_orderdetno=PurchaseDetail.pd_detno left join Warehouse on ProdIODetail.pd_whcode=wh_code left join product on ProdIODetail.pd_prodcode=pr_code where pd_piid=? and nvl(PR_ISGROUPPURC,0)=0 and nvl(PurchaseDetail.pd_factory,' ')<>nvl(wh_factory,' ') and nvl(ProdIODetail.pd_ordercode,' ')<>' ' "
+                                    + " and  PurchaseDetail.pd_factory is not null and pd_piclass in ('采购验收单','采购验退单')", String.class,
+                            pi_id);
+            if (dets != null) {
+                return "明细行采购单所属工厂与仓库的所属工厂不一致,不允许进行当前操作!行号:" + dets;
+            }
+            // 生产领料单、退料单、补料单:明细行制造单所属工厂与仓库的所属工厂不一致,不允许进行当前操作
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join Make on pd_ordercode=ma_code left join Warehouse on pd_whcode=wh_code left join product on ProdIODetail.pd_prodcode=pr_code where pd_piid=? and nvl(PR_ISGROUPPURC,0)=0 and nvl(ma_factory,' ')<>nvl(wh_factory,' ') and nvl(pd_ordercode,' ')<>' ' "
+                                    + "and pd_piclass in  ('生产领料单','生产退料单','生产补料单')", String.class, pi_id);
+            if (dets != null) {
+                return "明细行制造单所属工厂与仓库的所属工厂不一致,不允许进行当前操作!行号:" + dets;
+            }
+            // 委外领料单、退料单、补料单:明细行委外单所属工厂与仓库的所属工厂不一致,不允许进行当前操作
+            dets = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select wm_concat(pd_pdno) from ProdIODetail left join Make on pd_ordercode=ma_code left join Warehouse on pd_whcode=wh_code left join product on ProdIODetail.pd_prodcode=pr_code where pd_piid=? and nvl(PR_ISGROUPPURC,0)=0 and nvl(ma_factory,' ')<>nvl(wh_factory,' ') and nvl(pd_ordercode,' ')<>' ' "
+                                    + "and pd_piclass in ('委外领料单','委外退料单','委外补料单')", String.class, pi_id);
+            if (dets != null) {
+                return "明细行委外单所属工厂与仓库的所属工厂不一致,不允许进行当前操作!行号:" + dets;
+            }
+        }
+        return null;
+    }
+
+    private String checkIOMaPick(String caller, Object pi_id) {
+        String[] checkCallers={"ProdInOut!AppropriationOut","ProdInOut!Picking", "ProdInOut!OutsidePicking","ProdInOut!Make!Give","ProdInOut!OSMake!Give"
+                ,"ProdInOut!OtherOut","ProdInOut!SaleBorrow"};
+        if(Arrays.asList(checkCallers).contains(caller)){
+            String gridStore = "[]";
+            String formStore = null;
+            SqlRowList fromP = baseDao.queryForRowSet("select pi_id,pi_class,TO_CHAR(pi_date,'YYYYMM') pi_date from prodinout where pi_id = "+pi_id+" ");
+            if(fromP.next()){
+                formStore = BaseUtil.parseMap2Str(baseDao.changeKeyToLowerCase(fromP.getCurrentMap()));
+                SqlRowList checkDetail = baseDao.queryForRowSet("select pd_ordercode macode, pd_prodcode prodcode,pd_outqty outqty,pd_whcode outwhcode,pd_inwhcode inwhcode" +
+                        " from prodiodetail where pd_piid = "+pi_id+" order by pd_pdno");
+                if(checkDetail.hasNext()){
+                    gridStore = BaseUtil.parseGridStore2Str(baseDao.changeKeyToLowerCase(checkDetail.getResultList()));
+                }
+                String res = baseDao.callProcedure("USER_CHECKOUTSTOCK", new Object[] {formStore,gridStore});
+                if (res != null && res.length() > 0) {
+                    return res;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 新增生产退料和委外退料判断,替代料退料数量不能大于替代料已领数量,主料退料不能大于主料已领数,工单外退料的情况不限制
+     *
+     * @date 2016年10月17日 下午12:30:58
+     * @param pi_id
+     *            单据id
+     */
+    private String checkRepQty(int pi_id) {
+        SqlRowList rs = baseDao
+                .queryForRowSet(
+                        "select wm_concat(T.pdno) no from (select nvl(sum(pd_inqty),0) inqty,pd_ordercode,pd_orderdetno,pd_prodcode,max(pd_pdno)pdno "
+                                + " from prodiodetail where pd_piid=? group by pd_ordercode,pd_orderdetno,pd_prodcode )T "
+                                + " left join makematerial on mm_code=T.pd_ordercode and mm_detno=T.pd_orderdetno "
+                                + " where T.pd_prodcode=mm_prodcode and mm_havegetqty-nvl(mm_haverepqty,0)<T.inqty and (nvl(mm_qty,0)>0 or (nvl(mm_qty,0)=0 and nvl(mm_updatetype,' ')<>'R')) and rownum<25",
+                        pi_id);
+        if (rs.next() && rs.getObject("no") != null) {
+            return "主料退料数不允许大于主料已领数,行号:" + rs.getString(1);
+        }
+        rs = baseDao
+                .queryForRowSet(
+                        "select wm_concat(T.pdno) no from (select nvl(sum(pd_inqty),0) inqty,pd_ordercode,pd_orderdetno,pd_prodcode,max(pd_pdno)pdno "
+                                + " from prodiodetail where pd_piid=? group by pd_ordercode,pd_orderdetno,pd_prodcode )T "
+                                + " left join MakeMaterialreplace on mp_mmcode=T.pd_ordercode and mp_mmdetno=T.pd_orderdetno left join makematerial on mm_code=mp_mmcode and mm_detno=mp_mmdetno"
+                                + " where T.pd_prodcode=mp_prodcode and T.inqty>nvl(mp_haverepqty,0) and (nvl(mm_qty,0)>0 or (nvl(mm_qty,0)=0 and nvl(mm_updatetype,' ')<>'R')) and rownum<25",
+                        pi_id);
+        if (rs.next() && rs.getObject("no") != null) {
+            return "替代料退料数不允许大于替代已领数,行号:" + rs.getString(1);
+        }
+        return null;
+    }
+
+    private String checkMmBackOver(String caller, int pi_id) {
+        //截止到退料单单据日期月份的 本单的退料不允许大于 已过账的 领料出库-退料数+补料数-(完工-验退数)*单位用量
+        String data = baseDao.getJdbcTemplate().queryForObject("select wm_concat('工单:'||pd_ordercode||',序号:'||pd_orderdetno ||'<br>') " +
+                " from (select pd_ordercode,pd_orderdetno,sum(pd_inqty)inqty,to_char(max(pi_date),'yyyymm')pidate from prodinout left join prodiodetail on pd_piid=pi_id where pd_piid=? group by pd_ordercode,pd_orderdetno)a LEFT JOIN MAKE ON MA_CODE=PD_ORDERCODE " +
+                " LEFT JOIN MAKEMATERIAL ON MM_MAID=MA_ID and pd_orderdetno=mm_detno where " +
+                " inqty > nvl((select sum(nvl(pd_outqty,0)-nvl(pd_inqty,0)) from prodiodetail b left join prodinout on pd_piid=pi_id where pd_status=99 and pidate>= to_char(pi_date,'yyyymm') and " +
+                " a.pd_ordercode=b.pd_ordercode and a.pd_orderdetno=b.pd_orderdetno and pi_class in('生产领料单','委外领料单','生产退料单','委外退料单','生产补料单','委外补料单')),0) " +
+                " - NVL((select SUM(MD_QTY) from makescrap left join makescrapdetail on md_msid=ms_id WHERE ms_statuscode='AUDITED' AND pidate>=to_char(MS_AUDITDATE,'yyyymm') AND MD_mmcode = pd_ordercode AND MD_mmdetno = pd_orderdetno),0) " +
+                " -NVL((SELECT sum(nvl(pd_inqty,0)-nvl(pd_outqty,0)) FROM prodiodetail b left join prodinout on pd_piid=pi_id where pd_status=99 and pidate>=to_char(pi_date,'yyyymm') and " +
+                " a.pd_ordercode=b.pd_ordercode AND pi_class in('完工入库单','委外验退单','委外验收单')),0)*nvl(mm_oneuseqty,0) and rownum<10",String.class,pi_id);
+        if(data != null){
+            return "退料数大于截止到单据月份剩余的结存数,"+data;
+        }
+        return null;
+
+    }
+
+    /**
+     * 计算pi_total
+     */
+    private void getTotal(Object pi_id, String caller) {
+        baseDao.execute("update prodiodetail set pd_purcinqty=nvl(pd_inqty,0) where pd_piid=" + pi_id
+                + " and exists (select 1 from product where pd_prodcode=pr_code and nvl(pr_purcunit,pr_unit)=pr_unit) ");
+        baseDao.execute("update prodiodetail set pd_purcoutqty=nvl(pd_outqty,0) where pd_piid=" + pi_id
+                + " and exists (select 1 from product where pd_prodcode=pr_code and nvl(pr_purcunit,pr_unit)=pr_unit)");
+
+        baseDao.execute("update prodiodetail set pd_purcinqty=pd_inqty/(select case when nvl(pr_purcrate,0)<>0 then pr_purcrate else 1 end from product where pr_code=pd_prodcode) where pd_piid="
+                + pi_id + " and nvl(pd_purcinqty,0)=0");
+
+        if ("ProdInOut!PurcCheckin".equals(caller) || "ProdInOut!PurcCheckout".equals(caller) || "ProdInOut!OutsideCheckIn".equals(caller)
+                || "ProdInOut!OutesideCheckReturn".equals(caller)) {
+            if ("ProdInOut!OutsideCheckIn".equals(caller) || "ProdInOut!OutesideCheckReturn".equals(caller)) {// 委外
+                baseDao.updateByCondition("ProdIODetail", "pd_orderprice=(select ma_price from make where ma_code=pd_ordercode)",
+                        "pd_piid=" + pi_id + " and nvl(pd_orderprice,0)=0");
+                // 强制取委外单主表中的税率
+                baseDao.execute(
+                        "update ProdIODetail set pd_taxrate=(select nvl(ma_taxrate,0) from make where ma_code=pd_ordercode) where pd_ordercode is not null and pd_piid=?",
+                        pi_id);
+            } else {// 采购
+                baseDao.updateByCondition("ProdIODetail",
+                        "pd_orderprice=nvl((select pd_price from PurchaseDetail where pd_code=pd_ordercode and pd_detno=pd_orderdetno),0)",
+                        "pd_piid=" + pi_id + " and nvl(pd_orderprice,0)=0 and nvl(pd_status,0)<>99");
+                // 强制取采购单明细表中的对应的税率
+                baseDao.execute(
+                        "update ProdIODetail set pd_taxrate=(select nvl(pd_rate,0) from PurchaseDetail where pd_code=pd_ordercode and pd_detno=pd_orderdetno) where  pd_ordercode is not null  and nvl(pd_status,0)<>99 and pd_piid=?",
+                        pi_id);
+
+            }
+            baseDao.execute("update ProdIODetail set pd_ordertotal=round(pd_orderprice*(case when nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0)=0 then nvl(pd_inqty,0)+nvl(pd_outqty,0) else nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0) end),2) where pd_piid="
+                    + pi_id);
+            baseDao.execute("update ProdIODetail set pd_taxtotal=round(pd_orderprice*(case when nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0)=0 then nvl(pd_inqty,0)+nvl(pd_outqty,0) else nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0) end)*nvl(pd_taxrate,0)/(100+nvl(pd_taxrate,0)),2),pd_nettotal=round(pd_orderprice*(case when nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0)=0 then nvl(pd_inqty,0)+nvl(pd_outqty,0) else nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0) end)/(1+nvl(pd_taxrate,0)/100),2) where pd_piid="
+                    + pi_id);
+            baseDao.updateByCondition("ProdIODetail", " pd_total=round(nvl(pd_price,0)*(nvl(pd_inqty,0)+nvl(pd_outqty,0)),2)", "pd_piid="
+                    + pi_id);
+            baseDao.updateByCondition("ProdInOut",
+                    "pi_total = round(nvl((SELECT sum(round(pd_ordertotal,2)) FROM ProdIODetail WHERE pd_piid=pi_id),0),2)", "pi_id="
+                            + pi_id);
+            baseDao.updateByCondition(
+                    "ProdIODetail",
+                    "pd_netprice=round(pd_orderprice/(1+pd_taxrate/100),8),pd_nettotal=round(pd_orderprice*(case when nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0)=0 then nvl(pd_inqty,0)+nvl(pd_outqty,0) else nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0) end)/(1+nvl(pd_taxrate,0)/100),2)",
+                    "pd_piid=" + pi_id);
+            baseDao.updateByCondition("ProdInOut", "pi_totalupper=L2U(nvl(pi_total,0))", "pi_id=" + pi_id);
+        } else if ("ProdInOut!Sale".equals(caller) || "ProdInOut!SaleReturn".equals(caller)) {
+            baseDao.updateByCondition(
+                    "ProdIODetail",
+                    "pd_ordertotal=round(nvl(pd_sendprice,0)*(case when nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0)=0 then nvl(pd_inqty,0)+nvl(pd_outqty,0) else nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0) end),2),pd_total=round(nvl(pd_price,0)*(nvl(pd_inqty,0)+nvl(pd_outqty,0)),2)",
+                    "pd_piid=" + pi_id);
+            baseDao.updateByCondition(
+                    "ProdIODetail",
+                    "pd_netprice=round(pd_sendprice/(1+pd_taxrate/100),8),pd_nettotal=round(pd_sendprice*(case when nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0)=0 then nvl(pd_inqty,0)+nvl(pd_outqty,0) else nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0) end)/(1+nvl(pd_taxrate,0)/100),2)",
+                    "pd_piid=" + pi_id);
+            baseDao.updateByCondition("ProdInOut",
+                    "pi_total=round(nvl((SELECT sum(round(pd_ordertotal,2)) FROM ProdIODetail WHERE pd_piid=pi_id),0),2)", "pi_id=" + pi_id);
+            baseDao.execute("update prodiodetail set pd_customprice=pd_sendprice, pd_taxamount=pd_ordertotal "
+                    + "where pd_piclass in ('出货单','销售退货单') and pd_piid=? and nvl(pd_customprice,0)=0", pi_id);
+            baseDao.updateByCondition("ProdInOut", "pi_totalupper=L2U(nvl(pi_total,0))", "pi_id=" + pi_id);
+            // 成品标准成本,用于报价毛利润统计
+            baseDao.execute("UPDATE product set pr_cost=nvl((select price from ( select qd_prodcode,round(qd_factprice*qu_rate,2) price,"
+                    + "     row_number() over(partition by qd_prodcode order by qu_auditdate desc) rn from  quotation,quotationdetail  "
+                    + "where qu_id=qd_quid and qu_statuscode='AUDITED') t1 where rn=1 and qd_prodcode=pr_code),0) "
+                    + "where nvl(pr_cost,0)=0 and pr_code in (select pd_prodcode from prodiodetail where pd_piid=?)", pi_id);
+            baseDao.execute("UPDATE prodiodetail SET pd_showprice=nvl((select pr_cost from product where pd_prodcode=pr_code),0)"
+                    + "WHERE  pd_piid=?", pi_id);
+        } else {
+            baseDao.updateByCondition("ProdIODetail", "pd_total=round(nvl(pd_price,0)*(nvl(pd_inqty,0)+nvl(pd_outqty,0)),2)", "pd_piid="
+                    + pi_id);
+            baseDao.updateByCondition(
+                    "ProdInOut",
+                    "pi_total=(SELECT sum(round(nvl(pd_price,0)*(nvl(pd_inqty,0)+nvl(pd_outqty,0)),2)) FROM ProdIODetail WHERE pd_piid=pi_id)",
+                    "pi_id=" + pi_id);
+            baseDao.updateByCondition("ProdInOut", "pi_totalupper=L2U(nvl(pi_total,0))", "pi_id=" + pi_id);
+        }
+        if ("ProdInOut!Sale".equals(caller) || "ProdInOut!SaleReturn".equals(caller) || "ProdInOut!AppropriationOut".equals(caller)
+                || "ProdInOut!OtherOut".equals(caller) || "ProdInOut!ExchangeOut".equals(caller)) {
+            Object cardcode = baseDao.getFieldDataByCondition("ProdInOut", "pi_cardcode", "pi_id=" + pi_id);
+            baseDao.execute("update prodiodetail set (PD_CUSTPRODCODE,PD_CUSTPRODSPEC,pd_custproddetail)=(select max(pc_custprodcode),max(pc_custprodspec),max(pc_custproddetail) from ProductCustomer left join Product on pc_prodid=pr_id left join customer on pc_custid=cu_id where cu_code='"
+                    + cardcode
+                    + "' and pd_prodcode=pr_code) where pd_piid="
+                    + pi_id
+                    + " and nvl(pd_custprodcode,' ')=' ' and nvl(pd_custprodspec,' ')=' ' and pd_piclass in ('销售退货单', '出货单', '其它出库单', '拨出单', '换货出库单')");
+            baseDao.execute("update ProdIODetail set pd_taxtotal=round(pd_sendprice*(case when nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0)=0 then nvl(pd_inqty,0)+nvl(pd_outqty,0) else nvl(pd_purcinqty,0)+nvl(pd_purcoutqty,0) end)*nvl(pd_taxrate,0)/(100+nvl(pd_taxrate,0)),2) where pd_piid="
+                    + pi_id);
+        }
+
+        if ("ProdInOut!CostChange".equals(caller)) {
+            baseDao.execute(
+                    "update prodiodetail set pd_total=round((nvl(pd_price,0)-nvl(pd_orderprice,0))*nvl(pd_orderqty,0),2) where pd_piclass ='成本调整单' and pd_piid=?",
+                    pi_id);
+        }
+        // 入库类单据:如果pd_location为空,默认等于物料资料里的仓位pr_location
+        if (baseDao.isIn(caller)) {
+            baseDao.execute(
+                    "update prodiodetail set pd_location=(select pr_location from product where pr_code=pd_prodcode) where pd_piid=? and nvl(pd_location,' ')=' '",
+                    pi_id);
+        }
+        baseDao.updateByCondition("ProdInOut",
+                "pi_total = round(nvl((SELECT sum(round(nvl(pd_ordertotal,0),2)) FROM ProdIODetail WHERE pd_piid=pi_id),0),2)", "pi_id="
+                        + pi_id);
+        baseDao.updateByCondition("ProdInOut",
+                "pi_nettotal = round(nvl((SELECT sum(round(nvl(pd_nettotal,0),2)) FROM ProdIODetail WHERE pd_piid=pi_id),0),2)", "pi_id="
+                        + pi_id);
+    }
+
+    /**
+     * 计算pi_qtytotal
+     */
+    private void getQtyTotal(Object pi_id, String caller) {
+        if ("ProdInOut!Sale".equals(caller) || "ProdInOut!PurcCheckin".equals(caller) || "ProdInOut!OtherOut".equals(caller)) {
+            baseDao.execute("update ProdInOut set pi_qtytotal=nvl((select sum(nvl(pd_outqty,0)+nvl(pd_inqty,0))  from ProdIODetail where  "
+                    + "ProdIODetail.pd_piid = ProdInOut.pi_id),0) where pi_id=" + pi_id);
+        }
+    }
+
+    // @add 20170524 出库类型的单据,保存,更新,获取批号之后更新备料状态
+    private void updatePdaStatus(String caller, Object pi_id) {
+        Boolean bo = baseDao.isDBSetting("BarCodeSetting", "BarRelevancyBatch");
+        Boolean AutoPickBarcode = baseDao.isDBSetting("BarCodeSetting", "autoPickBarcode");
+        if (!AutoPickBarcode) {
+            if (!bo) {
+                if (baseDao.isOut(caller)) { // 出库类型
+                    // 如果所有的明细都没有条码则更新为空
+                    SqlRowList rs = baseDao.queryForRowSet(
+                            "select count(1)cn from prodiodetail where pd_piid=? and nvl(pd_batchcode,' ')<>' '", pi_id);
+                    if (rs.next() && rs.getInt("cn") == 0) {
+                        baseDao.execute("update prodinout set pi_pdastatus='' where pi_id=? and nvl(pi_pdastatus,' ')<>' '", pi_id);
+                    } else {
+                        rs = baseDao.queryForRowSet("select count(1)cn from barcodeio where bi_piid=? and bi_outqty>0", pi_id);
+                        if (rs.next() && rs.getInt("cn") > 0) { // 有一行以上备料记录则是备料中
+                            baseDao.execute("update prodinout set pi_pdastatus ='备料中' where pi_id=?", pi_id);
+                            rs = baseDao
+                                    .queryForRowSet(
+                                            "select count(1) cn from (select pd_prodcode,pd_whcode,sum(pd_outqty)qty from prodiodetail left join batch on pd_batchid=ba_id "
+                                                    + " where pd_piid=? and ba_hasbarcode<>0 group by pd_prodcode,pd_whcode)A left join (select bi_prodcode,bi_whcode,sum(bi_outqty)qty "
+                                                    + " from barcodeio where bi_piid=? group by bi_prodcode,bi_whcode)B on (pd_prodcode=bi_prodcode and pd_whcode=bi_whcode) where A.qty>NVL(B.qty,0)",
+                                            pi_id, pi_id);
+                            if (rs.next() && rs.getInt("cn") == 0) {
+                                baseDao.execute("update prodinout set pi_pdastatus ='已备料' where pi_id=?", pi_id);
+                            }
+                        } else {
+                            // --存在有条码的批号则更新成未备料
+                            baseDao.execute(
+                                    "update prodinout set pi_pdastatus ='未备料' where pi_id=?  and exists(select 1 from prodiodetail,batch where pd_piid=? and pd_batchid=ba_id and ba_hasbarcode<>0)",
+                                    pi_id, pi_id);
+                            // --所有批号都无条码则更新成无条码
+                            baseDao.execute(
+                                    "update prodinout set pi_pdastatus ='无条码' where pi_id=? and not exists(select 1 from prodiodetail left join batch on ba_id=pd_batchid where pd_piid=?  and ba_hasbarcode=-1)",
+                                    pi_id, pi_id);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 检查批号是否存在,批号数量是否足够
+     */
+    private String checkBatchRemain(Object pi_id) {
+        int count = baseDao.getCount("select count(1) from documentsetup where ds_name=(select pi_class from prodinout " + "where pi_id="
+                + pi_id + ") and (ds_inorout = '-IN' or ds_inorout = 'OUT')");
+        if (count > 0) {
+            String pdnos1 = baseDao.getJdbcTemplate().queryForObject(
+                    "select WMSYS.WM_CONCAT(pd_pdno) from (select pd_pdno  from prodiodetail left join batch on"
+                            + " pd_batchcode=ba_code and ba_whcode = pd_whcode and ba_prodcode = pd_prodcode "
+                            + "where pd_piid=? and ba_code is null order by pd_pdno) where rownum<20", String.class, pi_id);
+            String pdnos2 = baseDao
+                    .getJdbcTemplate()
+                    .queryForObject(
+                            "select WMSYS.WM_CONCAT(pd_pdno) from (select WMSYS.WM_CONCAT(pd_pdno) pd_pdno,max(pd_batchcode),"
+                                    + "sum(pd_outqty),max(ba_remain),max(ba_code) from prodiodetail left join batch on pd_batchcode=ba_code and "
+                                    + "ba_whcode = pd_whcode and ba_prodcode = pd_prodcode where pd_piid=? group by pd_batchcode,pd_prodcode,pd_whcode"
+                                    + "  having sum(pd_outqty)>max(ba_remain) ) where rownum<20", String.class, pi_id);
+            if (pdnos1 != null || pdnos2 != null) {
+                String error1 = pdnos1 == null ? "" : "找不到您所指的批号,请修改批号或点击【重置批号】再过账!行号是:" + pdnos1 + "<br>";
+                String error2 = pdnos2 == null ? "" : "批号的库存数小于出库数量,请修改批号或点击【重置批号】再过账!行号是:" + pdnos2 + "<br>";
+                return error1 + error2;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 产生冲销单并审核 发货单过帐/销售单审核 scm->prodinout->post->after scm->sale->audit->after
+     *
+     * @author ZhongYL
+     */
+    @Transactional
+    public void createSaleClash(Integer fromid, String fromcaller,Employee employee) {
+        String SqlStr = "", clashcode = "", canclash = "", othercondition = "";
+        double thisqty = 0, needclashqty = 0, clashedqty = 0;
+        int csid = 0, detno = 0;
+        String prodcode = "", ordercode = "", fromcode = "", fromwhere = "";
+        String clashoption = "", saleclashkind = "";
+        SqlRowList rs0;
+        if (fromcaller.equalsIgnoreCase("ProdInOut")) {
+            fromwhere = baseDao.getFieldDataByCondition("ProdInOut", "pi_class", "pi_id=" + fromid).toString();
+        } else if (fromcaller.equalsIgnoreCase("Sale") || fromcaller.equals("销售单")) {
+            fromwhere = "销售单";
+        } else {
+            return;
+        }
+        // 先更新呆冲销的明细已冲销数为0
+        SqlStr = "update saleforecastDetail set sd_stepqty=0 where sd_id in (select sd_id from saleforecastDetail ,saleforecast   where sd_sfid=sf_id and sf_statuscode='AUDITED' and NVL(sd_statuscode,' ')<>'FINISH' and sd_qty>0)  ";
+        baseDao.execute(SqlStr);
+        // 获取冲销来源单据
+        if (fromwhere.equals("出货单")) {
+            SqlStr = "select pd_id as sourcedetid,pd_inoutno as fromcode,pd_outqty+nvl(pd_beipinoutqty,0) as qty,pd_prodcode as prodcode,pd_ordercode as ordercode,pd_pdno as pdno,sd_forecastcode as sfcode,sd_forecastdetno as sfdetno from Prodiodetail left join saledetail on sd_code=pd_ordercode and sd_detno=pd_orderdetno where pd_piid='"
+                    + fromid + "' ";
+        } else if (fromwhere.equals("销售单")) {
+            SqlStr = "select sd_id as sourcedetid,sd_code as fromcode,sd_qty as qty,sd_prodcode as prodcode,sa_code as ordercode,sd_detno as pdno,sd_forecastcode as sfcode,sd_forecastdetno as sfdetno,sa_custcode,sa_sellercode from saledetail,sale where sa_id=sd_said and sd_said='"
+                    + fromid + "' ";
+        } else if (fromwhere.equals("完工入库单") || fromwhere.equals("委外验收单") || fromwhere.equals("委外验退单")) {
+            SqlStr = "select pd_id as sourcedetid,pd_inoutno as fromcode,NVL(pd_inqty,0)+NVL(pd_outqty,0) as qty,pd_prodcode as prodcode,pd_ordercode as ordercode,pd_pdno as pdno,ma_salecode,ma_saledetno from Prodiodetail,warehouse,make,makekind where pd_piid='"
+                    + fromid
+                    + "' and pd_whcode=wh_code and NVL(wh_ifclash,0)<>0  and ma_code=pd_ordercode and ma_kind=mk_name and NVL(mk_clashsale,0)<>0 ";
+            // 判断是否存在需要完工入库冲销的预测
+            rs0 = baseDao.queryForRowSet("select sf_code from saleforecastkind where sf_clashoption='完工冲销' or sf_clashoption='FINISH' ");
+            if (!rs0.hasNext()) {
+                // 不需要完工冲销
+                return;
+            }
+        } else if (fromwhere.equals("销售拨出单")) {
+            SqlStr = "select pd_id as sourcedetid,pd_inoutno as fromcode,pd_outqty+nvl(pd_beipinoutqty,0) as qty,pd_prodcode as prodcode,pd_plancode as ordercode,pd_pdno as pdno,pd_plancode as sfcode,pd_forecastdetno as sfdetno from Prodiodetail where  pd_piid='"
+                    + fromid + "' and  NVL(pd_plancode,' ')<>' ' and pd_forecastdetno>0 ";
+        } else if (fromwhere.equals("其它出库单")) {
+            SqlStr = "select pd_id as sourcedetid,pd_inoutno as fromcode,pd_outqty+nvl(pd_beipinoutqty,0) as qty,pd_prodcode as prodcode,pd_plancode as ordercode,pd_pdno as pdno,pd_plancode as sfcode,pd_forecastdetno as sfdetno from Prodiodetail where  pd_piid='"
+                    + fromid + "' and  NVL(pd_plancode,' ')<>' ' and pd_forecastdetno>0 ";
+        } else {
+            return;
+        }
+        detno = 1;
+        SqlRowList rs = baseDao.queryForRowSet(SqlStr);
+        while (rs.next()) {
+            fromcode = rs.getString("fromcode");
+            clashoption = "";
+            saleclashkind = "";
+            othercondition = "";
+            clashedqty = 0;
+            needclashqty = rs.getDouble("qty");
+            prodcode = rs.getString("prodcode");
+            ordercode = rs.getString("ordercode");
+            // 判断此行记录是否需要冲销
+            canclash = "N";
+            if (fromwhere.equals("销售单") || fromwhere.equals("出货单")) {
+                if(fromwhere.equals("出货单") && baseDao.isDBSetting("ProdInOut!Sale", "clashSaleForecastByProduct")){
+                    saleclashkind="PRODUCT";
+                    clashoption = "SEND";
+                }else{
+                    SqlStr = "SELECT * from sale left join salekind on (sa_kind=sk_name or sa_kind=sk_code) where sa_code='" + ordercode + "' ";
+                    SqlRowList rs2 = baseDao.queryForRowSet(SqlStr);
+                    if (rs2.next()) {
+                        saleclashkind = rs2.getString("sk_clashfor");
+                        clashoption = rs2.getString("sk_clashoption");
+                        othercondition = rs2.getString("sk_clashkind");
+                    } else {
+                        // 未设置类型,不冲销
+                        continue;
+                    }
+                }
+            } else if (fromwhere.equals("完工入库单") || fromwhere.equals("委外验收单") || fromwhere.equals("委外验退单")) {
+                saleclashkind = "PRODUCT";
+                clashoption = "FINISH";
+            } else if (fromwhere.equals("销售拨出单") || fromwhere.equals("其它出库单")) {
+                saleclashkind = "单号冲销";
+                clashoption = "SEND";
+            }
+            if (saleclashkind == null || clashoption == null) {
+                // 未设置类型,不冲销
+                continue;
+            }
+            if (fromwhere.equals("销售单")) {
+                if (clashoption.equals("订单冲销") || clashoption.equalsIgnoreCase("SALE")) {
+                    canclash = "Y";
+                }
+            } else if (fromwhere.equals("出货单")) {
+                if (clashoption.equals("发货冲销") || clashoption.equalsIgnoreCase("SEND")) {
+                    canclash = "Y";
+                }
+            }
+            if (fromwhere.equals("完工入库单") || fromwhere.equals("委外验收单") || fromwhere.equals("委外验退单") || fromwhere.equals("销售拨出单")
+                    || fromwhere.equals("其它出库单")) {
+                canclash = "Y";
+            }
+            if (canclash.equals("N")) {
+                // 不冲销
+                continue;
+            }
+            SqlStr = "";
+            if (saleclashkind.equalsIgnoreCase("sale") || saleclashkind.equals("单号冲销")) {
+                SqlStr = "SELECT saleforecastDetail.*,saleforecast.* from saleforecastDetail left join saleforecast on sd_sfid=sf_id left join saleforecastkind on (saleforecast.sf_kind=saleforecastkind.sf_name or saleforecast.sf_kind=saleforecastkind.sf_code) where saleforecast.sf_code='"
+                        + rs.getString("sfcode") + "' and sd_detno=" + rs.getInt("sfdetno");
+            } else if (saleclashkind.equalsIgnoreCase("product") || saleclashkind.equals("料号冲销")) {
+                // 按物料号冲销
+                SqlStr = "SELECT saleforecastDetail.*,saleforecast.* from saleforecastDetail left join saleforecast on sd_sfid=sf_id left join saleforecastkind on (saleforecast.sf_kind=saleforecastkind.sf_name or saleforecast.sf_kind=saleforecastkind.sf_code) where sd_prodcode='"
+                        + prodcode + "' ";
+                if (fromwhere.equals("完工入库单") || fromwhere.equals("委外验收单")) {
+                    SqlStr = "SELECT case when saleforecast.sf_code='"
+                            + rs.getString("ma_salecode")
+                            + "' and sd_detno="
+                            + rs.getInt("ma_saledetno")
+                            + " then 1 else 2 end sortid,saleforecastDetail.*,saleforecast.* from saleforecastDetail left join saleforecast on sd_sfid=sf_id left join saleforecastkind on (saleforecast.sf_kind=saleforecastkind.sf_name or saleforecast.sf_kind=saleforecastkind.sf_code) where sd_prodcode='"
+                            + prodcode + "' ";
+                }
+                if (fromwhere.equals("销售单") && othercondition != null && othercondition.equals("客户匹配")) {
+                    SqlStr = SqlStr + " and (case when NVL(saleforecastDetail.sd_custcode,' ')<>' ' then saleforecastDetail.sd_custcode else sf_custcode end)='" + rs.getString("sa_custcode") + "' ";
+                } else if (fromwhere.equals("销售单") && othercondition != null && othercondition.equals("业务员")){
+                    SqlStr = SqlStr + " and (case when nvl(saleforecastDetail.sd_sellercode,' ')<>' ' then saleforecastDetail.sd_sellercode else sf_sellercode end)='"+ rs.getString("sa_sellercode")+"' ";
+                }
+            } else {
+                // 不冲销
+                continue;
+            }
+            if (clashoption.equals("订单冲销") || clashoption.equalsIgnoreCase("SALE")) {
+                SqlStr = SqlStr + " and sf_clashoption in ('SALE','订单冲销') ";
+            } else if (clashoption.equals("发货冲销") || clashoption.equalsIgnoreCase("SEND")) {
+                SqlStr = SqlStr + " and sf_clashoption in ('SEND','发货冲销') ";
+            } else if (clashoption.equals("完工冲销") || clashoption.equalsIgnoreCase("FINISH")) {
+                SqlStr = SqlStr + " and sf_clashoption in ('FINISH','完工冲销') ";
+            }
+            if (saleclashkind.equalsIgnoreCase("product") || saleclashkind.equals("料号冲销")) {
+                SqlStr = SqlStr + " and trunc(sd_enddate)>=trunc(sysdate) ";// 只冲销有效的预测,@update 20170224 截止日期等于今日的也可冲销,与存储过程中的计算一致
+            }
+            if (fromwhere.equals("委外验退单")) {
+                SqlStr = " SELECT saleforecastDetail.*,saleforecast.*,scd_id,NVL(scd_clashqty,0)scd_clashqty,NVL(scd_cancelqty,0)scd_cancelqty,scd_id from saleclashdetail left join saleclash on scd_scid=sc_id left join saleforecast on scd_ordercode=sf_code left join saleforecastdetail on sd_sfid=sf_id  where sc_source='委外验收单' and scd_fromcode='"
+                        + rs.getString("ordercode")
+                        + "' and scd_clashqty>0 and scd_clashqty-NVL(scd_cancelqty,0)>0 and sc_statuscode='AUDITED' and sd_clashsaleqty>0 ";
+            }
+            if (fromwhere.equals("完工入库单") || fromwhere.equals("委外验收单")) {
+                if (baseDao.isDBSetting("SaleForecast", "mappingSaleForecast")) {
+                    SqlStr = SqlStr
+                            + " and saleforecast.sf_code='"
+                            + rs.getString("ma_salecode")
+                            + "' and saleforecastdetail.sd_detno="
+                            + rs.getInt("ma_saledetno")
+                            + " and saleforecast.sf_statuscode='AUDITED' and sd_qty-nvl(sd_stepqty,0)>0 order by sortid,sd_needdate asc,sd_detno asc";
+                } else {
+                    SqlStr = SqlStr
+                            + " and saleforecast.sf_statuscode='AUDITED' and sd_qty-nvl(sd_stepqty,0)>0 order by sortid,sd_needdate asc,sd_detno asc";
+                }
+            } else if (fromwhere.equals("委外验退单")) {
+                // 委外验退条件特殊,上面已加
+            } else {
+                SqlStr = SqlStr
+                        + " and saleforecast.sf_statuscode='AUDITED' and NVL(sd_statuscode,' ')<>'FINISH' and sd_qty-nvl(sd_stepqty,0)>0 order by sd_needdate asc,sd_detno asc";
+            }
+
+            if ("Y".equals(canclash) && !SqlStr.equals("")) {
+                SqlRowList rs2 = baseDao.queryForRowSet(SqlStr);
+                while (rs2.next() && clashedqty < needclashqty) {
+                    double remain = rs2.getDouble("sd_qty") - rs2.getDouble("sd_stepqty");
+                    int cancelsourceid = 0;
+                    if (fromwhere.equals("委外验退单")) {
+                        remain = (rs2.getDouble("scd_clashqty") - rs2.getDouble("scd_cancelqty"));// 拿冲销数反冲减预测
+                        cancelsourceid = rs2.getInt("scd_id");
+                        if (remain <= 0) {
+                            continue;
+                        }
+                    }
+                    thisqty = remain > needclashqty - clashedqty ? needclashqty - clashedqty : remain;
+                    if (clashcode == "") {
+                        clashcode = baseDao.sGetMaxNumber("SaleClash", 2);
+                        csid = baseDao.getSeqId("SALECLASH_SEQ");
+                        SqlStr = "insert into SaleClash(sc_id,sc_code,sc_date,sc_status,sc_statuscode,sc_recorder,sc_source,sc_sourceid,sc_sourcecode)values("
+                                + csid
+                                + ",'"
+                                + clashcode
+                                + "',sysdate,'已提交','COMMITED','"+employee.getEm_name()+"','" + fromwhere + "'," + fromid + ",'" + fromcode+ "') ";
+                        baseDao.execute(SqlStr);
+                    }
+                    SqlStr = "insert into SaleClashDetail(scd_id,scd_scid,scd_detno,scd_prodcode,scd_clashqty,scd_ordercode,scd_orderdetno,scd_sourcedetid,scd_fromcode,scd_cancelid)values("
+                            + "SALECLASHDETAIL_SEQ.NEXTVAL,"
+                            + csid
+                            + ",'"
+                            + detno
+                            + "','"
+                            + prodcode
+                            + "','"
+                            + thisqty
+                            + "','"
+                            + rs2.getString("sf_code")
+                            + "','"
+                            + rs2.getInt("sd_detno")
+                            + "',"
+                            + rs.getInt("sourcedetid")
+                            + ",'"
+                            + rs.getString("ordercode") + "'," + cancelsourceid + ")";
+                    baseDao.execute(SqlStr);
+                    if (fromwhere.equals("委外验退单")) {
+                        SqlStr = "UPDATE SaleClashDetail set scd_cancelqty=nvl(scd_cancelqty,0)+" + thisqty + " where scd_id="
+                                + rs2.getInt("scd_id") + " ";
+                        baseDao.execute(SqlStr);
+                    }
+                    SqlStr = "UPDATE saleforecastDetail set sd_stepqty=nvl(sd_stepqty,0)+(" + thisqty + ") where sd_id="
+                            + rs2.getInt("sd_id") + " ";
+                    baseDao.execute(SqlStr);
+                    detno = detno + 1;
+                    clashedqty = clashedqty + thisqty;
+                }
+            }
+        }
+        if (fromwhere.equals("委外验退单") && csid > 0) {
+            SqlStr = "UPDATE SaleClashDetail set scd_clashqty=0-scd_clashqty  where scd_scid=" + csid + " ";
+            baseDao.execute(SqlStr);
+        }
+        if (!"".equals(clashcode)) {
+            // 审核冲销单
+            auditSaleClash(csid, "SaleClash",employee);
+        }
+    }
+
+    public String auditSaleClash(int sc_id, String caller,Employee employee) {
+        // 只能对状态为[已提交]的订单进行审核操作!
+        Object status = baseDao.getFieldDataByCondition("SaleClash", "sc_statuscode", "sc_id=" + sc_id);
+        if (!"AUDITED".equals(StringUtil.nvl(status, ""))){
+            return "只能对已提交的单据进行审核!";
+        }
+        String dets = baseDao
+                .getJdbcTemplate()
+                .queryForObject(
+                        "select WM_CONCAT('预测单号:'||sf_code||',行号:'||sd_detno) from (select sf_code,sd_detno from SaleForecast left join SaleForecastDetail on sf_id=sd_sfid where  (nvl(sd_statuscode,' ')<>'AUDITED' and not(sd_statuscode='COMMITED' and sf_statuscode='AUDITED')) and (sf_code,sd_detno) in (select scd_ordercode,scd_orderdetno from SaleClashDetail where scd_scid=?))",
+                        String.class, sc_id);
+        if (dets != null) {
+            return "预测单号+预测行号状态不等于已审核,不允许已审核!" + dets;
+        }
+        // 执行审核操作
+        baseDao.audit("SaleClash", "sc_id=" + sc_id, "sc_status", "sc_statuscode", "sc_auditdate", "sc_auditman",employee);
+        Object source = baseDao.getFieldDataByCondition("SaleClash", "sc_source", "sc_id=" + sc_id);
+        // 冲销数量记录在预测单中
+        SqlRowList rs = baseDao
+                .queryForRowSet(
+                        "select scd_ordercode,scd_orderdetno,sum(scd_clashqty) scd_clashqty from SaleClashDetail where scd_scid=? group by scd_ordercode,scd_orderdetno",
+                        sc_id);
+        while (rs.next()) {
+            baseDao.updateByCondition("SaleForecastDetail", "sd_qty=sd_qty-(" + rs.getDouble("scd_clashqty")
+                    + "),sd_clashsaleqty=nvl(sd_clashsaleqty,0)+" + rs.getDouble("scd_clashqty"), "sd_detno=" + rs.getInt("scd_orderdetno")
+                    + " AND sd_sfid=(SELECT sf_id FROM SaleForecast WHERE sf_code='" + rs.getString("scd_ordercode") + "')");
+            if (source != null && source.equals("销售单") && rs.getGeneralDouble("scd_clashqty") > 0) {
+                baseDao.updateByCondition("SaleForecastDetail", "sd_yqty=(case when NVL(sd_yqty,0)-(" + rs.getDouble("scd_clashqty")
+                        + ")<0 then 0 else sd_yqty-(" + rs.getDouble("scd_clashqty") + ") end)", "sd_detno=" + rs.getInt("scd_orderdetno")
+                        + " AND sd_sfid=(SELECT sf_id FROM SaleForecast WHERE sf_code='" + rs.getString("scd_ordercode") + "')");
+            }
+        }
+        return null;
+    }
+
+    /*
+     * 拨出单过账后过账拨入单
+     */
+    public String turnProdIO(int id,Employee employee) {
+        String dets = null;
+        SqlRowList rs = baseDao.queryForRowSet("select pi_relativeplace,pi_class from prodinout where pi_id=?", id);
+        if (rs.next()) {
+            SqlRowList rs1 = baseDao.queryForRowSet(
+                    "select pi_id from prodinout where pi_inoutno=? and pi_class in ('拨入单','销售拨入单') and nvl(PI_UNAUTOPOSTIN,0)=0",
+                    rs.getString("pi_relativeplace"));
+            if (rs1.next()) {
+                if (baseDao.isDBSetting("sys","cgyCheck")) {
+                    /**
+                     * maz
+                     * 出入库单判断过账人是否在明细行仓库的仓管员资料表中存在,人员资料中查找管理员一样限制如果为非仓库员不允许过账
+                     * 虚拟账号不限制 2017080135
+                     */
+                    Object type = baseDao.getFieldDataByCondition("Employee", "em_code",
+                            "em_code='"+employee.getEm_code()+"'");
+                    if (type != null) {
+                        dets = baseDao.getJdbcTemplate()
+                                .queryForObject(
+                                        "select wm_concat(pd_pdno) from prodinout,prodiodetail where pi_id=pd_piid and pi_id=? and pd_id not in "
+                                                + "(select pd_id from prodinout,prodiodetail,warehouse,warehouseman where pi_id=pd_piid and pd_whcode=wh_code and wh_id=wm_whid "
+                                                + "and pi_id=? and wm_cgycode=?)", String.class, rs1.getInt("pi_id"),
+                                        rs1.getInt("pi_id"), employee.getEm_code());
+                    }
+                }
+                if (dets == null) {
+                    if ("拨出单".equals(rs.getString("pi_class"))) {
+                        postProdInOut(rs1.getInt("pi_id"), "ProdInOut!AppropriationIn",employee);
+                    } else if ("销售拨出单".equals(rs.getString("pi_class"))) {
+                        postProdInOut(rs1.getInt("pi_id"), "ProdInOut!SaleAppropriationIn",employee);
+                    }
+                }
+            }
+        }
+        return dets;
+    }
+
+    /**
+     * @author XiaoST 2016年8月25日 下午7:18:45 更新工单的完工状态,在完工入库,委外验收,验退过账,反过账时调用
+     */
+    public void updateMakeFinishStatus(Integer ma_id) {
+        baseDao.execute("update make set ma_madeqty=nvl((select sum(pd_inqty-pd_outqty) from prodiodetail where " +
+                "pd_ordercode=ma_code and pd_piclass in ('委外验收单','完工入库单','委外验退单') and pd_status>0),0) WHERE ma_id="
+                + ma_id);
+        baseDao.execute("update make set ma_finishstatuscode='COMPLETED',ma_finishstatus='已完工' where ma_id=" + ma_id + " and ma_madeqty>=ma_qty  ");
+        baseDao.execute("update make set ma_finishstatuscode='PARTFI',ma_finishstatus='部分完工' where ma_id="
+                + ma_id + " and ma_madeqty>0 and ma_madeqty<ma_qty  ");
+        baseDao.execute("update make set ma_finishstatuscode='UNCOMPLET',ma_finishstatus='未完工' where ma_id=" + ma_id + " and ma_madeqty=0  ");
+    }
+
+    private void changeMaStatus(int pi_id) {
+        String ids = baseDao
+                .getJdbcTemplate()
+                .queryForObject(
+                        "select wm_concat(ma_id) from (select distinct ma_id from ProdIODetail left join make on ma_code=pd_ordercode where pd_piid=?)",
+                        String.class, pi_id);
+        if (ids != null) {
+            updateMakeGetStatus(ids);
+        }
+    }
+
+    /**
+     * 修改工单领料状态
+     */
+    public void updateMakeGetStatus(String ids) {
+        baseDao.execute("update make set ma_turnstatuscode='UNGET',ma_turnstatus='未领料' where ma_id in ("
+                + ids + ") and not exists(select 1 from makematerial where mm_maid=ma_id and NVL(mm_havegetqty,0)+NVL(mm_totaluseqty,0)>0)");
+        baseDao.execute("update make set ma_turnstatuscode='PARTGET',ma_turnstatus='部分转领料' where ma_id in ("
+                + ids + ") and nvl(ma_turnstatuscode,' ')<>'PARTGET' and exists (select 1 from makematerial where mm_maid=ma_id "
+                + "and NVL(mm_havegetqty,0)+NVL(mm_totaluseqty,0)+NVL(mm_turnaddqty,0)>0 and NVL(mm_materialstatus,' ')=' ')");
+        baseDao.execute("update make set ma_turnstatuscode='TURNGET',ma_turnstatus='已转领料' where ma_id in ("
+                + ids + ") and nvl(ma_turnstatuscode,' ')<>'TURNGET' and not exists(select 1 from makematerial where mm_maid=ma_id "
+                + "and nvl(MM_QTY,0)-NVL(mm_havegetqty,0)-NVL(mm_totaluseqty,0)-NVL(mm_turnaddqty,0)>0 and NVL(mm_materialstatus,' ')=' ')");
+    }
 }

+ 7 - 7
src/main/java/com/uas/eis/service/Impl/ScheduleTaskServiceImpl.java

@@ -81,10 +81,10 @@ public class ScheduleTaskServiceImpl implements ScheduleTaskService {
     @Override
     public void syncMakeBaseDetails() {
         SqlRowList rs = baseDao.queryForRowSet("select id,mm_code,mm_detno from mes_makematerial where status='W' order by id");
-        while (rs.next()){
+        while (rs.next()) {
             int count = baseDao.getCount("select count(1) from mes_make where status='D' and action<>'D' and ma_code='" + rs.getGeneralString("mm_code") + "'");
-            if (count>0) {
-                MakeMaterial makeMaterial = baseDao.getJdbcTemplate().queryForObject("select mm_code,erpid,mm_prodcode,pr_detail,pr_spec,pr_unit,mm_oneuseqty qty,mm_qty,mm_oneuseqty,case when mm_ifrep=-1 then 'alternative' else 'main' end type,bo_recorder,to_char(bo_date,'yyyy-MM-dd HH24:mi:ss') bo_date,nvl(bo_version,0) bo_version,nvl(bo_cop,'BYT') bo_cop,case when nvl(mm_repprodcode,'\"\"')='\"\"' then mm_prodcode else mm_repprodcode end,mm_balance,nvl(cu_mescode,ma_custcode) ma_custcode,to_char(mc_indate,'yyyy-MM-dd HH24:mi:ss') mc_indate,mc_recorder,flag from mes_makematerial left join make on ma_id=mm_maid left join Product on mm_prodcode=pr_code left join bom on bo_id=mm_bomid left join MakeMaterialChangeDet on md_makecode=ma_code and md_mmdetno=mm_detno left join MakeMaterialChange on mc_id=md_mcid left join customer on ma_custcode=cu_code where id=? order by mm_detno", new BeanPropertyRowMapper<MakeMaterial>(MakeMaterial.class), rs.getInt("id"));
+            if (count > 0) {
+                MakeMaterial makeMaterial = baseDao.getJdbcTemplate().queryForObject("select id,mm_code,erpid,mm_prodcode,pr_detail,pr_spec,pr_unit,mm_oneuseqty qty,mm_qty,mm_oneuseqty,case when mm_ifrep=-1 then 'alternative' else 'main' end type,bo_recorder,to_char(bo_date,'yyyy-MM-dd HH24:mi:ss') bo_date,nvl(bo_version,0) bo_version,nvl(bo_cop,'BYT') bo_cop,mm_prodcode mm_repprodcode,mm_balance,nvl(cu_mescode,ma_custcode) ma_custcode,to_char(mc_indate,'yyyy-MM-dd HH24:mi:ss') mc_indate,mc_recorder,flag from mes_makematerial left join make on ma_id=mm_maid left join Product on mm_prodcode=pr_code left join bom on bo_id=mm_bomid left join MakeMaterialChangeDet on md_makecode=ma_code and md_mmdetno=mm_detno left join MakeMaterialChange on mc_id=md_mcid left join customer on ma_custcode=cu_code where id=? order by mm_detno", new BeanPropertyRowMapper<MakeMaterial>(MakeMaterial.class), rs.getInt("id"));
                 makeMaterial.setMesUser(tokenConfig.get("mesUser"));
                 makeMaterial.setMesPwd(MD5Util.encodeByMD5(tokenConfig.get("mesPwd")));
                 Map<String, Object> map = syncMES(JSON.toJSONString(makeMaterial, SerializerFeature.WriteMapNullValue).replace("null", "\"\""), tokenConfig.get("syncMakeBaseDetail"));
@@ -92,14 +92,14 @@ public class ScheduleTaskServiceImpl implements ScheduleTaskService {
                     int code = Integer.parseInt(StringUtil.nvl(map.get("code"), "-1"));
                     if (code == 0) {
                         baseDao.updateByCondition("mes_makematerial", "status='D'", "status='W' and id=" + rs.getInt("id"));
-                    } else {
-                        baseDao.updateByCondition("mes_makematerial", "status='F'", "status='W' and id=" + rs.getInt("id"));
-                        baseDao.execute("insert into meserrorlog (mel_id,mel_url,mel_error,mel_indate,mel_djcode,mel_djdetno,mel_type) values(MESERRORLOG_SEQ.NEXTVAL,'" + tokenConfig.get("syncMakeBaseDetail") + "','" + StringUtil.nvl(map.get("msg"), "") + "',sysdate,'" + rs.getGeneralString("mm_code") + "',"+rs.getInt("mm_detno")+",'工单BOM')");
+                        } else {
+                            baseDao.updateByCondition("mes_makematerial", "status='F'", "status='W' and id=" + rs.getInt("id"));
+                            baseDao.execute("insert into meserrorlog (mel_id,mel_url,mel_error,mel_indate,mel_djcode,mel_djdetno,mel_type) values(MESERRORLOG_SEQ.NEXTVAL,'" + tokenConfig.get("syncMakeBaseDetail") + "','" + StringUtil.nvl(map.get("msg"), "") + "',sysdate,'" + rs.getGeneralString("mm_code") + "'," + rs.getInt("mm_detno") + ",'工单BOM')");
+                        }
                     }
                 }
             }
         }
-    }
 
     private Map<String, Object> syncMES(String params,String url){
         Map<String, Object> map = new HashMap<>();

+ 11 - 0
src/main/java/com/uas/eis/utils/BaseUtil.java

@@ -166,5 +166,16 @@ public class BaseUtil {
 			return JSONUtil.toMap(formStore);
 		}
 	}
+
+	public static String parseMap2Str(Map<?, Object> map) {
+		if (map != null) {
+			return JacksonUtil.toJson(map);
+		}
+		return null;
+	}
+
+	public static String parseGridStore2Str(List<Map<String, Object>> list) {
+		return JacksonUtil.toJsonArray(list);
+	}
 	
 }

+ 1 - 1
src/main/resources/application-prod.yml

@@ -2,7 +2,7 @@ spring:
     datasource:
         type: org.apache.tomcat.jdbc.pool.DataSource
         driverClassName: oracle.jdbc.OracleDriver
-        username: BOYT
+        username: BOYT_TEST
         password: select!#%*(
         url: jdbc:oracle:thin:@192.168.16.243:1521:orcl
     redis: