public Boolean ValidateBalanceQuantityInDocument(DocumentLine validationLine, Node node, Boolean autoThrow, bool isCrossDock) //bool isCrossDock, Adicionada en SEP/17/2009 para manejar el balance en cross dock sin tener en cuenta BO Quantities { DocumentBalance docBal = new DocumentBalance { Document = validationLine.Document, Product = validationLine.Product, Unit = validationLine.Unit, Node = node }; docBal = Factory.DaoDocumentBalance().GeneralBalance(docBal, isCrossDock).First(); //Multiplica la cantidad por la unidad base para hacer la resta //La unidad del documento de Balance es la unidad Basica if (docBal == null || docBal.BaseQtyPending < validationLine.Quantity * validationLine.Unit.BaseAmount) { if (autoThrow) { Factory.Rollback(); //throw new Exception("Current balance for document is " + (docBal.QtyPending / validationLine.Unit.BaseAmount).ToString() + " and you are trying to receive " + ((int)validationLine.Quantity).ToString() + "."); throw new Exception("Current balance for product " + docBal.Product.ProductCode + " in document " + docBal.Document.DocNumber +" is " + docBal.QtyPending.ToString() + " (" + docBal.Unit.Name + ")" + " and you are trying to process " + ((int)validationLine.Quantity).ToString() + " (" + docBal.Unit.Name + ")."); } else return false; } return true; }
public IList<Node> Select(Node data) { IList<Node> datos = new List<Node>(); try { datos = GetHsql(data).List<Node>(); if (!Factory.IsTransactional) Factory.Commit(); } catch (Exception e) { NHibernateHelper.WriteEventLog(WriteLog.GetTechMessage(e)); } return datos; }
/* private Object[] ReceiptLinesForErpDocument(Document receivingTask, Document prDocument) { Object[] result = new Object[2]; try { Node recNode = new Node { NodeID = NodeType.Received }; Node storedNode = new Node { NodeID = NodeType.Stored }; DocumentBalance docBal = new DocumentBalance { Document = receivingTask, Node = storedNode }; //Obtiene el balance linea por linea, Es decir el cruce contra lo ya posteado, porque la linea se //asigna una vez se postea, lo que no tiene linea no aparece en el balance //es decir el saldo que queda por llenar de cada linea de documento IList<DocumentBalance> balanceList = Factory.DaoDocumentBalance().DetailedBalance(docBal, false); balanceList = balanceList.OrderBy(f => f.DocumentLine.LineNumber).ToList(); //Ordernada por LineNumber //Armar las lineas del documento de Recibo IList<DocumentLine> prDocLines = new List<DocumentLine>(); NodeTrace qNodeTrace; DocumentLine rpLine; int line = 1; IList<NodeTrace> nodeTraceSameUnit; IList<NodeTrace> allNodeTrace = new List<NodeTrace>(); Status lineStatus = WType.GetStatus(new Status { StatusID = DocStatus.New }); //Label curLabel; //Recorre los saldos pendientes para ese documento foreach (DocumentBalance balance in balanceList.Where(b => b.QtyPending > 0)) { qNodeTrace = new NodeTrace { Document = receivingTask, Node = recNode, PostingDocument = new Document { DocID = 0 }, //0 mean Null Label = new Label { Product = balance.Product, Unit = balance.Unit } }; //PASO 1 : Primero buscar los nodetrace que coincidan con la unidad necesitada y traer los pendientes nodeTraceSameUnit = Factory.DaoNodeTrace().Select(qNodeTrace).ToList(); //.Take(int.Parse(balance.QtyPending.ToString())) //Si se obtienen registros if (nodeTraceSameUnit.Count > 0) { //1.1 Actualiza los que encontro foreach (NodeTrace traceSame in nodeTraceSameUnit) { traceSame.DocumentLine = balance.DocumentLine; traceSame.PostingDate = DateTime.Now; traceSame.PostingDocument = prDocument; traceSame.PostingDocLineNumber = line; traceSame.PostingUserName = prDocument.CreatedBy; traceSame.ModifiedBy = prDocument.CreatedBy; traceSame.ModDate = DateTime.Now; allNodeTrace.Add(traceSame); } //1.2 Disminuye el balance balance.QtyPending -= nodeTraceSameUnit.Sum(f => f.Quantity); //Crea una linea para el documento de recibo rpLine = new DocumentLine { Product = balance.Product, Quantity = nodeTraceSameUnit.Sum(f => f.Quantity), Unit = balance.Unit, Document = prDocument, CreationDate = DateTime.Now, IsDebit = false, LineNumber = line, LineStatus = lineStatus, Location = prDocument.Location, UnitBaseFactor = balance.Unit.BaseAmount, LinkDocNumber = balance.Document.DocNumber, LinkDocLineNumber = balance.DocumentLine.LineNumber, CreatedBy = prDocument.CreatedBy, UnitPrice = balance.UnitPrice, ExtendedPrice = balance.UnitPrice * nodeTraceSameUnit.Sum(f => f.Quantity) * balance.Unit.BaseAmount }; prDocLines.Add(rpLine); line++; } //1.4 Si encontro todos los que necesitaba se sale a la siguiente linea if (balance.QtyPending <= 0) continue; } result[0] = prDocLines; result[1] = allNodeTrace; return result; } catch (Exception ex) { //Factory.Rollback(); ExceptionMngr.WriteEvent("ReceiptLinesForErpDocument", ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Business); //throw; return null; } } */ //Actualiza el nodetrace y crea los Nuevos Registros de trace private void ProcessReceivingTransactionTrace(IList<NodeTrace> traceList, Document postedDocument, Document taskDocument, Node node) { if (traceList == null) return; Label curLabel; Status activeStatus = WType.GetStatus(new Status { StatusID = EntityStatus.Active }); foreach (NodeTrace nodeTrace in traceList) { //Actualiza el trace actual //Factory.DaoNodeTrace().Update(nodeTrace); //Pasa los labels de ese nodeTrace a Storedb //Registra el movimiento del nodo SaveNodeTrace( new NodeTrace { Node = node, Document = taskDocument, Label = nodeTrace.Label, Quantity = nodeTrace.Label.StockQty, //GetLabelStockQty(new Label { LabelID = nodeTrace.Label.LabelID }), //nodeTrace.Label.CurrQty IsDebit = nodeTrace.IsDebit, CreatedBy = postedDocument.CreatedBy, PostingDocument = postedDocument, PostingDocLineNumber = nodeTrace.PostingDocLineNumber, PostingUserName = postedDocument.CreatedBy }); //Factory.Commit(); //Pasa los labels de ese nodeTrace a Stored curLabel = nodeTrace.Label; curLabel.Node = node; curLabel.ModDate = DateTime.Now; curLabel.Status = activeStatus; curLabel.ModifiedBy = postedDocument.CreatedBy; if (curLabel.LabelCode.StartsWith("VOID_")) curLabel.LabelCode = curLabel.LabelCode.Replace("VOID_",""); Factory.DaoLabel().Update(curLabel); //Modificando las hijas try { curLabel.ChildLabels = Factory.DaoLabel().Select(new Label { FatherLabel = curLabel }); if (curLabel.ChildLabels != null && curLabel.ChildLabels.Count > 0) foreach (Label child in curLabel.ChildLabels) { child.Node = node; child.ModDate = DateTime.Now; child.ModifiedBy = child.FatherLabel.CreatedBy; child.Status = activeStatus; Factory.DaoLabel().Update(child); } } catch { } } }
/// <summary> /// Recibe producto, con etiqueta (recibo capturado por scanner generalmente) /// </summary> /// <param name="document">Task Document in Process</param> /// <param name="label">Label de transaccion </param> public Label PickLabel(Document document, Label label, Node node, Label packageLabel, SysUser picker, Bin destBin) { Factory.IsTransactional = true; //Node node = WType.GetNode(new Node { NodeID = NodeType.Picked }); try { if (label.LabelID == 0) { try { label = Factory.DaoLabel().Select(label).First(); } catch { throw new Exception("Label " + label.LabelCode + " does not exists."); } } //Check if already picked if (label.Node.NodeID == NodeType.Picked || label.Node.NodeID == NodeType.Released) throw new Exception("Label " + label.LabelCode + " already picked."); if (destBin == null) destBin = Rules.GetBinForNode(node, label.Bin.Location); Status locked = WType.GetStatus(new Status { StatusID = EntityStatus.Locked }); //Valida si el docuemnto no es nulo Rules.ValidateDocument(document, true); //Valida si el label es un label de producto, //TODO: alarma cuand o suceda el evento de que no es un label de producto Rules.ValidateIsProductLabel(label, true); Rules.ValidateBinStatus(label.Bin, true); //Valida si el status es Activo Rules.ValidateActiveStatus(label.Status, true); //Valida si el label esta en el nodo que debe estar (Ruta de Nodos) //TODO: alarma cuand o suceda el evento de que no es un label de producto Rules.ValidateNodeRoute(label, node, true); //revisa si el label tiene zero Qty Rules.ValidateLabelQuantity(label, true); //Validar si las locations son iguales Rules.ValidatePickLocation(document.Location, label.Bin.Location, true); //label.ChildLabels = Factory.DaoLabel().Select( // new Label { FatherLabel = label, Status = new Status { StatusID = EntityStatus.Active } }); if (document.IsFromErp == true) { //Valida si el producto esta en ese documento //Se debe ejecutar proceso para saber si la company permite //recibir producto no existente en el docuemnto DocumentLine docLine = new DocumentLine { Document = document, Product = label.Product, LineStatus = new Status { StatusID = DocStatus.New }, Unit = label.Unit, Quantity = label.StockQty, //label.CurrQty, CreatedBy = document.ModifiedBy }; Rules.ValidateProductInDocument(docLine, true); //Valida si hay saldo pendiente por recibir //Calcula el Current Qty y Valida si esa cantidad aun esta pendiente en el documento //Double quantity = (label.IsLogistic == true) ? Factory.DaoLabel().SelectCurrentQty(label, null, true) : label.CurrQty; Rules.ValidateBalanceQuantityInDocument(docLine, node, true, false); } if (packageLabel != null) { try { packageLabel = GetPackageLabel(packageLabel, document, picker).PackLabel; } catch (Exception ex) { Factory.Rollback(); throw new Exception("Package label could not be created.\n" + ex.Message); } } //Actualiza Label with new data label.Node = node; label.LastBin = label.Bin; label.Bin = destBin; label.ModifiedBy = picker.UserName; label.ModDate = DateTime.Now; label.ShippingDocument = document; label.Printed = true; label.Status = locked; //Registra el movimiento del label en el nodo SaveNodeTrace(new NodeTrace { Node = node, Document = document, Label = label, Quantity = label.CurrQty, IsDebit = false }); label.LabelSource = label.FatherLabel; label.FatherLabel = packageLabel; Factory.DaoLabel().Update(label); //Actualiza Los Hijos (si existen) try { label.ChildLabels = Factory.DaoLabel().Select(new Label { FatherLabel = label }); if (label.ChildLabels != null && label.ChildLabels.Count > 0) foreach (Label curLabel in label.ChildLabels) { curLabel.Node = node; curLabel.LastBin = label.LastBin; curLabel.Bin = label.Bin; curLabel.ModifiedBy = picker.UserName; curLabel.ModDate = DateTime.Now; curLabel.ShippingDocument = document; curLabel.Status = locked; SaveNodeTrace(new NodeTrace { Node = node, Document = document, Label = curLabel, Quantity = curLabel.CurrQty, IsDebit = false, CreatedBy = document.CreatedBy }); Factory.DaoLabel().Update(curLabel); } } catch { } Factory.Commit(); return label; } catch (Exception ex) { Factory.Rollback(); ExceptionMngr.WriteEvent("PickLabel:", ListValues.EventType.Error, ex, null, ListValues.ErrorCategory.Business); throw new Exception(WriteLog.GetTechMessage(ex)); } }
public Boolean ValidateNodeRoute(Label label, Node node, Boolean autoThrow) { NodeRoute nodeRoute = new NodeRoute { NextNode = node, CurNode = label.Node }; if (Factory.DaoNodeRoute().Select(nodeRoute).Count == 0) { if (autoThrow) { Factory.Rollback(); throw new Exception("Transaction from " + label.Node.Name + " to " + node.Name + " not allowed."); } else return false; } return true; }
internal Boolean ValidateVoided(Node node, bool autoThrow) { if (node.NodeID != NodeType.Voided) return true; if (autoThrow) { Factory.Rollback(); throw new Exception("Label appears as voided."); } else return false; }
public Hero(int health, int maxHealth, ref Model modelwalk, ref Model modeldie, ref Model modelhurt, Action<Entity, Entity> actionFunction) : base() { this.model = modelwalk; this.HealthPoints = health; this.MaxHealth = maxHealth; this.Stance = AnimationStance.Standing; PowerupsList = new List<Powerup>(); ItemsList = new Dictionary<Item, int>(); WeaponsList = new Dictionary<Weapon, int>(); this.ActionFunction = actionFunction; //get animations // Look up our custom skinning information. for walking skinningDatawalk = (SkinningData)modelwalk.Tag; if (skinningDatawalk == null) throw new InvalidOperationException ("This model does not contain a SkinningData tag."); // Create an animation player, and start decoding an animation clip. animationPlayerwalk = new AnimationPlayer(skinningDatawalk); clipwalk = skinningDatawalk.AnimationClips["Take 001"]; animationPlayerwalk.StartClip(clipwalk); // Look up our custom skinning information. for dying skinningDatadie = (SkinningData)modeldie.Tag; if (skinningDatadie == null) throw new InvalidOperationException ("This model does not contain a SkinningData tag."); // Create an animation player, and start decoding an animation clip. animationPlayerdie = new AnimationPlayer(skinningDatadie); clipdie = skinningDatadie.AnimationClips["Take 001"]; animationPlayerdie.StartClip(clipdie); // Look up our custom skinning information. for hurting skinningDatahurt = (SkinningData)modelhurt.Tag; if (skinningDatahurt == null) throw new InvalidOperationException ("This model does not contain a SkinningData tag."); // Create an animation player, and start decoding an animation clip. animationPlayerhurt = new AnimationPlayer(skinningDatahurt); cliphurt = skinningDatahurt.AnimationClips["Take 001"]; animationPlayerhurt.StartClip(cliphurt); //adding flanking info for (int i = 0; i < 6; i++) { slots[i] = new Node(); } }
private void ProcessPrintingLine(DocumentBalance printLine, String printLot, Node node, Bin bin, UserByRol userByRol) { //Tipo De impresion //1. Normal Imprime standar, sin logistica //2. Logistic (Notes tiene data) - imprime normal mas la Logistica Unit logisticUnit = null; //bool printOnlyLogistic = false; if (printLine.Notes != null && printLine.Notes.Contains("Pack")) { string[] dataLogistic = printLine.Notes.Split(':'); //El elemento [1] contiene la unidad logistica, si es cero es custom. if (dataLogistic[2].Equals(WmsSetupValues.CustomUnit)) { try { //trata de encontrar una unidad con ese baseamount logisticUnit = Factory.DaoUnit().Select( new Unit { BaseAmount = printLine.QtyPending, Company = userByRol.Location.Company, ErpCodeGroup = printLine.Unit.ErpCodeGroup } ).First(); } catch { //Obtiene la custom logisticUnit = Factory.DaoUnit().SelectById(new Unit { UnitID = int.Parse(dataLogistic[1]) }); } } else // Si no es Custom { logisticUnit = Factory.DaoUnit().SelectById(new Unit { UnitID = int.Parse(dataLogistic[1]) }); } } //Se ingresa para poder sacar el dato de la company if (printLine.Document == null) printLine.Document = new Document { Company = userByRol.Location.Company }; //CReating Document Line to Send DocumentLine prnLine = new DocumentLine { Product = printLine.Product, Document = printLine.Document, Unit = printLine.Unit, Quantity = printLine.Quantity, CreatedBy = userByRol.User.UserName }; if (logisticUnit != null) logisticUnit.BaseAmount = printLine.QtyPending; //Obteniendo el factor logistico antes de enviar a crear los labels double logisticFactor = (logisticUnit != null) ? printLine.QtyPending : 1; //Manda a Crear los Labels IList<Label> resultList = CreateProductLabels(logisticUnit, prnLine, node, bin, logisticFactor, printLot,"", DateTime.Now) .Where(f => f.FatherLabel == null).ToList(); foreach (Label lbl in resultList) this.listOfLabels.Add(lbl); }
public IList<ProductStock> GetNodeStock(ProductStock data, Node node, Status status) { string initQuery = "SELECT l.ProductID, l.UnitID, 0 as BinID, Sum(l.SingleQuantity) AS Stock, Sum(l.PackQuantity) as PackStock, " + " Max(l.MaxDate) as MaxDate, Min(l.MinDate) as MinDate " + " FROM vwStockSummary AS l Where (l.SingleQuantity > 0 Or l.PackQuantity > 0) And l.NodeID = :nid And l.StatusID = :sid "; StringBuilder sql = new StringBuilder(initQuery); Parms = new List<Object[]>(); Parms.Add(new Object[] { "nid", node.NodeID }); Parms.Add(new Object[] { "sid", status.StatusID }); if (data.Product != null && data.Product.ProductID != 0) { sql.Append(" and l.ProductID = :id1 "); Parms.Add(new Object[] { "id1", data.Product.ProductID }); } if (data.Bin != null && data.Bin.BinID != 0) { sql.Append(" and l.BinID = :id2 "); Parms.Add(new Object[] { "id2", data.Bin.BinID }); } if (data.Bin != null && data.Bin.Location != null && data.Bin.Location.LocationID != 0) { sql.Append(" and l.LocationID = :id3 "); Parms.Add(new Object[] { "id3", data.Bin.Location.LocationID }); } sql.Append(" Group By l.ProductID, l.UnitID "); IQuery query = Factory.Session.CreateSQLQuery(sql.ToString()); SetParameters(query); IList<ProductStock> ret = GetProductStockObject(query.List<Object[]>(), Factory); if (!Factory.IsTransactional) Factory.Commit(); return ret; }
public Label PickUniqueLabel(Document document, Node node, Product product, string serialLabel, SysUser picker, Label packLabel) { //Valida si el label piquedo esta disponible y pertenece al producto y luego lo manda a PickLabel Label label = new Label { LabelCode = serialLabel, //LabelType = new DocumentType { DocTypeID = LabelType.UniqueTrackLabel }, LabelType = new DocumentType { DocTypeID = LabelType.ProductLabel }, Product = new Product { ProductID = product.ProductID } }; try { label = Factory.DaoLabel().Select(label).First(); } catch { throw new Exception("Barcode " + serialLabel + " does not exists for product " + product.FullDesc + "."); } return PickLabel(document, label, node, packLabel, picker, null); }
//Permite reversar un documento que fue creado y enviado al ERP //solo se reversa si en el ERP no lo ha posteado public void ReverseShipmentDocument(Document data, Bin binRestore) { Factory.IsTransactional = true; //Revisa si se debe enviar el recibo al ERP, es decir si esta en true la opcion de conexion a ERP bool ErpConnected = GetCompanyOption(data.Company, "WITHERPSH").Equals("T"); Node releaseNode = new Node { NodeID = NodeType.Released }; Node storeNode = new Node { NodeID = NodeType.Stored }; try { //Update document status to Cancelled Status cancelled = WType.GetStatus(new Status { StatusID = DocStatus.Cancelled }); Status inactive = WType.GetStatus(new Status { StatusID = EntityStatus.Inactive }); Status active = WType.GetStatus(new Status { StatusID = EntityStatus.Active }); //Cancelacion del Assembly Order en caso de que haya conexion al ERP y la opcion // ERPASMORDER este en True para esa compania // 22 Mayo de 2007, Mande el resultado a Notes para poder enviarlo en el mail // COMENTARIADO EL 3 Junio de 2009 - Se quita el envio a GP /* if (GetCompanyOption(data.Company, "SHOWCOMP").Equals("T") && GetCompanyOption(data.Company, "ERPASMORDER").Equals("T")) { SetConnectMngr(data.Company); data.Comment += "\n\n" + ErpFactory.Documents().CancelKitAssemblyOrderBasedOnSalesDocument(data); } */ data.DocStatus = cancelled; Factory.DaoDocument().Update(data); //Pasa las lineas del documento a Cancelled IList<DocumentLine> docLines = Factory.DaoDocumentLine().Select(new DocumentLine { Document = data }); foreach (DocumentLine dl in docLines) { dl.LineStatus = cancelled; Factory.DaoDocumentLine().Update(dl); } //update NodeTrace NodeTrace qNodeTrace = new NodeTrace { PostingDocument = data }; //Busca todo los registros de ese documento y los reversa IList<NodeTrace> nodeTraceList = Factory.DaoNodeTrace().Select(qNodeTrace); Node voidNode = WType.GetNode(new Node { NodeID = NodeType.Voided }); Label curLabel; foreach (NodeTrace trace in nodeTraceList) { //Crear un trace que tenga la transaccion del posting eliminado en el nodo void //Registra el movimiento del nodo if (trace.Node.NodeID == NodeType.Released) { trace.Node = voidNode; trace.Status = inactive; trace.ModDate = DateTime.Now; trace.ModifiedBy = data.ModifiedBy; trace.Comment = "Released: " + trace.PostingDocument.DocNumber + " Reversed"; Factory.DaoNodeTrace().Update(trace); SaveNodeTrace( new NodeTrace { Node = storeNode, Document = trace.Document, Label = trace.Label, Quantity = trace.Quantity, IsDebit = trace.IsDebit, CreatedBy = trace.CreatedBy, //PostingDocument = trace.PostingDocument, //PostingUserName = trace.PostingUserName, Status = active, Comment = "Stock: " + trace.PostingDocument.DocNumber + " Reversed", CreationDate= DateTime.Now, //ModifiedBy = data.ModifiedBy, //PostingDate = trace.PostingDate, }); } //Reversa el trace original para poderlo postear nuevamente o reversarlo a stored if (trace.Node.NodeID == NodeType.Picked) { //trace.DocumentLine = null; //trace.PostingDate = null; //trace.PostingDocument = null; //trace.PostingUserName = null; trace.ModifiedBy = data.ModifiedBy; trace.ModDate = DateTime.Now; trace.Node = voidNode; trace.Comment = "Picked: " + trace.PostingDocument.DocNumber + " Reversed"; Factory.DaoNodeTrace().Update(trace); } //Recorre los Packages de ese shipment y reversa los labels HIjos //Poner en Void los package Labels de ese documento. IList<DocumentPackage> packList = Factory.DaoDocumentPackage().Select(new DocumentPackage { PostingDocument = data }); IList<Label> labelList; foreach (DocumentPackage curPack in packList) { labelList = Factory.DaoLabel().Select(new Label { FatherLabel = curPack.PackLabel }); foreach (Label lbl in labelList) { //Reverse labels to node trace stored lbl.Bin = binRestore; lbl.Node = storeNode; lbl.ModDate = DateTime.Now; lbl.ModifiedBy = data.ModifiedBy; lbl.Status = active; lbl.ShippingDocument = null; lbl.FatherLabel = null; Factory.DaoLabel().Update(lbl); //Reversando los Hijos en caso de que ese label tenga Hijos try { lbl.ChildLabels = Factory.DaoLabel().Select(new Label { FatherLabel = lbl }); if (lbl.ChildLabels != null && lbl.ChildLabels.Count > 0) foreach (Label child in lbl.ChildLabels) { child.Bin = binRestore; child.Node = storeNode; child.ModDate = DateTime.Now; child.ModifiedBy = data.ModifiedBy; child.Status = active; child.ShippingDocument = null; Factory.DaoLabel().Update(child); } } catch { } } curPack.PackLabel.Status = inactive; curPack.PackLabel.Node = voidNode; Factory.DaoLabel().Update(curPack.PackLabel); } } #region Restoring QtyShipped - JM Ene21/2010 //reversando el ShippedQty to the Original Order Qher is a MergedOrder try { Document mergedDoc = Factory.DaoDocument().Select(new Document { DocNumber = data.CustPONumber, Company = data.Company }).First(); mergedDoc.PostingDocument = ""; mergedDoc.Priority = 0; Factory.DaoDocument().Update(mergedDoc); if (mergedDoc.DocType.DocTypeID == SDocType.MergedSalesOrder) { DocumentLine mergedLine; DocumentLine oriLine; //1. Toma las lineas del Shipped foreach (DocumentLine shipLine in docLines) { try { //2. Busca las lineas del merged y luego la original mergedLine = Factory.DaoDocumentLine().Select(new DocumentLine { Document = new Document { DocNumber = shipLine.LinkDocNumber, Company = data.Company }, LineNumber = shipLine.LinkDocLineNumber }).First(); //2. Busca las lineas del merged original oriLine = Factory.DaoDocumentLine().Select(new DocumentLine { Document = new Document { DocNumber = mergedLine.LinkDocNumber, Company = data.Company }, LineNumber = mergedLine.LinkDocLineNumber }).First(); //3. Actualiza el QtyShipped. oriLine.QtyShipped -= shipLine.Quantity; oriLine.ModDate = DateTime.Now; oriLine.QtyBackOrder = 0; oriLine.QtyAllocated = 0; oriLine.QtyCancel = 0; // Factory.DaoDocumentLine().Update(oriLine); } catch (Exception ex) { ExceptionMngr.WriteEvent("Updating ShipQty:" + data.DocNumber + ", Line:" + shipLine.LineNumber, ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Business); continue; } } } } catch (Exception ex) { ExceptionMngr.WriteEvent("Updating ShipQty:" + data.DocNumber, ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Business); } #endregion Factory.Commit(); } catch (Exception ex) { Factory.Rollback(); ExceptionMngr.WriteEvent("ReverseSalesShipment #" + data.DocNumber, ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Persistence); throw; } }
//Permite reversar un documento IA que fue posteado en el ERP, //solo se reversa si en el ERP no lo ha posteado public void ReverseInventoryAdjustment(Document data) { //if (data.Company.ErpConnection == null) // throw new Exception("Please setup Erp Connection."); Factory.IsTransactional = true; //SetConnectMngr(data.Company); Node storedNode = new Node { NodeID = NodeType.Stored }; Node voidNode = WType.GetNode(new Node { NodeID = NodeType.Voided }); try { //Update document status to Cancelled Status cancelled = WType.GetStatus(new Status { StatusID = DocStatus.Cancelled }); Status inactive = WType.GetStatus(new Status { StatusID = EntityStatus.Inactive }); Status active = WType.GetStatus(new Status { StatusID = EntityStatus.Active }); data.DocStatus = cancelled; Factory.DaoDocument().Update(data); //Pasa las lineas del documento a Cancelled IList<DocumentLine> docLines = Factory.DaoDocumentLine().Select(new DocumentLine { Document = data }); foreach (DocumentLine dl in docLines) { dl.LineStatus = cancelled; Factory.DaoDocumentLine().Update(dl); } //update NodeTrace NodeTrace qNodeTrace = new NodeTrace { PostingDocument = data }; //Busca todo los registros de ese documento y los reversa IList<NodeTrace> nodeTraceList = Factory.DaoNodeTrace().Select(qNodeTrace); Label curLabel; foreach (NodeTrace trace in nodeTraceList) { //Reverse labels que se generaron con el ajuste, si son negativos //Pasan de nuevo a stored, si son positivos pasan a void. curLabel = trace.Label; curLabel.Node = (trace.IsDebit == true) ? storedNode : voidNode; curLabel.CurrQty = (trace.IsDebit == true) ? curLabel.CurrQty : 0; curLabel.Status = (trace.IsDebit == true) ? active : inactive; curLabel.ModDate = DateTime.Now; curLabel.ModifiedBy = data.ModifiedBy; Factory.DaoLabel().Update(curLabel); //Crear un trace que tenga la transaccion del posting eliminado en el nodo void //Registra el movimiento del nodo SaveNodeTrace( new NodeTrace { Node = (trace.IsDebit == true) ? storedNode : voidNode, Document = trace.Document, Label = trace.Label, Quantity = trace.Quantity, IsDebit = !trace.IsDebit, CreatedBy = trace.CreatedBy, PostingDocument = trace.PostingDocument, PostingUserName = trace.PostingUserName, Status = active, // inactive, Comment = trace.PostingDocument.DocNumber + " Reversed", ModDate = DateTime.Now, ModifiedBy = data.ModifiedBy, PostingDate = trace.PostingDate, }); //Factory.DaoNodeTrace().Delete(trace); } Factory.Commit(); } catch (Exception ex) { Factory.Rollback(); ExceptionMngr.WriteEvent("ReverseInventoryAdjustment #" + data.DocNumber, ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Persistence); throw; //return; } }
//Cuando las lineas deben hacer link con un documento del ERP, solo se permite que el Uom Coincida //Con el del documento private Object[] SalesLinesForErpDocument(Document shipTask, Document ssDocument) { Object[] result = new Object[2]; try { Node releaseNode = new Node { NodeID = NodeType.Released }; Node pickNode = new Node { NodeID = NodeType.Picked }; DocumentBalance docBal = new DocumentBalance { Document = shipTask, Node = releaseNode }; //Obtiene el balance linea por linea, Es decir el cruce contra lo ya Released, porque la linea se //asigna una vez se postea, lo que no tiene linea no aparece en el balance //es decir el saldo que queda por llenar de cada linea de documento IList<DocumentBalance> balanceList = Factory.DaoDocumentBalance().DetailedBalance(docBal, shipTask.CrossDocking == true ? true : false); balanceList = balanceList.OrderBy(f => f.DocumentLine.LineNumber).ToList(); //Ordernada por LineNumber Console.WriteLine("Balance List"); //Armar las lineas del documento de Shipment IList<DocumentLine> ssDocLines = new List<DocumentLine>(); //NodeTrace qNodeTrace; DocumentLine ssLine; int line = 1; IEnumerable<NodeTrace> nodeTraceSameUnit; IList<NodeTrace> allNodeTrace = new List<NodeTrace>(); Dictionary<long, double> acumLines = new Dictionary<long, double>(); Status lineStatus = WType.GetStatus(new Status { StatusID = DocStatus.New }); //Obtienen los saldos pendientes de lo que se piqueo para ese documento. nodeTraceSameUnit = nodeTraceSameUnit = Factory.DaoNodeTrace().Select( new NodeTrace { Document = shipTask, Node = pickNode, PostingDocument = new Document { DocID = 0 }, //0 mean Null //Label = new Label { Product = balance.Product, Unit = balance.Unit } }).Where(f => f.Quantity > 0); //Recorre los NodeTrace en Picking que tengan saldo y tengan balance. double traceBalance; double shipLineQty; int xLine = 0; Console.WriteLine("Before Foreach"); foreach (NodeTrace curTrace in nodeTraceSameUnit.Where(f => f.Label.Product != null).OrderBy(f => f.Label.Product.ProductID)) { traceBalance = curTrace.Quantity * curTrace.Unit.BaseAmount; //Aqui en shipping el despacho es en EA asi que se deben procescar todas las lineas del nodetrace //En EA foreach (DocumentBalance curline in balanceList .Where(f => f.Product.ProductID == curTrace.Label.Product.ProductID //&& (f.Unit.UnitID == curTrace.Label.Unit.UnitID || f.Unit.BaseAmount == curTrace.Label.Unit.BaseAmount) && f.QtyPending > 0)) { //Para el consecutivo de la linea if (!acumLines.ContainsKey(curline.DocumentLine.LineID)) xLine++; //Si el valor de la cantidad del label actual es mayor o igual a la pendiente. if (traceBalance >= curline.BaseQtyPending) { traceBalance -= curline.BaseQtyPending; shipLineQty = curline.BaseQtyPending; curline.QtyPending = 0; } else //Si es menor { curline.QtyPending -= traceBalance/curline.Unit.BaseAmount; //nodeTraceSameUnit.Sum(f => f.Quantity); shipLineQty = traceBalance; // nodeTraceSameUnit.Sum(f => f.Quantity); traceBalance = 0; } //Creado los nuevos traces en el RELEASE. curTrace.DocumentLine = curline.DocumentLine; curTrace.PostingDate = DateTime.Now; curTrace.PostingDocument = ssDocument; curTrace.PostingDocLineNumber = xLine; curTrace.PostingUserName = ssDocument.CreatedBy; curTrace.ModifiedBy = ssDocument.CreatedBy; curTrace.ModDate = DateTime.Now; //Update Anterior. Factory.DaoNodeTrace().Update(curTrace); //Nuevo node para el caso de Shipping. if (shipLineQty > 0) allNodeTrace.Add( new NodeTrace { Node = curTrace.Node, Document = curTrace.Document, Label = curTrace.Label, Quantity = shipLineQty, IsDebit = curTrace.IsDebit, CreatedBy = curTrace.CreatedBy, PostingDocument = curTrace.PostingDocument, PostingDocLineNumber = xLine, PostingUserName = ssDocument.CreatedBy, Bin = curTrace.Bin, CreationDate = DateTime.Now, PostingDate = DateTime.Now, Status = curTrace.Status, Unit = curline.Product.BaseUnit, FatherLabel = curTrace.Label.FatherLabel }); //Crea el acumulador para cada linea. if (acumLines.ContainsKey(curline.DocumentLine.LineID)) acumLines[curline.DocumentLine.LineID] += shipLineQty; else acumLines.Add(curline.DocumentLine.LineID, shipLineQty); } if (traceBalance <= 0) continue; else //Reportar que hubo overshipment. { ExceptionMngr.WriteEvent("SalesLinesForErpDocument: Overshipment: " + curTrace.Document.DocNumber + ", Product: " + curTrace.Label.Product.Name, ListValues.EventType.Warn, null, null, ListValues.ErrorCategory.Business); } } //Para todos los saldos de las lineas. //Crea las lineas respectivas. DocumentLine oriLine; foreach (long lineID in acumLines.Keys) { oriLine = balanceList.Where(f => f.DocumentLine.LineID == lineID).Select(f => f.DocumentLine).First(); //Crea una linea para el documento de fullfilment ssLine = new DocumentLine { Product = oriLine.Product, Quantity = acumLines[lineID] / oriLine.Unit.BaseAmount, //acumLines[lineID], //nodeTraceSameUnit.Sum(f => f.Quantity), Unit = oriLine.Unit, Document = ssDocument, CreationDate = DateTime.Now, IsDebit = false, LineNumber = line, LineStatus = lineStatus, Location = ssDocument.Location, UnitBaseFactor = oriLine.Unit.BaseAmount, LinkDocNumber = oriLine.Document.DocNumber, LinkDocLineNumber = oriLine.LineNumber, CreatedBy = ssDocument.CreatedBy, Note = oriLine.Note, //If Note=2 indica que es un componente Sequence = oriLine.Sequence, Date1 = DateTime.Now, UnitPrice = oriLine.UnitPrice, ExtendedPrice = oriLine.UnitPrice * acumLines[lineID] * oriLine.Unit.BaseAmount, UnitCost = oriLine.UnitCost, ExtendedCost = oriLine.UnitCost * acumLines[lineID] * oriLine.Unit.BaseAmount }; ssDocLines.Add(ssLine); line++; } result[0] = ssDocLines; result[1] = allNodeTrace; return result; } catch (Exception ex) { //Factory.Rollback(); ExceptionMngr.WriteEvent("SalesLinesForErpDocument", ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Business); //throw; return null; } //Recorre los saldos pendientes para ese documento /* double curQty = 0; foreach (DocumentBalance balance in balanceList.Where(b => b.QtyPending > 0)) { qNodeTrace = new NodeTrace { Document = shipTask, Node = pickNode, PostingDocument = new Document { DocID = 0 }, //0 mean Null Label = new Label { Product = balance.Product, Unit = balance.Unit } }; //PASO 1 : Primero buscar los nodetrace que coincidan con la unidad necesitada y traer los pendientes nodeTraceSameUnit = Factory.DaoNodeTrace().Select(qNodeTrace).ToList(); //.Take(int.Parse(balance.QtyPending.ToString())) //Si se obtienen registros //if (nodeTraceSameUnit.Count > 0) if (nodeTraceSameUnit.Sum(f => f.Quantity) > 0) { //1.1 Actualiza los que encontro foreach (NodeTrace traceSame in nodeTraceSameUnit) { traceSame.DocumentLine = balance.DocumentLine; traceSame.PostingDate = DateTime.Now; traceSame.PostingDocument = ssDocument; traceSame.PostingDocLineNumber = line; traceSame.PostingUserName = ssDocument.CreatedBy; traceSame.ModifiedBy = ssDocument.CreatedBy; traceSame.ModDate = DateTime.Now; allNodeTrace.Add(traceSame); } //1.2 Disminuye el balance //Ajuste para que trabaje bien cuando hay items repetidos en una misma orden if (nodeTraceSameUnit.Sum(f => f.Quantity) <= balance.QtyPending) { balance.QtyPending -= nodeTraceSameUnit.Sum(f => f.Quantity); curQty = nodeTraceSameUnit.Sum(f => f.Quantity); } else { curQty = balance.QtyPending; balance.QtyPending = 0; } //Crea una linea para el documento de fullfilment ssLine = new DocumentLine { Product = balance.Product, Quantity = curQty, //nodeTraceSameUnit.Sum(f => f.Quantity), Unit = balance.Unit, Document = ssDocument, CreationDate = DateTime.Now, IsDebit = false, LineNumber = line, LineStatus = lineStatus, Location = ssDocument.Location, UnitBaseFactor = balance.Unit.BaseAmount, LinkDocNumber = balance.Document.DocNumber, LinkDocLineNumber = balance.DocumentLine.LineNumber, CreatedBy = ssDocument.CreatedBy, Note = balance.DocumentLine.Note, //If Note=2 indica que es un componente Sequence = balance.DocumentLine.Sequence, Date1 = DateTime.Now, UnitPrice = balance.UnitPrice, ExtendedPrice = balance.UnitPrice * curQty * balance.Unit.BaseAmount }; ssDocLines.Add(ssLine); line++; } //1.4 Si encontro todos los que necesitaba se sale a la siguiente linea if (balance.QtyPending <= 0) continue; } result[0] = ssDocLines; result[1] = allNodeTrace; return result; } catch (Exception ex) { //Factory.Rollback(); ExceptionMngr.WriteEvent("SalesLinesForErpDocument", ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Business); //throw; return null; } * */ }
//Cuando las lineas no requieren de hacer link con un Documento en el ERP private Object[] SalesLinesForTask(Document shipTask, Document ssDocument) { Object[] result = new Object[2]; try { //Node releaseNode = new Node { NodeID = NodeType.Released }; Node pickNode = new Node { NodeID = NodeType.Picked }; //Armar las lineas del documento de Recibo IList<DocumentLine> ssDocLines = new List<DocumentLine>(); //Obtiene los nodetrace records a recorrer, //los que no han sido posteados para esa tarea de recibo NodeTrace qNodeTrace = new NodeTrace { Document = shipTask, PostingDocument = new Document { DocID = 0 }, Node = pickNode }; IList<NodeTrace> nodeTraceList = Factory.DaoNodeTrace().Select(qNodeTrace); Status status = WType.GetStatus(new Status { StatusID = DocStatus.New }); DocumentLine ssLine; Double line = 0; //Leva el conteo del acumulado a recibir IDictionary<UnitProductRelation, Double[]> shipmentBalance = new Dictionary<UnitProductRelation, Double[]>(); UnitProductRelation curUnitProduct; //Consolidar las lineas de la misma unidad y hacer una sola linea foreach (NodeTrace nodeTrace in nodeTraceList) { if (nodeTrace.Label.Product == null) continue; //Armando el consolidado curUnitProduct = Factory.DaoUnitProductRelation().Select( new UnitProductRelation { Unit = nodeTrace.Label.Unit, Product = nodeTrace.Label.Product }).First(); if (shipmentBalance.ContainsKey(curUnitProduct)) shipmentBalance[curUnitProduct][1] += nodeTrace.Quantity; else { line += 1; shipmentBalance.Add(curUnitProduct, new Double[2] { line, nodeTrace.Quantity }); } //Update Node Trace nodeTrace.Document = shipTask; nodeTrace.PostingDate = DateTime.Now; nodeTrace.PostingDocument = ssDocument; nodeTrace.PostingDocLineNumber = (Int32)line; nodeTrace.PostingUserName = ssDocument.CreatedBy; nodeTrace.ModifiedBy = ssDocument.CreatedBy; nodeTrace.ModDate = DateTime.Now; Factory.DaoNodeTrace().Update(nodeTrace); } //Recorre la coleccion de balance para adicionar las demas lineas del recibo foreach (UnitProductRelation unitProductRel in shipmentBalance.Keys) { //Si hay cantidad (elemento 1) if (shipmentBalance[unitProductRel][1] > 0) { //Crea una linea para el documento de recibo obteniedo la info del balance ssLine = new DocumentLine { Product = unitProductRel.Product, Quantity = shipmentBalance[unitProductRel][1], Unit = unitProductRel.Unit, Document = ssDocument, CreationDate = DateTime.Now, IsDebit = false, LineNumber = (Int32)shipmentBalance[unitProductRel][0], LineStatus = status, Location = ssDocument.Location, UnitBaseFactor = unitProductRel.Unit.BaseAmount, CreatedBy = ssDocument.CreatedBy, Date1 = DateTime.Now }; ssDocLines.Add(ssLine); } } result[0] = ssDocLines; result[1] = nodeTraceList; return result; } catch (Exception ex) { //Factory.Rollback(); ExceptionMngr.WriteEvent("SalesLinesForTask", ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Business); //throw; return null; } }
//Actualiza el nodetrace y crea los Nuevos Registros de trace private void ProcessShippingTransactionTrace(IList<NodeTrace> traceList, Document postedDocument, Document taskDocument, Node node) { if (traceList == null) return; Label curLabel; foreach (NodeTrace nodeTrace in traceList) { //Actualiza el trace actual //Factory.DaoNodeTrace().Update(nodeTrace); //Pasa los labels de ese nodeTrace a Storedb //Registra el movimiento del nodo SaveNodeTrace( new NodeTrace { Node = node, Document = taskDocument, Label = nodeTrace.Label, Quantity = nodeTrace.Quantity, //GetLabelStockQty(new Label { LabelID = nodeTrace.Label.LabelID }), //nodeTrace.Label.CurrQty IsDebit = nodeTrace.IsDebit, CreatedBy = postedDocument.CreatedBy, PostingDocument = postedDocument, PostingDocLineNumber = nodeTrace.PostingDocLineNumber, PostingUserName = postedDocument.CreatedBy }); //Factory.Commit(); //Pasa los labels de ese nodeTrace a Stored o Node defined. curLabel = nodeTrace.Label; curLabel.Node = node; curLabel.ModDate = DateTime.Now; curLabel.ModifiedBy = postedDocument.CreatedBy; Factory.DaoLabel().Update(curLabel); //Modificando las hijas try { curLabel.ChildLabels = Factory.DaoLabel().Select(new Label { FatherLabel = curLabel }); if (curLabel.ChildLabels != null && curLabel.ChildLabels.Count > 0) foreach (Label child in curLabel.ChildLabels) { child.Node = node; child.ModDate = DateTime.Now; child.ModifiedBy = child.FatherLabel.CreatedBy; Factory.DaoLabel().Update(child); } } catch { } } #region Updating QtyShipped - JM Ene21/2010 //Adicionando el ShippedQty to the Original Order Qher is a MergedOrder if (taskDocument.DocType.DocTypeID == SDocType.MergedSalesOrder) { try { //DocumentLine mergedLine; DocumentLine oriLine; //ProductInventory prInventory; //1. Toma las lineas del Shipped foreach (DocumentLine shipLine in postedDocument.DocumentLines) { try { //2. Busca las lineas del merged y luego la original /* mergedLine = Factory.DaoDocumentLine().Select(new DocumentLine { Document = new Document { DocNumber = shipLine.LinkDocNumber, Company = postedDocument.Company }, LineNumber = shipLine.LinkDocLineNumber }).First(); */ //mergedLine = taskDocument.DocumentLines.Where(f => f.LineNumber == shipLine.LinkDocLineNumber).First(); //2. Busca las lineas del merged original oriLine = Factory.DaoDocumentLine().Select(new DocumentLine { Document = new Document { DocNumber = taskDocument.DocumentLines.Where(f => f.LineNumber == shipLine.LinkDocLineNumber) .First().LinkDocNumber, Company = postedDocument.Company }, LineNumber = taskDocument.DocumentLines.Where(f => f.LineNumber == shipLine.LinkDocLineNumber) .First().LinkDocLineNumber }).First(); //3. Actualiza el QtyShipped. oriLine.QtyShipped += shipLine.Quantity; oriLine.ModDate = DateTime.Now; oriLine.ModifiedBy = postedDocument.CreatedBy; if (oriLine.QtyBackOrder > 0) oriLine.LineStatus = new Status { StatusID = DocStatus.InProcess }; if (oriLine.Quantity - oriLine.QtyShipped < 0) oriLine.LineStatus = new Status { StatusID = DocStatus.Completed }; Factory.DaoDocumentLine().Update(oriLine); //4. Actualiza el QtyShipped En el Merged. /* try { taskDocument.DocumentLines.Where(f => f.LineNumber == shipLine.LinkDocLineNumber).First().QtyShipped += shipLine.Quantity; taskDocument.DocumentLines.Where(f => f.LineNumber == shipLine.LinkDocLineNumber).First().ModDate = DateTime.Now; taskDocument.DocumentLines.Where(f => f.LineNumber == shipLine.LinkDocLineNumber).First().ModifiedBy = postedDocument.CreatedBy; Factory.DaoDocumentLine().Update(taskDocument.DocumentLines.Where(f => f.LineNumber == shipLine.LinkDocLineNumber).First()); mergedLine.QtyShipped += shipLine.Quantity; mergedLine.ModDate = DateTime.Now; mergedLine.ModifiedBy = postedDocument.CreatedBy; Factory.DaoDocumentLine().Update(mergedLine); } catch { } **/ //Borrar esa cantidad de lo allocated para ese documento y ese producto. /* try { prInventory = Factory.DaoProductInventory().Select( new ProductInventory { Document = oriLine.Document, Product = oriLine.Product }).First(); if (prInventory.QtyAllocated - shipLine.Quantity <= 0 && prInventory.QtyInUse == 0) Factory.DaoProductInventory().Delete(prInventory); else { prInventory.QtyAllocated -= shipLine.Quantity; if (prInventory.QtyAllocated < 0) prInventory.QtyAllocated = 0; Factory.DaoProductInventory().Update(prInventory); } } catch { } */ } catch (Exception ex) { ExceptionMngr.WriteEvent("Updating ShipQty:" + postedDocument.DocNumber + ", Line:" + shipLine.LineNumber, ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Business); continue; } } } catch (Exception ex) { ExceptionMngr.WriteEvent("Updating ShipQty:" + postedDocument.DocNumber, ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Business); } } #endregion }
public void PickAtOnce(Document document, Label sourceLocation, Node node, SysUser picker) { Factory.IsTransactional = true; //Node node = WType.GetNode(new Node { NodeID = NodeType.Picked }); DocumentBalance docBal = new DocumentBalance { Document = document, Node = node }; IList<DocumentBalance> balanceList = Factory.DaoDocumentBalance().BalanceByUnit(docBal); //Recorre las lineas del documento y las pickea usando PickProduct, pero solo si el balance //existe en la location indicada para todo lo pendiente. if (balanceList == null || balanceList.Count == 0) throw new Exception("Document " + document.DocNumber + " not contains product pending to pick."); DocumentLine curLine; string fullExistence = ""; foreach (DocumentBalance line in balanceList.Where(f=>f.QtyPending > 0)) { //Define Document, Product, Unit and Qty to send to receiving transaction curLine = new DocumentLine { Document = document, Product = line.Product, Unit = line.Unit, Quantity = line.QtyPending, CreatedBy = picker.UserName }; fullExistence += CheckForStockInLocation(curLine, sourceLocation); } //Si alguno no tiene existencia no puede ejecutar el PickAtOnce if (!string.IsNullOrEmpty(fullExistence)) { ExceptionMngr.WriteEvent("PickAtOnce:", ListValues.EventType.Error, null, null, ListValues.ErrorCategory.Business); throw new Exception(fullExistence); } //Ejecutando el Picking despues de que se confirma la existencia foreach (DocumentBalance line in balanceList) { //Define Document, Product, Unit and Qty to send to receiving transaction curLine = new DocumentLine { Document = document, Product = line.Product, Unit = line.Unit, Quantity = line.QtyPending }; Label packageLabel = new Label { LabelID = -1 }; PickProduct(curLine, sourceLocation, node, packageLabel, picker, null); } }
public Node Save(Node data) { return (Node)base.Save(data); }
/// <summary> /// Piquea un producto a una orden teneindo en cuanta las tracking options. /// </summary> /// <param name="label"></param> /// <param name="qtyToPick"></param> /// <param name="node"></param> /// <param name="picker"></param> public Label PickProductWithTrack(Document document, Label label, double qtyToPick, Node destNode, SysUser picker, Label packLabel) { //Debe piquear de producto suelto, teniendo en cuanta el Track del Label. Factory.IsTransactional = true; Node storedNode = WType.GetNode(new Node { NodeID = NodeType.Stored }); Status status = WType.GetStatus(new Status { StatusID = EntityStatus.Active }); Status locked = WType.GetStatus(new Status { StatusID = EntityStatus.Locked }); //DocumentType labelType = WType.GetLabelType(new DocumentType { DocTypeID = LabelType.ProductLabel }); Bin destBin = Rules.GetBinForNode(destNode, document.Location); try { //Valida si el docuemnto no es nulo Rules.ValidateDocument(document, true); Rules.ValidateBinStatus(label.Bin, true); //Valida si el producto esta en ese documento DocumentLine docLine = new DocumentLine { Document = document, Product = label.Product, LineStatus = new Status { StatusID = DocStatus.New }, Unit = label.Unit, Quantity = qtyToPick, CreatedBy = picker.UserName }; if (document.DocType.DocTypeID != SDocType.PickTicket) { Rules.ValidateProductInDocument(docLine, true); //Valida si hay saldo pendiente por procesar Rules.ValidateBalanceQuantityInDocument(docLine, destNode, true, false); } //Evaluacion de tipo de source, Bin or Label DateTime recDate = DateTime.Now; //if (Rules.ValidateIsBinLabel(sourceLocation, false)) //{ IList<Label> tranLabel = DecreaseQtyFromBin(label, docLine, "Picking Source Track", true, storedNode); try { recDate = (DateTime)tranLabel.Where(f => f.ReceivingDate != null).OrderBy(f => f.ReceivingDate).First().ReceivingDate; } catch { recDate = DateTime.Now; } //} // //SI el ajustes es sobre un Label //else if (Rules.ValidateIsProductLabel(sourceLocation, false)) //{ // DecreaseQtyFromLabel(sourceLocation, line, "Picking Source", true, storedNode); // try { recDate = (sourceLocation.ReceivingDate == null) ? DateTime.Now : (DateTime)sourceLocation.ReceivingDate; } // catch { recDate = DateTime.Now; } //} //Creando el package para ingresar la mercancia. if (packLabel == null) packLabel = new Label { LabelID = -1 }; document.Location = label.Bin.Location; //Revalidando que el location sea correcto try { packLabel = GetPackageLabel(packLabel, document, picker).PackLabel; } catch (Exception ex) { Factory.Rollback(); throw new Exception("Package label could not be created.\n" + ex.Message); } //Increasing the Record of Product on Dest Bin. //Oct 09 /2009 Se adiciona el track option. Label pickedLabel = IncreaseQtyIntoBin(docLine, destNode, destBin, "Picking Dest Track", true, recDate, label.TrackOptions, label); pickedLabel.FatherLabel = packLabel; pickedLabel.Status = locked; pickedLabel.ShippingDocument = document; Factory.DaoLabel().Update(pickedLabel); Factory.Commit(); return pickedLabel; } catch (Exception ex) { Factory.Rollback(); ExceptionMngr.WriteEvent("PickProductWithTrack:", ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Business); throw new Exception(WriteLog.GetTechMessage(ex)); } }
public Boolean Update(Node data) { return base.Update(data); }
/// <summary> /// Get Print file string to print /// </summary> /// <param name="labels">List of labels to print</param> /// <param name="template">Template to use for the printing</param> /// <returns></returns> public String ProcessPrintingLine(DocumentBalance printLine, LabelTemplate template, String printLot, Node node, Bin bin, UserByRol userByRol) { string result = ""; Status status = WType.GetStatus(new Status { StatusID = EntityStatus.Active }); //Active //Obteniendo el listado de TAGS que se deben reemplazar en el template IList<LabelMapping> labelmappings = Factory.DaoLabelMapping().Select( new LabelMapping { LabelType = template.LabelType }); //Template base //int i; IList<Label> labelList = new List<Label>(); //Tipo De impresion //1. Normal Imprime standar, sin logistica //2. Logistic (Notes tiene data) - imprime normal mas la Logistica Unit logisticUnit = null; if (printLine.Notes != null && printLine.Notes.Contains("Logistic")) { string[] dataLogistic = printLine.Notes.Split(':'); //El primer elemento contiene la unidad logistica. logisticUnit = Factory.DaoUnit().SelectById(new Unit { UnitID = int.Parse(dataLogistic[1]) }); //3. Only print Logistic (notes tiene "ONLYPACK") - no imprime la normal (si las crea), solo imprime las logisticas //if (printLine.Notes.Contains("ONLYPACK")) //printOnlyLogistic = true; } //CReating Document Line to Send DocumentLine prnLine = new DocumentLine { Product = printLine.Product, Document = printLine.Document, Unit = printLine.Unit, Quantity = printLine.Quantity }; //Crea las etiquetas de la cantidad de producto a recibir Logisticas y sus Hijas double logisticFactor = (logisticUnit != null) ? (double)(logisticUnit.BaseAmount / printLine.Unit.BaseAmount) : 1; labelList = CreateProductLabels(logisticUnit, prnLine, node, bin, logisticFactor, printLot,"", DateTime.Now) .Where(f=>f.FatherLabel == null).ToList(); //Reemplazando el Header if (template.Header != null) result += ReplaceTemplate(labelmappings, template.Header, labelList[0]) + Environment.NewLine; //Reemplazando el Body if (template.Body != null) { foreach (Label label in labelList) result += ReplaceTemplate(labelmappings, template.Body, label) + Environment.NewLine; } return result; }
public Boolean Delete(Node data) { return base.Delete(data); }
private void UpdateStock(ProductStock ps, Node storedNode, string comment) { if (!string.IsNullOrEmpty(ps.Bin.BinCode)) { try { ps.Bin = Factory.DaoBin().Select(ps.Bin).First(); } catch (Exception ex) { //El bin no Existe //Console.WriteLine(ps.Product.ProductCode + " => " + ps.Bin.BinCode); Console.WriteLine(ex.Message); //Console.ReadKey(); Status active = Factory.DaoStatus().Select(new Status { StatusID = EntityStatus.Active }).First(); ps.Bin.CreatedBy = WmsSetupValues.SystemUser; ps.Bin.CreationDate = DateTime.Now; ps.Bin.IsFromErp = true; ps.Bin.Status = active; ps.Bin.Rank = 0; Console.WriteLine("Creating Bin: " + ps.Bin.BinCode); ps.Bin = Factory.DaoBin().Save(ps.Bin); } } else ps.Bin = WType.GetBin(new Bin { BinCode = DefaultBin.MAIN, Location = ps.Bin.Location }); //Procesando el Stock. DocumentLine line = new DocumentLine { Product = ps.Product, Quantity = ps.Stock, Unit = ps.Product.BaseUnit, CreatedBy = WmsSetupValues.SystemUser }; (new TransactionMngr()).IncreaseQtyIntoBin(line, storedNode, ps.Bin, comment, true, DateTime.Now, null, null); }
public Node SelectById(Node data) { return (Node)base.SelectById(data); }
public Boolean ValidateNodeInLabel(Label label, Node node, Boolean autoThrow) { if (label.Node.NodeID != node.NodeID) { if (autoThrow) { Factory.Rollback(); throw new Exception("Label " + label.LabelCode + " is not in a valid Node."); } else return false; } return true; }
private void ReversePickedProduct(Document data) { //Node releaseNode = new Node { NodeID = NodeType.Released }; Node storeNode = new Node { NodeID = NodeType.Stored }; Bin binRestore = WType.GetBin(new Bin {BinCode = DefaultBin.MAIN, Location = data.Location}); //Update document status to Cancelled Status cancelled = WType.GetStatus(new Status { StatusID = DocStatus.Cancelled }); Status inactive = WType.GetStatus(new Status { StatusID = EntityStatus.Inactive }); Status active = WType.GetStatus(new Status { StatusID = EntityStatus.Active }); //update NodeTrace NodeTrace qNodeTrace = new NodeTrace { Document = data }; //Busca todo los registros de ese documento y los reversa IList<NodeTrace> nodeTraceList = Factory.DaoNodeTrace().Select(qNodeTrace); Node voidNode = WType.GetNode(new Node { NodeID = NodeType.Voided }); //Label curLabel; foreach (NodeTrace trace in nodeTraceList) { //Reversa el trace original para poderlo postear nuevamente o reversarlo a stored if (trace.Node.NodeID == NodeType.Picked) { trace.ModifiedBy = data.ModifiedBy; trace.ModDate = DateTime.Now; trace.Node = voidNode; trace.Comment = "Picked: " + trace.Document.DocNumber + " Reversed"; Factory.DaoNodeTrace().Update(trace); // CAA // Vuelve a Stock node SaveNodeTrace( new NodeTrace { Node = storeNode, Document = trace.Document, Label = trace.Label, Quantity = trace.Quantity, IsDebit = trace.IsDebit, CreatedBy = trace.CreatedBy, Status = active, Comment = "Stock: " + trace.Document.DocNumber + " Reversed", CreationDate = DateTime.Now }); } //Recorre los Packages de ese document y reversa los labels HIjos //Poner en Void los package Labels de ese documento. IList<DocumentPackage> packList = Factory.DaoDocumentPackage().Select(new DocumentPackage { Document = data }); IList<Label> labelList; foreach (DocumentPackage curPack in packList) { labelList = Factory.DaoLabel().Select(new Label { FatherLabel = curPack.PackLabel }); foreach (Label lbl in labelList) { //Reverse labels to node trace stored lbl.Bin = binRestore; lbl.Node = storeNode; lbl.ModDate = DateTime.Now; lbl.ModifiedBy = data.ModifiedBy; lbl.Status = active; lbl.ShippingDocument = null; lbl.FatherLabel = null; Factory.DaoLabel().Update(lbl); //Reversando los Hijos en caso de que ese label tenga Hijos try { lbl.ChildLabels = Factory.DaoLabel().Select(new Label { FatherLabel = lbl }); if (lbl.ChildLabels != null && lbl.ChildLabels.Count > 0) foreach (Label child in lbl.ChildLabels) { child.Bin = binRestore; child.Node = storeNode; child.ModDate = DateTime.Now; child.ModifiedBy = data.ModifiedBy; child.Status = active; child.ShippingDocument = null; Factory.DaoLabel().Update(child); } } catch { } } curPack.PackLabel.Status = inactive; curPack.PackLabel.Node = voidNode; Factory.DaoLabel().Update(curPack.PackLabel); } } }
public Bin GetBinForNode(Node node, Location location) { switch (node.NodeID) { case NodeType.Picked: return Factory.DaoBin().Select(new Bin { Location = location, BinCode = DefaultBin.PICKING }).First(); case NodeType.Process: return Factory.DaoBin().Select(new Bin { Location = location, BinCode = DefaultBin.PROCESS }).First(); default: return Factory.DaoBin().Select(new Bin { Location = location, BinCode = DefaultBin.MAIN }).First(); } }
/// <summary> /// Recolecta= producto, sin etiqueta (recibo manual) toma de los labels virtuales para cada unidad basica de producto /// </summary> /// <param name="line"></param> /// <param name="sourceLocation"></param> /// <param name="node"></param> /// <param name="packageLabel"></param> /// <param name="picker"></param> public void PickProduct(DocumentLine line, Label sourceLocation, Node destNode, Label packageLabel, SysUser picker, Bin destBin) { Factory.IsTransactional = true; Node storedNode = WType.GetNode(new Node { NodeID = NodeType.Stored }); Status status = WType.GetStatus(new Status { StatusID = EntityStatus.Active }); Status locked = WType.GetStatus(new Status { StatusID = EntityStatus.Locked }); DocumentType labelType = WType.GetLabelType(new DocumentType { DocTypeID = LabelType.ProductLabel }); if (destBin == null) destBin = Rules.GetBinForNode(destNode, sourceLocation.Bin.Location); try { //Valida si el docuemnto no es nulo Rules.ValidateDocument(line.Document, true); Rules.ValidateBinStatus(sourceLocation.Bin, true); //Validar si las locations son iguales Rules.ValidatePickLocation(line.Document.Location, sourceLocation.Bin.Location, true); if (sourceLocation.LabelType.DocTypeID == LabelType.ProductLabel) { //Valida que este activo Rules.ValidateActiveStatus(sourceLocation.Status, true); //Validar que no este vod Rules.ValidateVoided(sourceLocation.Node, true); } if (line.Document.DocType.DocTypeID != SDocType.PickTicket) { //Valida si el producto esta en ese documento DocumentLine docLine = new DocumentLine { Document = line.Document, Product = line.Product, LineStatus = new Status { StatusID = DocStatus.New }, Unit = line.Unit, Quantity = line.Quantity, CreatedBy = picker.UserName }; Rules.ValidateProductInDocument(docLine, true); //Valida si hay saldo pendiente por procesar Rules.ValidateBalanceQuantityInDocument(docLine, destNode, true, false); } //Evaluacion de tipo de source, Bin or Label DateTime recDate = DateTime.Now; if (Rules.ValidateIsBinLabel(sourceLocation, false)) { IList<Label> tranLabel = DecreaseQtyFromBin(sourceLocation, line, "Picking Source Product", true, storedNode); try { recDate = (DateTime)tranLabel.Where(f => f.ReceivingDate != null).OrderBy(f => f.ReceivingDate).First().ReceivingDate; } catch { recDate = DateTime.Now; } } //SI el ajustes es sobre un Label else if (Rules.ValidateIsProductLabel(sourceLocation, false)) { DecreaseQtyFromLabel(sourceLocation, line, "Picking Source Product", true, storedNode, true); try { recDate = (sourceLocation.ReceivingDate == null) ? DateTime.Now : (DateTime)sourceLocation.ReceivingDate; } catch { recDate = DateTime.Now; } } //Creando el package para ingresar la mercancia. if (packageLabel != null) { line.Document.Location = sourceLocation.Bin.Location; //Revalidando que el location sea correcto try { packageLabel = GetPackageLabel(packageLabel, line.Document, picker).PackLabel; } catch (Exception ex) { Factory.Rollback(); throw new Exception("Package label could not be created.\n" + ex.Message); } } //Increasing the Record of Product on Dest Bin. Label pickedLabel = IncreaseQtyIntoBin(line, destNode, destBin, "Picking Dest Product", true, recDate, null, sourceLocation); pickedLabel.FatherLabel = packageLabel; pickedLabel.Status = locked; pickedLabel.ShippingDocument = line.Document; Factory.DaoLabel().Update(pickedLabel); Factory.Commit(); } catch (Exception ex) { Factory.Rollback(); ExceptionMngr.WriteEvent("PickProduct:", ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Business); throw new Exception(WriteLog.GetTechMessage(ex)); } }
public bool IsTrackRequiredInDocument(Document document, Node node) { return Factory.DaoDocument().IsTrackRequiredInDocument(document, node); }
//Cuando las lineas deben hacer link con un documento del ERP, solo se permite que el Uom Coincida //Con el del documento private Object[] ReceiptLinesForErpDocument(Document receivingTask, Document prDocument) { Object[] result = new Object[2]; try { Node recNode = new Node { NodeID = NodeType.Received }; Node storedNode = new Node { NodeID = NodeType.Stored }; DocumentBalance docBal = new DocumentBalance { Document = receivingTask, Node = storedNode }; //Obtiene el balance linea por linea, Es decir el cruce contra lo ya posteado, porque la linea se //asigna una vez se postea, lo que no tiene linea no aparece en el balance //es decir el saldo que queda por llenar de cada linea de documento IList<DocumentBalance> balanceList = Factory.DaoDocumentBalance().DetailedBalance(docBal, false); balanceList = balanceList.OrderBy(f => f.DocumentLine.LineNumber).ToList(); //Ordernada por LineNumber //Armar las lineas del documento de Recibo IList<DocumentLine> prDocLines = new List<DocumentLine>(); NodeTrace qNodeTrace; DocumentLine rpLine; int line = 1; IEnumerable<NodeTrace> nodeTraceSameUnit; IList<NodeTrace> allNodeTrace = new List<NodeTrace>(); Dictionary<long, double> acumLines = new Dictionary<long, double>(); Status lineStatus = WType.GetStatus(new Status { StatusID = DocStatus.New }); //Label curLabel; //Obtienen los saldos pendientes de lo que se recibio para ese documento. nodeTraceSameUnit = Factory.DaoNodeTrace().Select( new NodeTrace { Document = receivingTask, Node = recNode, PostingDocument = new Document { DocID = 0 }, //0 mean Null //Label = new Label { Product = balance.Product, Unit = balance.Unit } }).Where(f => f.Quantity > 0); //Recorre los NodeTrace en Receiving que tengan saldo y tengan balance. double traceBalance; double receivedLineQty; int xLine = 0; foreach (NodeTrace curTrace in nodeTraceSameUnit.Where(f => f.Label.Product != null).OrderBy(f => f.Label.Product.ProductID)) { traceBalance = curTrace.Quantity * curTrace.Unit.BaseAmount; //Saca todas las lineas del mismos producto que tenga la misma unidad y tengan saldo pendiente. foreach (DocumentBalance curline in balanceList .Where(f => f.Product.ProductID == curTrace.Label.Product.ProductID //&& (f.Unit.UnitID == curTrace.Label.Unit.UnitID || f.Unit.BaseAmount == curTrace.Label.Unit.BaseAmount) && f.QtyPending > 0)) { //Para el consecutivo de la linea if (!acumLines.ContainsKey(curline.DocumentLine.LineID)) xLine++; //Si el valor de la cantidad del label actual es mayor o igual a la pendiente. if (traceBalance >= curline.BaseQtyPending) //(traceBalance >= curline.QtyPending) { traceBalance -= curline.BaseQtyPending; receivedLineQty = curline.BaseQtyPending; curline.QtyPending = 0; } else //Si es menor { curline.QtyPending -= traceBalance / curline.Unit.BaseAmount; //nodeTraceSameUnit.Sum(f => f.Quantity); receivedLineQty = traceBalance; //nodeTraceSameUnit.Sum(f => f.Quantity); traceBalance = 0; } //Creado los nuevos traces en el STORED. curTrace.DocumentLine = curline.DocumentLine; curTrace.PostingDate = DateTime.Now; curTrace.PostingDocument = prDocument; curTrace.PostingDocLineNumber = line; curTrace.PostingUserName = prDocument.CreatedBy; curTrace.ModifiedBy = prDocument.CreatedBy; curTrace.ModDate = DateTime.Now; //Nuevo node para el caso de Receiving. Factory.DaoNodeTrace().Update(curTrace); //allNodeTrace.Add(curTrace); if (receivedLineQty > 0) allNodeTrace.Add(new NodeTrace { Node = curTrace.Node, Document = curTrace.Document, Label = curTrace.Label, Quantity = receivedLineQty, IsDebit = curTrace.IsDebit, CreatedBy = curTrace.CreatedBy, PostingDocument = curTrace.PostingDocument, PostingDocLineNumber = xLine, PostingUserName = prDocument.CreatedBy, Bin = curTrace.Bin, CreationDate = DateTime.Now, PostingDate = DateTime.Now, Status = curTrace.Status, Unit = curline.Product.BaseUnit, //curline.Unit, FatherLabel = curTrace.Label.FatherLabel }); //Crea el acumulador para cada linea. if (acumLines.ContainsKey(curline.DocumentLine.LineID)) acumLines[curline.DocumentLine.LineID] += receivedLineQty; else acumLines.Add(curline.DocumentLine.LineID, receivedLineQty); } if (traceBalance <= 0) continue; else //Reportar que hubo Overreceived. { ExceptionMngr.WriteEvent("ReceiptLinesForErpDocument: Overreceived: " + curTrace.Document.DocNumber + ", Product: " + curTrace.Label.Product.Name, ListValues.EventType.Warn, null, null, ListValues.ErrorCategory.Business); } } //Para todos los saldos de las lineas. //Crea las lineas respectivas. DocumentLine oriLine; foreach (long lineID in acumLines.Keys) { oriLine = balanceList.Where(f => f.DocumentLine.LineID == lineID).Select(f => f.DocumentLine).First(); //Crea una linea para el documento de fullfilment rpLine = new DocumentLine { Product = oriLine.Product, AccountItem = oriLine.AccountItem, Quantity = acumLines[lineID] / oriLine.Unit.BaseAmount, //nodeTraceSameUnit.Sum(f => f.Quantity), Unit = oriLine.Unit, Document = prDocument, CreationDate = DateTime.Now, IsDebit = false, LineNumber = line, LineStatus = lineStatus, Location = prDocument.Location, UnitBaseFactor = oriLine.Unit.BaseAmount, LinkDocNumber = oriLine.Document.DocNumber, LinkDocLineNumber = oriLine.LineNumber, CreatedBy = prDocument.CreatedBy, Note = oriLine.Note, //If Note=2 indica que es un componente Sequence = oriLine.Sequence, Date1 = DateTime.Now, //UnitPrice = oriLine.UnitPrice, //ExtendedPrice = oriLine.UnitPrice * acumLines[lineID] * oriLine.Unit.BaseAmount, UnitCost = oriLine.UnitCost, ExtendedCost = oriLine.UnitCost * acumLines[lineID] * oriLine.Unit.BaseAmount, Date2 = oriLine.Date2, //Pone las fechas en el recibo, siver para las fechas de entrega Date2 en ENTERPRISE QtyOnHand = oriLine.UnitBaseFactor, BinAffected = oriLine.BinAffected, PostingUserName = oriLine.PostingUserName }; prDocLines.Add(rpLine); line++; } result[0] = prDocLines; result[1] = allNodeTrace; return result; } catch (Exception ex) { //Factory.Rollback(); ExceptionMngr.WriteEvent("ReceiptLinesForErpDocument", ListValues.EventType.Fatal, ex, null, ListValues.ErrorCategory.Business); //throw; return null; } }