// API to add component transaction lines in M_WorkOrderTransactionLine. Called from MWarehouseTask for WMS integration. /** * Api to add component transaction lines. * @param ctx * @param VAMFG_M_WorkOrder_ID Work Order * @param M_WorkOrderComponent_ID Work Order Component * @param Qty Number of components to be issued * @param M_Locator_ID Supply Locator for the component * @param trx * @return int M_WorkOrderTransactionLine_ID */ public int AddComponentTxnLine(Ctx ctx, int M_WorkOrderComponent_ID, Decimal Qty, int M_Locator_ID, Trx trx) { ViennaAdvantage.Model.MVAMFGMWorkOrderComponent woc = new ViennaAdvantage.Model.MVAMFGMWorkOrderComponent(ctx, M_WorkOrderComponent_ID, trx); MVAMFGMWorkOrderOperation woo = new MVAMFGMWorkOrderOperation(ctx, woc.GetVAMFG_M_WorkOrderOperation_ID(), trx); ViennaAdvantage.Model.MVAMFGMWrkOdrTransaction wot = RetrieveWOTxn(ctx, woo.GetVAMFG_M_WorkOrder_ID(), X_VAMFG_M_WrkOdrTransaction.VAMFG_WORKORDERTXNTYPE_1_ComponentIssueToWorkOrder, trx); if (wot == null) { log.Severe("Cannot create or retrieve WO Txn."); return(0); } ViennaAdvantage.Model.MVAMFGMWrkOdrTrnsctionLine wotLine = new ViennaAdvantage.Model.MVAMFGMWrkOdrTrnsctionLine(ctx, 0, trx); wotLine.SetRequiredColumns(wot.GetVAMFG_M_WrkOdrTransaction_ID(), woc.GetM_Product_ID(), woc.GetM_AttributeSetInstance_ID(), woc.GetC_UOM_ID(), Qty, woc.GetVAMFG_M_WorkOrderOperation_ID(), woc.GetBasisType()); wotLine.SetC_BPartner_ID(wot.GetC_BPartner_ID()); wotLine.SetC_BPartner_Location_ID(wot.GetC_BPartner_Location_ID()); wotLine.SetM_Locator_ID(M_Locator_ID); if (save) { if (!wotLine.Save(trx)) { log.Severe("Could not save component transaction line."); return(0); } } return(wotLine.GetVAMFG_M_WrkOdrTrnsctionLine_ID()); }
// API to generate component transaction lines in M_WorkOrderTransactionLine. It should be possible to generate component lines // for all push / pull components in a specific operation and all push / pull components in all operations in a work order /** * api to generate component transaction lines in M_WorkOrderTransactionLine. Skips Optional operations unless they are either the starting operation sequence or ending operation sequence in the list of operations specified * @param ctx * @param M_WorkOrderTransaction_ID Work Order Transaction * @param Qty Number of Work Order Product Assemblies for which to generate components * @param OperationFrom Starting operation sequence number * @param OperationTo Ending operation sequence number * @param SupplyType Component Supply Type. Valid values are P (Push), O (Operation Pull), A (Assembly Pull) * @param M_Locator_ID Supply Locator for the components in case of Push supply type * @param trx * @return Array of MVAMFGMWrkOdrTrnsctionLine */ public ViennaAdvantage.Model.MVAMFGMWrkOdrTrnsctionLine[] GenerateComponentTxnLine(Ctx ctx, int M_WorkOrderTransaction_ID, Decimal?Qty, Decimal?OperationFrom, Decimal?OperationTo, String SupplyType, int M_Locator_ID, Trx trx) { int _countGOM01 = 0; Tuple <String, String, String> mInfo = null; if (Env.HasModulePrefix("GOM01_", out mInfo)) { _countGOM01 = 1; } if (OperationFrom != null && OperationFrom.Value.CompareTo(OperationTo) > 0) { log.Severe("Operation Numbers not correct."); return(null); } ViennaAdvantage.Model.MVAMFGMWrkOdrTransaction wot = new ViennaAdvantage.Model.MVAMFGMWrkOdrTransaction(ctx, M_WorkOrderTransaction_ID, trx); if (0 == M_WorkOrderTransaction_ID || !((wot.GetDocStatus().Equals(X_VAMFG_M_WrkOdrTransaction.DOCSTATUS_Drafted) || wot.GetDocStatus().Equals(X_VAMFG_M_WrkOdrTransaction.DOCSTATUS_InProgress)) && (wot.GetVAMFG_WorkOrderTxnType().Equals(X_VAMFG_M_WrkOdrTransaction.VAMFG_WORKORDERTXNTYPE_1_ComponentIssueToWorkOrder) || wot.GetVAMFG_WorkOrderTxnType().Equals(X_VAMFG_M_WrkOdrTransaction.VAMFG_WORKORDERTXNTYPE_ComponentReturnFromWorkOrder)))) { log.Severe("Cannot create component lines against give WO Txn."); return(null); } if (Qty != null && Qty.Value.CompareTo(Decimal.Zero) <= 0) { log.Severe("Number of product assemblies must be positive"); return(null); } //ArrayList<MVAMFGMWrkOdrTrnsctionLine> wotLines = new ArrayList<MVAMFGMWrkOdrTrnsctionLine>(); // List<MVAMFGMWrkOdrTrnsctionLine> wotLines = new List<MVAMFGMWrkOdrTrnsctionLine>(); ArrayList wotLines = new ArrayList(); int lastMandatoryWOO = DB.GetSQLValue(trx, "SELECT MAX(VAMFG_SeqNo) FROM VAMFG_M_WorkOrderOperation " + "WHERE VAMFG_M_WorkOrder_ID = " + wot.GetVAMFG_M_WorkOrder_ID() + " AND VAMFG_IsOptional<>'Y'"); // automatically consider AssemblyPull Supply Type when the OperationTo is greater than the last Work Order Operation. // This in turn should take care of optional operations. bool assemblyPull = lastMandatoryWOO == OperationTo; StringBuilder response = new StringBuilder(""); // Getting the WorkOrder product assembly quantity Decimal woQty = DB.GetSQLValue(trx, "SELECT VAMFG_QtyEntered FROM VAMFG_M_WorkOrder " + "WHERE VAMFG_M_WorkOrder_ID = " + wot.GetVAMFG_M_WorkOrder_ID()); // Get component requirements based on the operations moved through in this transaction and then make lines StringBuilder sqlBuf = new StringBuilder("SELECT woc.M_Product_ID, woc.C_UOM_ID, woc.VAMFG_QtyRequired, " + " woc.VAMFG_SupplyType, woc.M_AttributeSetInstance_ID, woc.M_Locator_ID, woc.BasisType," + " woo.VAMFG_M_WorkOrderOperation_ID, woc.VAMFG_QtyAvailable, woc.VAMFG_QtySpent," + " woc.VAMFG_QtyAllocated, woc.VAMFG_QtyDedicated,woc.isqualitycorrection" + " FROM VAMFG_M_WorkOrderOperation woo INNER JOIN VAMFG_M_WorkOrderComponent woc ON woo.VAMFG_M_WorkOrderOperation_ID = woc.VAMFG_M_WorkOrderOperation_ID" + " WHERE woo.VAMFG_M_WorkOrder_ID = " + wot.GetVAMFG_M_WorkOrder_ID() + " AND woc.VAMFG_QtyRequired != 0 AND (woo.VAMFG_IsOptional <> 'Y' OR "); if (OperationFrom != null && OperationFrom.Value.CompareTo(Decimal.Zero) > 0) { sqlBuf.Append(" woo.VAMFG_SeqNo =" + VAdvantage.Utility.Util.GetValueOfInt(OperationFrom)); sqlBuf.Append(" OR woo.VAMFG_SeqNo =" + VAdvantage.Utility.Util.GetValueOfInt(OperationTo)); sqlBuf.Append(")"); } else { sqlBuf.Append(" woo.VAMFG_SeqNo =0"); sqlBuf.Append(" OR woo.VAMFG_SeqNo =0"); sqlBuf.Append(")"); } // Set OperationTo sequence no if (OperationTo != null && OperationTo.Value.CompareTo(Decimal.Zero) > 0) { sqlBuf.Append(" AND ((woo.VAMFG_SeqNo BETWEEN " + VAdvantage.Utility.Util.GetValueOfInt(OperationFrom) + " AND " + VAdvantage.Utility.Util.GetValueOfInt(OperationTo)); sqlBuf.Append(")"); } else { sqlBuf.Append(" AND ((woo.VAMFG_SeqNo BETWEEN " + lastMandatoryWOO + " AND 0"); sqlBuf.Append(")"); } if (assemblyPull) // if assembly pull, then get component lines from all operations except { sqlBuf.Append(" OR woc.VAMFG_SupplyType = 'A'"); } sqlBuf.Append(" ) ORDER BY woo.VAMFG_SeqNo, woc.M_Product_ID, woc.VAMFG_QtyRequired "); // close the statement and add ORDER BY clause String sql = sqlBuf.ToString(); // SqlParameter[] param = null; IDataReader idr = null; DataTable dt = new DataTable(); try { //pstmt.setInt(1, wot.GetVAMFG_M_WorkOrder_ID()); // woo.VAMFG_M_WorkOrder_ID //param = new SqlParameter[5]; //param[0] = new SqlParameter("@param1", wot.GetVAMFG_M_WorkOrder_ID()); //// Set OperationFrom sequence no //if (OperationFrom != null && OperationFrom.Value.CompareTo(Decimal.Zero) > 0) //{ // param[1] = new SqlParameter("@param2", VAdvantage.Utility.Util.GetValueOfInt(OperationFrom)); // param[3] = new SqlParameter("@param4", VAdvantage.Utility.Util.GetValueOfInt(OperationFrom)); // //pstmt.setInt(2, OperationFrom.intValue()); // //pstmt.setInt(4, OperationFrom.intValue()); //} //else //{ // param[1] = new SqlParameter("@param2", 0); // param[3] = new SqlParameter("@param4", 0); // //pstmt.setInt(2, 0); // //pstmt.setInt(4, 0); //} //// Set OperationTo sequence no //if (OperationTo != null && OperationTo.Value.CompareTo(Decimal.Zero) > 0) //{ // param[2] = new SqlParameter("@param3", VAdvantage.Utility.Util.GetValueOfInt(OperationTo)); // param[4] = new SqlParameter("@param5", VAdvantage.Utility.Util.GetValueOfInt(OperationTo)); // //pstmt.setInt(3, OperationTo.intValue()); // //pstmt.setInt(5, OperationTo.intValue()); //} //else //{ // param[2] = new SqlParameter("@param3", lastMandatoryWOO); // param[4] = new SqlParameter("@param5", 0); // //pstmt.setInt(3, lastMandatoryWOO); // //pstmt.setInt(5, 0); //} //rs = pstmt.executeQuery(); idr = DB.ExecuteReader(sql.ToString(), null, trx); //dt.Load(idr); //idr.Close(); int productID = 0; int uomID = 0; Decimal qtyEntered = Decimal.Zero; // Quantity in the Product Transaction Line Decimal QtyInKg = Decimal.Zero; // Quantity in KG at Product Transaction Line int asiID = 0; int locatorID = 0; // set the component line no to 10 greater than existing int compLineNo = DB.GetSQLValue(trx, "SELECT COALESCE(MAX(VAMFG_Line),0)+10 FROM VAMFG_M_WrkOdrTrnsctionLine " + "WHERE VAMFG_M_WrkOdrTransaction_ID =" + M_WorkOrderTransaction_ID); bool checkInventory = wot.GetVAMFG_WorkOrderTxnType().Equals(X_VAMFG_M_WrkOdrTransaction.VAMFG_WORKORDERTXNTYPE_1_ComponentIssueToWorkOrder); while (idr.Read()) { productID = VAdvantage.Utility.Util.GetValueOfInt(idr[0]); uomID = VAdvantage.Utility.Util.GetValueOfInt(idr[1]); Decimal qtyRequired = VAdvantage.Utility.Util.GetValueOfDecimal(idr[2]); String wocSupplyType = VAdvantage.Utility.Util.GetValueOfString(idr[3]); asiID = VAdvantage.Utility.Util.GetValueOfInt(idr[4]); locatorID = VAdvantage.Utility.Util.GetValueOfInt(idr[5]); String basisType = VAdvantage.Utility.Util.GetValueOfString(idr[6]); int wooID = VAdvantage.Utility.Util.GetValueOfInt(idr[7]); string IsQualityCorr = VAdvantage.Utility.Util.GetValueOfString(idr[12]); // If qty=0, then no value was passed for Qty // for Component Issue assume issue needs to be generated for remaining amount // for Component Return assume return needs to be generated for unused quantity Decimal qtyIssued = VAdvantage.Utility.Util.GetValueOfDecimal(idr[8]); Decimal qtySpent = VAdvantage.Utility.Util.GetValueOfDecimal(idr[9]); Decimal qtyAllocated = VAdvantage.Utility.Util.GetValueOfDecimal(idr[10]); Decimal qtyDedicated = VAdvantage.Utility.Util.GetValueOfDecimal(idr[11]); // continue if component line is quality correction if (IsQualityCorr == "Y") { continue; } if (Qty == null) { if (wot.GetVAMFG_WorkOrderTxnType().Equals(X_VAMFG_M_WrkOdrTransaction.VAMFG_WORKORDERTXNTYPE_1_ComponentIssueToWorkOrder)) { // qtyEntered = (qtyRequired.multiply(woQty)).subtract(qtyIssued).subtract(qtyAllocated).subtract(qtyDedicated); qtyEntered = Decimal.Subtract(Decimal.Subtract(Decimal.Subtract(Decimal.Multiply(qtyRequired, woQty), qtyIssued), qtyAllocated), qtyDedicated); } else // automatically assume ComponentReturn txn { qtyEntered = Decimal.Subtract(qtyIssued, qtySpent); } } else { qtyEntered = Decimal.Multiply(qtyRequired, Qty.Value); if (wot.GetVAMFG_WorkOrderTxnType().Equals(X_VAMFG_M_WrkOdrTransaction.VAMFG_WORKORDERTXNTYPE_ComponentReturnFromWorkOrder) //&& qtyEntered.setScale(MUOM.getPrecision(ctx, uomID), Decimal.ROUND_HALF_UP).compareTo(qtyIssued.subtract(qtySpent)) > 0) && Decimal.Round((qtyEntered), VAdvantage.Model.MUOM.GetPrecision(ctx, uomID), MidpointRounding.AwayFromZero).CompareTo(Decimal.Subtract(qtyIssued, qtySpent)) > 0) { log.Warning("Not enough quantities to return from Work Order"); continue; } } // For Pull type: If quantity requirement has been filled or there are not enough quantities to issue // then don't generate a line -> goto next line processing //if (qtyEntered.setScale(MUOM.getPrecision(ctx, uomID), Decimal.ROUND_HALF_UP).compareTo(Decimal.Zero) <= 0) // continue; if (Decimal.Round((qtyEntered), VAdvantage.Model.MUOM.GetPrecision(ctx, uomID), MidpointRounding.AwayFromZero).CompareTo(Decimal.Zero) <= 0) { continue; } if (SupplyType.Equals(wocSupplyType) || (wocSupplyType.Equals(X_VAMFG_M_WorkOrderComponent.VAMFG_SUPPLYTYPE_AssemblyPull) && assemblyPull && !SupplyType.Equals(X_VAMFG_M_WorkOrderComponent.VAMFG_SUPPLYTYPE_Push))) { ViennaAdvantage.Model.MVAMFGMWrkOdrTrnsctionLine compIssueLine = new ViennaAdvantage.Model.MVAMFGMWrkOdrTrnsctionLine(ctx, 0, trx); // set the client + org derived from the transaction header compIssueLine.SetClientOrg(wot); // Work done to add attributeset Instance ID for finished products compIssueLine.SetRequiredColumns(M_WorkOrderTransaction_ID, productID, asiID, uomID, qtyEntered, wooID, basisType); // Added by Bharat on 26 Dec 2017 to set Business Partner Information on Line compIssueLine.SetC_BPartner_ID(wot.GetC_BPartner_ID()); compIssueLine.SetC_BPartner_Location_ID(wot.GetC_BPartner_Location_ID()); if (locatorID != 0) // Implicit assumption : Only Pull components will have a locator populated in the WOC { // compIssueLine.SetM_Locator_ID(locatorID); ((X_VAMFG_M_WrkOdrTrnsctionLine)compIssueLine).SetM_Locator_ID(locatorID); } else { // Check if the locator passed is under the Warehouse of the Work Order // If no, then skip generating transaction line for this component ViennaAdvantage.Model.MVAMFGMWorkOrder wo = new ViennaAdvantage.Model.MVAMFGMWorkOrder(ctx, wot.GetVAMFG_M_WorkOrder_ID(), trx); MLocator loc = new MLocator(ctx, M_Locator_ID, trx); if (loc.GetM_Warehouse_ID() != wo.GetM_Warehouse_ID()) { log.Warning("Locator passed is not under the Warehouse of the WorkOrder"); continue; } ((X_VAMFG_M_WrkOdrTrnsctionLine)compIssueLine).SetM_Locator_ID(M_Locator_ID); } if (asiID > 0) { compIssueLine.SetM_AttributeSetInstance_ID(asiID); } compIssueLine.SetVAMFG_Line(compLineNo); compLineNo += 10; // Added by Bharat on 20/12/2016 to Set Density and Liter values for production execution Process of Gulf Oil. if (_countGOM01 > 0) { Decimal density = wot.GetGOM01_Density(); QtyInKg = Decimal.Multiply(qtyEntered, density); QtyInKg = Decimal.Round((QtyInKg), VAdvantage.Model.MUOM.GetPrecision(ctx, uomID)); Decimal ltrQty = density > 0 ? QtyInKg / density : 0; compIssueLine.SetGOM01_Quantity(QtyInKg); compIssueLine.SetGOM01_ActualQuantity(QtyInKg); compIssueLine.SetGOM01_Density(density); compIssueLine.SetGOM01_Litre(Decimal.Round((ltrQty), VAdvantage.Model.MUOM.GetPrecision(ctx, uomID))); compIssueLine.SetGOM01_FromProcess(true); } // End Bharat wotLines.Add(compIssueLine); VAdvantage.Model.MProduct product = new VAdvantage.Model.MProduct(ctx, productID, trx); if (checkInventory) { if (_countGOM01 > 0) { response.Append(product.GetName() + ": ").Append(VerifyQuantity(product, wot, QtyInKg, asiID)).Append(" "); } else { response.Append(product.GetName() + ": ").Append(VerifyQuantity(product, wot, qtyEntered, asiID)).Append(" "); } } if (compIssueLine.Save()) { } } } } catch (Exception e) { log.Log(Level.SEVERE, sqlBuf.ToString(), e); log.Severe("SQL failure in checking component requirements"); return(null); } finally { if (idr != null) { idr.Close(); idr = null; } } //Not using this here we have save line one by one //if (save) //{ // if (!VAdvantage.Model.PO.SaveAll(trx, wotLines)) // { // log.Severe("Could not save component transaction lines."); // return null; // } //} log.SaveInfo("Info", response.ToString()); //return wotLines.toArray(new MVAMFGMWrkOdrTrnsctionLine[] { }); ViennaAdvantage.Model.MVAMFGMWrkOdrTrnsctionLine[] newObject = null; try { newObject = (ViennaAdvantage.Model.MVAMFGMWrkOdrTrnsctionLine[])wotLines.ToArray(typeof(ViennaAdvantage.Model.MVAMFGMWrkOdrTrnsctionLine)); //newObject = new MVAMFGMWrkOdrTrnsctionLine[] { }; //newObject = Convert.ChangeType(wotLines.ToArray(), typeof(MVAMFGMWrkOdrTrnsctionLine[])); //newObject = lst.ToArray(); return(newObject); } catch { } return((ViennaAdvantage.Model.MVAMFGMWrkOdrTrnsctionLine[])wotLines.ToArray()); }