public XElement GetDocumentOperations(Document document) { var processTypeAttr = document.Attributes.Children.Where(a => a.DocumentFieldName == DocumentFieldName.Attribute_ProcessType).FirstOrDefault(); if (processTypeAttr == null) { return(null); } var processObjectAttr = document.Attributes.Children.Where(a => a.DocumentFieldName == DocumentFieldName.Attribute_ProcessObject).FirstOrDefault(); string processObject = processObjectAttr.Value.Value; var processStateAttr = document.Attributes.Children.Where(a => a.DocumentFieldName == DocumentFieldName.Attribute_ProcessState).FirstOrDefault(); DocumentRelation processMainObjectRelation = null; DocumentRelationType?drt = this.GetRelationTypeToMainObject(document); if (drt != null) { processMainObjectRelation = document.Relations.Children.Where(r => r.RelationType == drt.Value).FirstOrDefault(); } XElement process = ConfigurationMapper.Instance.Processes[processTypeAttr.Value.Value]; string processState = null; Document mainObject = null; if (processStateAttr != null) // jestesmy w glownym obiekcie { processState = processStateAttr.Value.Value.ToLowerInvariant(); } else //wczytujemy glowny obiekt i z niego odczytujemy stan { if (processMainObjectRelation == null) { //throw new InvalidOperationException("Relation to the main object not found in the given document."); return(null); //zmienione bo w przypadku SERWIS->FVS->WZ to wz nie ma powiazania z serwisem i narazie upraszczamy } var moElement = process.Element("objects").Elements().Where(o => o.Attribute("mainObject") != null && o.Attribute("mainObject").Value.ToUpperInvariant() == "TRUE").First(); string typeSymbol = moElement.Attribute("typeSymbol").Value; DocumentType dt = DictionaryMapper.Instance.GetDocumentType(typeSymbol); using (Coordinator c = Coordinator.GetCoordinatorForSpecifiedType(dt.BusinessObjectType, false, false)) { mainObject = (Document)c.LoadBusinessObject(dt.BusinessObjectType, processMainObjectRelation.RelatedDocument.Id.Value); } processState = mainObject.Attributes.Children.Where(aa => aa.DocumentFieldName == DocumentFieldName.Attribute_ProcessState).First().Value.Value.ToLowerInvariant(); } //mamy stan procesu, mamy role jaka odgrywa biezacy dokument (processObject), wiec teraz sprawdzamy jakie operacje moze miec var operationsResult = from node in process.Element("states").Elements("state") where node.Attribute("name").Value == processState from operation in node.Elements() where operation.Attribute("object").Value == processObject select operation; XElement operations = new XElement("operations"); operations.Add(operationsResult); if (document.DocumentType.DocumentCategory == DocumentCategory.SalesOrder) { CommercialDocument comDoc = document as CommercialDocument; if (comDoc.SalesOrderSettlements == null) //na wszelki wypadek tylko jak w pozniejszym developmencie zdarzy sie inny przypadek { SalesOrderSettlements settlements = new SalesOrderSettlements(); settlements.LoadSalesOrder(comDoc); XElement prepaidsXml = DependencyContainerManager.Container.Get <DocumentMapper>().GetSalesOrderSettledAmount(comDoc.Id.Value); settlements.LoadPrepaids(prepaidsXml); comDoc.SalesOrderSettlements = settlements; } } this.FilterOperations(document, operations); return(operations); }
public static void GeneratePrepaymentDocument(XElement source, CommercialDocument destination) { /* * <source type="salesOrder"> * <salesOrderId>{documentId}</salesOrderId> * <processObject>prepaidInvoice</processObject> * <closeOrder>false</closeOrder> * </source> */ DocumentMapper mapper = DependencyContainerManager.Container.Get <DocumentMapper>(); bool closeOrder = false; if (source.Element("closeOrder") != null && source.Element("closeOrder").Value.ToUpperInvariant() == "TRUE") { closeOrder = true; } CommercialDocument salesOrder = (CommercialDocument)mapper.LoadBusinessObject(BusinessObjectType.CommercialDocument, new Guid(source.Element("salesOrderId").Value)); SalesOrderFactory.CheckIfSalesOrderHasWarehouseDocumentsWithInvoices(salesOrder, closeOrder); SalesOrderSettlements salesOrderSettlements = new SalesOrderSettlements(); salesOrderSettlements.LoadSalesOrder(salesOrder); XElement settledAmount = mapper.GetSalesOrderSettledAmount(salesOrder.Id.Value); salesOrderSettlements.LoadPrepaids(settledAmount); destination.SalesOrderSettlements = salesOrderSettlements; string processType = salesOrder.Attributes[DocumentFieldName.Attribute_ProcessType].Value.Value; string processObject = source.Element("processObject").Value; bool isSimulated = processObject == "simulatedInvoice"; bool hasProtocole = source.Element("protocole") != null && source.Element("protocole").Value == "true"; ProcessManager.Instance.AppendProcessAttributes(destination, processType, processObject, null, null); DuplicableAttributeFactory.DuplicateAttributes(salesOrder, destination); if (isSimulated && hasProtocole) { destination.Attributes.GetOrCreateNew(DocumentFieldName.Attribute_IsSimulateSettlementInvoiceWithProtocole).Value.Value = "1"; } //sprawdzamy czy dokumenty zrodlowe maja zgodne sposoby liczenia if (salesOrder.CalculationType != destination.CalculationType && destination.DocumentType.CommercialDocumentOptions.AllowCalculationTypeChange) { destination.CalculationType = salesOrder.CalculationType; } if (salesOrder.Contractor != null) { destination.Contractor = (Contractor)salesOrder.Contractor; } if (salesOrder.ContractorAddressId != null) { destination.ContractorAddressId = salesOrder.ContractorAddressId; } int prepaidDocuments = 0; prepaidDocuments = salesOrder.Relations.Where(r => r.RelationType == DocumentRelationType.SalesOrderToInvoice).Count(); destination.Tag = prepaidDocuments.ToString(CultureInfo.InvariantCulture); /* teraz wybieramy odpowiednia sciezke algorytmu. mamy takie mozliwosc: * 1) wystawiamy zaliczke * - w takiej sytuacji wybieramy id towaru zaliczkowego dla kazdej ze stawek vat i wpisujemy tam wartosci nierozliczone * 2) wystawiamy fakture rozliczajaca (closeOrder == true) podczas gdy mamy zaliczki (prepaidDocuments > 0) * - kopiujemy wszystkie pozycje z ZS 1:1, a tabele vat pomniejszamy o sume zaliczek * 3) wystawiamy fakture rozliczajaca (closeOrder == true) i nie mamy dokumentow zaliczkowych (prepaidDocuments == 0) * - w takim przypadku zamowienie sprzedazowe traktujemy jako proforme, kopiujemy wszystkie pozycje i tabele vat bez zmian i tyle */ //wstawiamy odpowiedni towar na zaliczke + ustawiamy odpowiednai wartosc int stage = 0; if (closeOrder) { stage = 0; } else if (prepaidDocuments == 0) { stage = 1; } else if (prepaidDocuments == 1) { stage = 2; } else if (prepaidDocuments == 2) { stage = 3; } else if (prepaidDocuments >= 3) { stage = 4; } List <Guid> items = new List <Guid>(2); ICollection <SalesOrderSettlement> unsettledValues = salesOrderSettlements.GetUnsettledValues(); foreach (var v in salesOrder.VatTableEntries.GetVatRates()) { items.Add(ProcessManager.Instance.GetPrepaidItemId(salesOrder, stage, v)); } XDocument xml = DependencyContainerManager.Container.Get <ItemMapper>().GetItemsDetailsForDocument(false, null, null, items); if (closeOrder) { SalesOrderFactory.CopyLinesFromSalesOrder(salesOrder, destination, false, true, false, true); destination.Calculate(); //Ostatnia rata pchamy do atrybutu zeby wydruk fiskalny wiedzial co ma wydrukowac if (destination.CalculationType == CalculationType.Gross && !isSimulated) { XElement fiscalLines = new XElement("fiscalLines"); foreach (var v in unsettledValues) { XElement itemXml = xml.Root.Elements().Where(i => i.Attribute("id").Value == ProcessManager.Instance.GetPrepaidItemId(salesOrder, stage, v.VatRateId).ToUpperString()).First(); XElement fiscalLine = new XElement("fiscalLine"); fiscalLine.Add(new XElement("itemName", itemXml.Attribute("name").Value)); fiscalLine.Add(new XElement("quantity", "1")); fiscalLine.Add(new XElement("vatRateId", itemXml.Attribute("vatRateId").Value)); fiscalLine.Add(new XElement("grossPrice", v.GrossValue.ToString(CultureInfo.InvariantCulture))); fiscalLine.Add(new XElement("grossValue", v.GrossValue.ToString(CultureInfo.InvariantCulture))); fiscalLine.Add(new XElement("unitId", itemXml.Attribute("unitId").Value)); fiscalLines.Add(fiscalLine); } var attribute = destination.Attributes.CreateNew(DocumentFieldName.Attribute_FiscalPrepayment); attribute.Value = fiscalLines; } if (prepaidDocuments > 0) // *2) { decimal maxDifference = ProcessManager.Instance.GetMaxSettlementDifference(salesOrder); foreach (var v in salesOrderSettlements.Prepaids) { if (v.NetValue > 0 || v.GrossValue > 0 || v.VatValue > 0) { var vt = destination.VatTableEntries.Where(t => t.VatRateId == v.VatRateId).FirstOrDefault(); var prepaidVt = destination.VatTableEntries.CreateNewAfter(vt, v.VatRateId); prepaidVt.VatRateId = v.VatRateId; prepaidVt.NetValue = -v.NetValue; prepaidVt.GrossValue = -v.GrossValue; prepaidVt.VatValue = -v.VatValue; decimal vtNetValue = 0; decimal vtGrossValue = 0; decimal vtVatValue = 0; if (vt != null) { vtNetValue = vt.NetValue; vtGrossValue = vt.GrossValue; vtVatValue = vt.VatValue; } decimal grossBalance = vtGrossValue + prepaidVt.GrossValue; decimal netBalance = vtNetValue + prepaidVt.NetValue; decimal vatBalance = vtVatValue + prepaidVt.VatValue; SalesOrderBalanceValidator validator = new SalesOrderBalanceValidator(maxDifference, grossBalance, netBalance, vatBalance); if (validator.IsIllegalOverPayment) { throw new ClientException(ClientExceptionId.SalesOrderSettlementOverpaidError, null, "value:" + (-grossBalance).ToString(CultureInfo.InvariantCulture).Replace('.', ',')); //nadpłata powyżej granicy błędu } else if (validator.IsAcceptableOverPayment) //czyli mamy nadplate w granicy bledu { prepaidVt.NetValue = -vtNetValue; prepaidVt.GrossValue = -vtGrossValue; prepaidVt.VatValue = -vtVatValue; } } } } else { throw new ClientException(ClientExceptionId.UnableToCreateSettlementDocument3); } decimal netValue = 0; decimal grossValue = 0; decimal vatValue = 0; foreach (var vt in destination.VatTableEntries) { netValue += vt.NetValue; grossValue += vt.GrossValue; vatValue += vt.VatValue; } destination.NetValue = netValue; destination.GrossValue = grossValue; destination.VatValue = vatValue; destination.DisableLinesChange = DisableDocumentChangeReason.LINES_SETTLEMENT_INVOICE; if (!isSimulated) { var attr = destination.Attributes.CreateNew(DocumentFieldName.Attribute_IsSettlementDocument); attr.Value.Value = "1"; } } else //1) wystawiamy zaliczke { foreach (XElement itemXml in xml.Root.Elements("item")) { CommercialDocumentLine line = destination.Lines.CreateNew(); line.ItemId = new Guid(itemXml.Attribute("id").Value); Guid vatRateId = new Guid(itemXml.Attribute("vatRateId").Value); if (itemXml.Attribute("code") != null) { line.ItemCode = itemXml.Attribute("code").Value; } line.UnitId = new Guid(itemXml.Attribute("unitId").Value); line.VatRateId = vatRateId; line.ItemVersion = new Guid(itemXml.Attribute("version").Value); line.Quantity = 1; line.ItemName = itemXml.Attribute("name").Value; } destination.Calculate(); } }