protected override void BaseSecure(Security config)
        {
            var itemStates       = new PurchaseOrderItemStates(this.Session);
            var created          = itemStates.Created;
            var onHold           = itemStates.OnHold;
            var cancelled        = itemStates.Cancelled;
            var rejected         = itemStates.Rejected;
            var awaitingApproval = itemStates.AwaitingApproval;
            var inProcess        = itemStates.InProcess;
            var completed        = itemStates.Completed;
            var finished         = itemStates.Finished;
            var sent             = itemStates.Sent;

            var cancel       = this.Meta.Cancel;
            var reject       = this.Meta.Reject;
            var quickReceive = this.Meta.QuickReceive;
            var reopen       = this.Meta.Reopen;
            var delete       = this.Meta.Delete;

            config.Deny(this.ObjectType, created, reopen);
            config.Deny(this.ObjectType, onHold, quickReceive, delete, reopen);
            config.Deny(this.ObjectType, awaitingApproval, cancel, reject, quickReceive, delete, reopen);
            config.Deny(this.ObjectType, inProcess, cancel, reject, delete, quickReceive, delete, reopen);
            config.Deny(this.ObjectType, completed, cancel, reject, delete);
            config.Deny(this.ObjectType, cancelled, cancel, reject);
            config.Deny(this.ObjectType, rejected, cancel, reject);

            config.Deny(this.ObjectType, inProcess, Operations.Write);
            config.Deny(this.ObjectType, cancelled, Operations.Write);
            config.Deny(this.ObjectType, rejected, Operations.Write);
            config.Deny(this.ObjectType, completed, Operations.Execute, Operations.Write);
            config.Deny(this.ObjectType, finished, Operations.Execute, Operations.Write);
        }
Beispiel #2
0
        protected override void AppsSecure(Security config)
        {
            base.AppsSecure(config);

            var created           = new PurchaseOrderItemStates(this.Session).Created;
            var inProcess         = new PurchaseOrderItemStates(this.Session).InProcess;
            var partiallyReceived = new PurchaseOrderItemStates(this.Session).PartiallyReceived;
            var received          = new PurchaseOrderItemStates(this.Session).Received;
            var cancelled         = new PurchaseOrderItemStates(this.Session).Cancelled;
            var rejected          = new PurchaseOrderItemStates(this.Session).Rejected;
            var completed         = new PurchaseOrderItemStates(this.Session).Completed;
            var finished          = new PurchaseOrderItemStates(this.Session).Finished;

            var part = this.Meta.Part;

            config.Deny(this.ObjectType, partiallyReceived, part);
            config.Deny(this.ObjectType, received, part);

            var cancel = this.Meta.Cancel;
            var reject = this.Meta.Reject;

            // TODO: Delete
            var delete = this.Meta.Delete;

            config.Deny(this.ObjectType, created, cancel, reject);
            config.Deny(this.ObjectType, completed, delete);
            config.Deny(this.ObjectType, inProcess, delete);
            config.Deny(this.ObjectType, partiallyReceived, delete, cancel, reject);
            config.Deny(this.ObjectType, received, delete, cancel, reject);

            config.Deny(this.ObjectType, inProcess, Operations.Write);
            config.Deny(this.ObjectType, cancelled, Operations.Execute, Operations.Write);
            config.Deny(this.ObjectType, rejected, Operations.Execute, Operations.Write);
            config.Deny(this.ObjectType, completed, Operations.Execute, Operations.Write);
            config.Deny(this.ObjectType, finished, Operations.Execute);
        }
        public void BaseOnDerive(ObjectOnDerive method)
        {
            var derivation = method.Derivation;

            // States
            var states = new PurchaseOrderItemStates(this.Session());

            var purchaseOrderState = this.PurchaseOrderWherePurchaseOrderItem.PurchaseOrderState;

            if (purchaseOrderState.IsCreated &&
                !this.PurchaseOrderItemState.IsCancelled &&
                !this.PurchaseOrderItemState.IsRejected)
            {
                this.PurchaseOrderItemState = states.Created;
            }

            if (purchaseOrderState.IsInProcess &&
                (this.PurchaseOrderItemState.IsCreated || this.PurchaseOrderItemState.IsOnHold))
            {
                this.PurchaseOrderItemState = states.InProcess;
            }

            if (purchaseOrderState.IsOnHold && this.PurchaseOrderItemState.IsInProcess)
            {
                this.PurchaseOrderItemState = states.OnHold;
            }

            if (purchaseOrderState.IsSent && this.PurchaseOrderItemState.IsInProcess)
            {
                this.PurchaseOrderItemState = states.Sent;
            }

            if (this.IsValid && purchaseOrderState.IsFinished)
            {
                this.PurchaseOrderItemState = states.Finished;
            }

            if (this.IsValid && purchaseOrderState.IsCancelled)
            {
                this.PurchaseOrderItemState = states.Cancelled;
            }

            if (this.IsValid && purchaseOrderState.IsRejected)
            {
                this.PurchaseOrderItemState = states.Rejected;
            }

            if (this.IsValid)
            {
                if (this.AssignedDeliveryDate.HasValue)
                {
                    this.DeliveryDate = this.AssignedDeliveryDate.Value;
                }
                else if (this.PurchaseOrderWherePurchaseOrderItem.DeliveryDate.HasValue)
                {
                    this.DeliveryDate = this.PurchaseOrderWherePurchaseOrderItem.DeliveryDate.Value;
                }

                this.UnitBasePrice = 0;
                this.UnitDiscount  = 0;
                this.UnitSurcharge = 0;

                if (this.AssignedUnitPrice.HasValue)
                {
                    this.UnitBasePrice = this.AssignedUnitPrice.Value;
                    this.UnitPrice     = this.AssignedUnitPrice.Value;
                }
                else
                {
                    var order = this.PurchaseOrderWherePurchaseOrderItem;
                    this.UnitBasePrice = new SupplierOfferings(this.Strategy.Session).PurchasePrice(order.TakenViaSupplier, order.OrderDate, this.Part);
                }

                this.VatRegime = this.AssignedVatRegime ?? this.PurchaseOrderWherePurchaseOrderItem.VatRegime;
                this.VatRate   = this.VatRegime?.VatRate;

                this.UnitVat        = this.ExistVatRate ? this.UnitPrice * this.VatRate.Rate / 100 : 0;
                this.TotalBasePrice = this.UnitBasePrice * this.QuantityOrdered;
                this.TotalDiscount  = this.UnitDiscount * this.QuantityOrdered;
                this.TotalSurcharge = this.UnitSurcharge * this.QuantityOrdered;
                this.UnitPrice      = this.UnitBasePrice - this.UnitDiscount + this.UnitSurcharge;
                this.TotalVat       = this.UnitVat * this.QuantityOrdered;
                this.TotalExVat     = this.UnitPrice * this.QuantityOrdered;
                this.TotalIncVat    = this.TotalExVat + this.TotalVat;
            }

            if (this.ExistPart && this.Part.InventoryItemKind.Serialised)
            {
                derivation.Validation.AssertAtLeastOne(this, M.PurchaseOrderItem.SerialisedItem, M.PurchaseOrderItem.SerialNumber);
                derivation.Validation.AssertExistsAtMostOne(this, M.PurchaseOrderItem.SerialisedItem, M.PurchaseOrderItem.SerialNumber);
            }

            var purchaseOrderItemShipmentStates = new PurchaseOrderItemShipmentStates(derivation.Session);
            var purchaseOrderItemPaymentStates  = new PurchaseOrderItemPaymentStates(derivation.Session);
            var purchaseOrderItemStates         = new PurchaseOrderItemStates(derivation.Session);

            if (this.IsValid)
            {
                // ShipmentState
                if (this.ExistPart)
                {
                    var quantityReceived = 0M;
                    foreach (ShipmentReceipt shipmentReceipt in this.ShipmentReceiptsWhereOrderItem)
                    {
                        quantityReceived += shipmentReceipt.QuantityAccepted;
                    }

                    this.QuantityReceived = quantityReceived;
                }

                if (this.QuantityReceived == 0)
                {
                    this.PurchaseOrderItemShipmentState = new PurchaseOrderItemShipmentStates(this.Strategy.Session).NotReceived;
                }
                else
                {
                    this.PurchaseOrderItemShipmentState = this.QuantityReceived < this.QuantityOrdered ?
                                                          purchaseOrderItemShipmentStates.PartiallyReceived :
                                                          purchaseOrderItemShipmentStates.Received;
                }

                // PaymentState
                var orderBilling = this.OrderItemBillingsWhereOrderItem.Select(v => v.InvoiceItem).OfType <PurchaseInvoiceItem>().ToArray();

                if (orderBilling.Any())
                {
                    if (orderBilling.All(v => v.PurchaseInvoiceWherePurchaseInvoiceItem.PurchaseInvoiceState.IsPaid))
                    {
                        this.PurchaseOrderItemPaymentState = purchaseOrderItemPaymentStates.Paid;
                    }
                    else if (orderBilling.All(v => !v.PurchaseInvoiceWherePurchaseInvoiceItem.PurchaseInvoiceState.IsPaid))
                    {
                        this.PurchaseOrderItemPaymentState = purchaseOrderItemPaymentStates.NotPaid;
                    }
                    else
                    {
                        this.PurchaseOrderItemPaymentState = purchaseOrderItemPaymentStates.PartiallyPaid;
                    }
                }

                // PurchaseOrderItem States
                if (this.PurchaseOrderItemShipmentState.IsReceived)
                {
                    this.PurchaseOrderItemState = purchaseOrderItemStates.Completed;
                }

                if (this.PurchaseOrderItemState.IsCompleted && this.PurchaseOrderItemPaymentState.IsPaid)
                {
                    this.PurchaseOrderItemState = purchaseOrderItemStates.Finished;
                }
            }

            if (this.PurchaseOrderItemState.Equals(states.InProcess) ||
                this.PurchaseOrderItemState.Equals(states.Cancelled) ||
                this.PurchaseOrderItemState.Equals(states.Rejected))
            {
                NonSerialisedInventoryItem inventoryItem = null;

                if (this.ExistPart)
                {
                    var inventoryItems = this.Part.InventoryItemsWherePart;
                    inventoryItems.Filter.AddEquals(M.InventoryItem.Facility, this.PurchaseOrderWherePurchaseOrderItem.Facility);
                    inventoryItem = inventoryItems.First as NonSerialisedInventoryItem;
                }

                if (this.PurchaseOrderItemState.Equals(new PurchaseOrderItemStates(this.Strategy.Session).InProcess))
                {
                    if (!this.ExistPreviousQuantity || !this.QuantityOrdered.Equals(this.PreviousQuantity))
                    {
                        // TODO: Remove OnDerive
                        inventoryItem?.OnDerive(x => x.WithDerivation(derivation));
                    }
                }

                if (this.PurchaseOrderItemState.Equals(new PurchaseOrderItemStates(this.Strategy.Session).Cancelled) ||
                    this.PurchaseOrderItemState.Equals(new PurchaseOrderItemStates(this.Strategy.Session).Rejected))
                {
                    // TODO: Remove OnDerive
                    inventoryItem?.OnDerive(x => x.WithDerivation(derivation));
                }
            }

            if ((this.IsValid && !this.ExistOrderItemBillingsWhereOrderItem &&
                 this.PurchaseOrderItemShipmentState.IsReceived) || this.PurchaseOrderItemShipmentState.IsPartiallyReceived || (!this.ExistPart && this.QuantityReceived == 1))
            {
                this.CanInvoice = true;
            }
            else
            {
                this.CanInvoice = false;
            }
        }
Beispiel #4
0
        public void BaseOnDerive(ObjectOnDerive method)
        {
            var derivation = method.Derivation;

            if (this.TakenViaSupplier is Organisation supplier)
            {
                if (!this.OrderedBy.ActiveSuppliers.Contains(supplier))
                {
                    derivation.Validation.AddError(this, this.Meta.TakenViaSupplier, ErrorMessages.PartyIsNotASupplier);
                }
            }

            if (this.TakenViaSubcontractor is Organisation subcontractor)
            {
                if (!this.OrderedBy.ActiveSubContractors.Contains(subcontractor))
                {
                    derivation.Validation.AddError(this, this.Meta.TakenViaSubcontractor, ErrorMessages.PartyIsNotASubcontractor);
                }
            }

            derivation.Validation.AssertExistsAtMostOne(this, this.Meta.TakenViaSupplier, this.Meta.TakenViaSubcontractor);
            derivation.Validation.AssertAtLeastOne(this, this.Meta.TakenViaSupplier, this.Meta.TakenViaSubcontractor);

            if (!this.ExistShipToAddress)
            {
                this.ShipToAddress = this.OrderedBy.ShippingAddress;
            }

            if (!this.ExistBillToContactMechanism)
            {
                this.BillToContactMechanism = this.OrderedBy.ExistBillingAddress ? this.OrderedBy.BillingAddress : this.OrderedBy.GeneralCorrespondence;
            }

            if (!this.ExistTakenViaContactMechanism && this.ExistTakenViaSupplier)
            {
                this.TakenViaContactMechanism = this.TakenViaSupplier.OrderAddress;
            }

            this.VatRegime ??= this.TakenViaSupplier?.VatRegime;

            this.Locale = this.Strategy.Session.GetSingleton().DefaultLocale;

            var validOrderItems = this.PurchaseOrderItems.Where(v => v.IsValid).ToArray();

            this.ValidOrderItems = validOrderItems;

            var purchaseOrderShipmentStates = new PurchaseOrderShipmentStates(this.Strategy.Session);
            var purchaseOrderPaymentStates  = new PurchaseOrderPaymentStates(this.Strategy.Session);
            var purchaseOrderItemStates     = new PurchaseOrderItemStates(derivation.Session);

            // PurchaseOrder Shipment State
            if (validOrderItems.Any())
            {
                // var receivable = validOrderItems.Where(v => this.PurchaseOrderState.IsSent && v.PurchaseOrderItemState.IsInProcess && !v.PurchaseOrderItemShipmentState.IsReceived);
                if ((validOrderItems.Any(v => v.ExistPart) && validOrderItems.Where(v => v.ExistPart).All(v => v.PurchaseOrderItemShipmentState.IsReceived)) ||
                    (validOrderItems.Any(v => !v.ExistPart) && validOrderItems.Where(v => !v.ExistPart).All(v => v.PurchaseOrderItemShipmentState.IsReceived)))
                {
                    this.PurchaseOrderShipmentState = purchaseOrderShipmentStates.Received;
                }
                else if (validOrderItems.All(v => v.PurchaseOrderItemShipmentState.IsNotReceived))
                {
                    this.PurchaseOrderShipmentState = purchaseOrderShipmentStates.NotReceived;
                }
                else
                {
                    this.PurchaseOrderShipmentState = purchaseOrderShipmentStates.PartiallyReceived;
                }

                // PurchaseOrder Payment State
                if (validOrderItems.All(v => v.PurchaseOrderItemPaymentState.IsPaid))
                {
                    this.PurchaseOrderPaymentState = purchaseOrderPaymentStates.Paid;
                }
                else if (validOrderItems.All(v => v.PurchaseOrderItemPaymentState.IsNotPaid))
                {
                    this.PurchaseOrderPaymentState = purchaseOrderPaymentStates.NotPaid;
                }
                else
                {
                    this.PurchaseOrderPaymentState = purchaseOrderPaymentStates.PartiallyPaid;
                }

                // PurchaseOrder OrderState
                if (this.PurchaseOrderShipmentState.IsReceived)
                {
                    this.PurchaseOrderState = new PurchaseOrderStates(this.Strategy.Session).Completed;
                }

                if (this.PurchaseOrderState.IsCompleted && this.PurchaseOrderPaymentState.IsPaid)
                {
                    this.PurchaseOrderState = new PurchaseOrderStates(this.Strategy.Session).Finished;
                }
            }

            // Derive Totals
            var quantityOrderedByPart = new Dictionary <Part, decimal>();
            var totalBasePriceByPart  = new Dictionary <Part, decimal>();

            foreach (PurchaseOrderItem item in this.ValidOrderItems)
            {
                if (item.ExistPart)
                {
                    if (!quantityOrderedByPart.ContainsKey(item.Part))
                    {
                        quantityOrderedByPart.Add(item.Part, item.QuantityOrdered);
                        totalBasePriceByPart.Add(item.Part, item.TotalBasePrice);
                    }
                    else
                    {
                        quantityOrderedByPart[item.Part] += item.QuantityOrdered;
                        totalBasePriceByPart[item.Part]  += item.TotalBasePrice;
                    }
                }
            }

            if (this.ExistValidOrderItems)
            {
                this.TotalBasePrice = 0;
                this.TotalDiscount  = 0;
                this.TotalSurcharge = 0;
                this.TotalVat       = 0;
                this.TotalExVat     = 0;
                this.TotalIncVat    = 0;

                foreach (PurchaseOrderItem orderItem in this.ValidOrderItems)
                {
                    this.TotalBasePrice += orderItem.TotalBasePrice;
                    this.TotalDiscount  += orderItem.TotalDiscount;
                    this.TotalSurcharge += orderItem.TotalSurcharge;
                    this.TotalVat       += orderItem.TotalVat;
                    this.TotalExVat     += orderItem.TotalExVat;
                    this.TotalIncVat    += orderItem.TotalIncVat;
                }
            }

            this.PreviousTakenViaSupplier = this.TakenViaSupplier;

            // Derive Workflow
            this.WorkItemDescription = $"PurchaseOrder: {this.OrderNumber} [{this.TakenViaSupplier?.PartyName}]";
            var openTasks = this.TasksWhereWorkItem.Where(v => !v.ExistDateClosed).ToArray();

            if (this.PurchaseOrderState.IsAwaitingApprovalLevel1)
            {
                if (!openTasks.OfType <PurchaseOrderApprovalLevel1>().Any())
                {
                    new PurchaseOrderApprovalLevel1Builder(this.Session()).WithPurchaseOrder(this).Build();
                }
            }

            if (this.PurchaseOrderState.IsAwaitingApprovalLevel2)
            {
                if (!openTasks.OfType <PurchaseOrderApprovalLevel2>().Any())
                {
                    new PurchaseOrderApprovalLevel2Builder(this.Session()).WithPurchaseOrder(this).Build();
                }
            }

            this.ResetPrintDocument();
        }
Beispiel #5
0
        public void BaseOnDerive(ObjectOnDerive method)
        {
            var derivation = method.Derivation;

            if (!this.ExistOrderNumber)
            {
                var year = this.OrderDate.Year;
                this.OrderNumber = this.OrderedBy.NextPurchaseOrderNumber(year);

                var fiscalYearInternalOrganisationSequenceNumbers = this.OrderedBy?.FiscalYearsInternalOrganisationSequenceNumbers.FirstOrDefault(v => v.FiscalYear == year);
                var prefix = this.OrderedBy.InvoiceSequence.IsEnforcedSequence ? this.OrderedBy?.PurchaseOrderNumberPrefix : fiscalYearInternalOrganisationSequenceNumbers.PurchaseOrderNumberPrefix;
                this.SortableOrderNumber = this.Session().GetSingleton().SortableNumber(prefix, this.OrderNumber, year.ToString());
            }

            if (this.TakenViaSupplier is Organisation supplier)
            {
                if (!this.OrderedBy.ActiveSuppliers.Contains(supplier))
                {
                    derivation.Validation.AddError(this, this.Meta.TakenViaSupplier, ErrorMessages.PartyIsNotASupplier);
                }
            }

            if (this.TakenViaSubcontractor is Organisation subcontractor)
            {
                if (!this.OrderedBy.ActiveSubContractors.Contains(subcontractor))
                {
                    derivation.Validation.AddError(this, this.Meta.TakenViaSubcontractor, ErrorMessages.PartyIsNotASubcontractor);
                }
            }

            if (this.PurchaseOrderState.IsCreated)
            {
                this.DerivedLocale                   = this.Locale ?? this.OrderedBy?.Locale;
                this.DerivedCurrency                 = this.AssignedCurrency ?? this.OrderedBy?.PreferredCurrency;
                this.DerivedVatRegime                = this.AssignedVatRegime;
                this.DerivedIrpfRegime               = this.AssignedIrpfRegime;
                this.DerivedShipToAddress            = this.AssignedShipToAddress ?? this.OrderedBy?.ShippingAddress;
                this.DerivedBillToContactMechanism   = this.AssignedBillToContactMechanism ?? this.OrderedBy?.BillingAddress ?? this.OrderedBy?.GeneralCorrespondence;
                this.DerivedTakenViaContactMechanism = this.AssignedTakenViaContactMechanism ?? this.TakenViaSupplier?.OrderAddress;
            }

            derivation.Validation.AssertExistsAtMostOne(this, this.Meta.TakenViaSupplier, this.Meta.TakenViaSubcontractor);
            derivation.Validation.AssertAtLeastOne(this, this.Meta.TakenViaSupplier, this.Meta.TakenViaSubcontractor);

            if (this.ExistOrderDate &&
                this.ExistOrderedBy &&
                this.DerivedCurrency != this.OrderedBy.PreferredCurrency)
            {
                var exchangeRate = this.DerivedCurrency.ExchangeRatesWhereFromCurrency.Where(v => v.ValidFrom.Date <= this.OrderDate.Date && v.ToCurrency.Equals(this.OrderedBy.PreferredCurrency)).OrderByDescending(v => v.ValidFrom).FirstOrDefault();

                if (exchangeRate == null)
                {
                    exchangeRate = this.OrderedBy.PreferredCurrency.ExchangeRatesWhereFromCurrency.Where(v => v.ValidFrom.Date <= this.OrderDate.Date && v.ToCurrency.Equals(this.DerivedCurrency)).OrderByDescending(v => v.ValidFrom).FirstOrDefault();
                }

                if (exchangeRate == null)
                {
                    derivation.Validation.AddError(this, M.Quote.AssignedCurrency, ErrorMessages.CurrencyNotAllowed);
                }
            }

            var validOrderItems = this.PurchaseOrderItems.Where(v => v.IsValid).ToArray();

            this.ValidOrderItems = validOrderItems;

            var purchaseOrderShipmentStates = new PurchaseOrderShipmentStates(this.Strategy.Session);
            var purchaseOrderPaymentStates  = new PurchaseOrderPaymentStates(this.Strategy.Session);
            var purchaseOrderItemStates     = new PurchaseOrderItemStates(derivation.Session);

            // PurchaseOrder Shipment State
            if (validOrderItems.Any())
            {
                if (validOrderItems.Any(v => v.IsReceivable))
                {
                    if (validOrderItems.Where(v => v.IsReceivable).All(v => v.PurchaseOrderItemShipmentState.IsReceived))
                    {
                        this.PurchaseOrderShipmentState = purchaseOrderShipmentStates.Received;
                    }
                    else if (validOrderItems.Where(v => v.IsReceivable).All(v => v.PurchaseOrderItemShipmentState.IsNotReceived))
                    {
                        this.PurchaseOrderShipmentState = purchaseOrderShipmentStates.NotReceived;
                    }
                    else
                    {
                        this.PurchaseOrderShipmentState = purchaseOrderShipmentStates.PartiallyReceived;
                    }
                }
                else
                {
                    this.PurchaseOrderShipmentState = purchaseOrderShipmentStates.Na;
                }

                // PurchaseOrder Payment State
                if (validOrderItems.All(v => v.PurchaseOrderItemPaymentState.IsPaid))
                {
                    this.PurchaseOrderPaymentState = purchaseOrderPaymentStates.Paid;
                }
                else if (validOrderItems.All(v => v.PurchaseOrderItemPaymentState.IsNotPaid))
                {
                    this.PurchaseOrderPaymentState = purchaseOrderPaymentStates.NotPaid;
                }
                else
                {
                    this.PurchaseOrderPaymentState = purchaseOrderPaymentStates.PartiallyPaid;
                }

                // PurchaseOrder OrderState
                if (this.PurchaseOrderState.IsSent &&
                    (this.PurchaseOrderShipmentState.IsReceived || this.PurchaseOrderShipmentState.IsNa))
                {
                    this.PurchaseOrderState = new PurchaseOrderStates(this.Strategy.Session).Completed;
                }

                if (this.PurchaseOrderState.IsCompleted && this.PurchaseOrderPaymentState.IsPaid)
                {
                    this.PurchaseOrderState = new PurchaseOrderStates(this.Strategy.Session).Finished;
                }
            }

            // Derive Totals
            var quantityOrderedByPart = new Dictionary <Part, decimal>();
            var totalBasePriceByPart  = new Dictionary <Part, decimal>();

            foreach (PurchaseOrderItem item in this.ValidOrderItems)
            {
                if (item.ExistPart)
                {
                    if (!quantityOrderedByPart.ContainsKey(item.Part))
                    {
                        quantityOrderedByPart.Add(item.Part, item.QuantityOrdered);
                        totalBasePriceByPart.Add(item.Part, item.TotalBasePrice);
                    }
                    else
                    {
                        quantityOrderedByPart[item.Part] += item.QuantityOrdered;
                        totalBasePriceByPart[item.Part]  += item.TotalBasePrice;
                    }
                }
            }

            this.TotalBasePrice   = 0;
            this.TotalDiscount    = 0;
            this.TotalSurcharge   = 0;
            this.TotalVat         = 0;
            this.TotalIrpf        = 0;
            this.TotalExVat       = 0;
            this.TotalExtraCharge = 0;
            this.TotalIncVat      = 0;
            this.GrandTotal       = 0;
            this.TotalShippingAndHandlingInPreferredCurrency = 0;
            this.TotalFeeInPreferredCurrency         = 0;
            this.TotalExtraChargeInPreferredCurrency = 0;
            this.TotalListPriceInPreferredCurrency   = 0;

            foreach (PurchaseOrderItem orderItem in this.ValidOrderItems)
            {
                this.TotalBasePrice += orderItem.TotalBasePrice;
                this.TotalDiscount  += orderItem.TotalDiscount;
                this.TotalSurcharge += orderItem.TotalSurcharge;
                this.TotalVat       += orderItem.TotalVat;
                this.TotalIrpf      += orderItem.TotalIrpf;
                this.TotalExVat     += orderItem.TotalExVat;
                this.TotalIncVat    += orderItem.TotalIncVat;
                this.GrandTotal     += orderItem.GrandTotal;
            }

            if (this.ExistOrderDate && this.ExistDerivedCurrency && this.ExistOrderedBy)
            {
                this.TotalBasePriceInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalBasePrice, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.TotalDiscountInPreferredCurrency  = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalDiscount, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.TotalSurchargeInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalSurcharge, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.TotalExVatInPreferredCurrency     = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalExVat, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.TotalVatInPreferredCurrency       = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalVat, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.TotalIncVatInPreferredCurrency    = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalIncVat, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.TotalIrpfInPreferredCurrency      = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalIrpf, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.GrandTotalInPreferredCurrency     = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.GrandTotal, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
            }

            this.TotalBasePrice = Rounder.RoundDecimal(this.TotalBasePrice, 2);
            this.TotalDiscount  = Rounder.RoundDecimal(this.TotalDiscount, 2);
            this.TotalSurcharge = Rounder.RoundDecimal(this.TotalSurcharge, 2);
            this.TotalVat       = Rounder.RoundDecimal(this.TotalVat, 2);
            this.TotalIrpf      = Rounder.RoundDecimal(this.TotalIrpf, 2);
            this.TotalExVat     = Rounder.RoundDecimal(this.TotalExVat, 2);
            this.TotalIncVat    = Rounder.RoundDecimal(this.TotalIncVat, 2);
            this.GrandTotal     = Rounder.RoundDecimal(this.GrandTotal, 2);

            this.PreviousTakenViaSupplier = this.TakenViaSupplier;

            // Derive Workflow
            this.WorkItemDescription = $"PurchaseOrder: {this.OrderNumber} [{this.TakenViaSupplier?.PartyName}]";
            var openTasks = this.TasksWhereWorkItem.Where(v => !v.ExistDateClosed).ToArray();

            if (this.PurchaseOrderState.IsAwaitingApprovalLevel1)
            {
                if (!openTasks.OfType <PurchaseOrderApprovalLevel1>().Any())
                {
                    new PurchaseOrderApprovalLevel1Builder(this.Session()).WithPurchaseOrder(this).Build();
                }
            }

            if (this.PurchaseOrderState.IsAwaitingApprovalLevel2)
            {
                if (!openTasks.OfType <PurchaseOrderApprovalLevel2>().Any())
                {
                    new PurchaseOrderApprovalLevel2Builder(this.Session()).WithPurchaseOrder(this).Build();
                }
            }

            this.Sync(derivation, validOrderItems);

            this.ResetPrintDocument();
        }