protected override void BaseSecure(Security config) { var readyForPosting = new SalesInvoiceItemStates(this.Session).ReadyForPosting; var notPaid = new SalesInvoiceItemStates(this.Session).NotPaid; var paid = new SalesInvoiceItemStates(this.Session).Paid; var writtenOff = new SalesInvoiceItemStates(this.Session).WrittenOff; var cancelledByInvoice = new SalesInvoiceItemStates(this.Session).CancelledByInvoice; config.Deny(this.ObjectType, notPaid, Operations.Write, Operations.Execute); config.Deny(this.ObjectType, paid, Operations.Write, Operations.Execute); config.Deny(this.ObjectType, writtenOff, Operations.Write, Operations.Execute); config.Deny(this.ObjectType, cancelledByInvoice, Operations.Write); }
protected override void AppsSecure(Security config) { base.AppsSecure(config); ObjectState sent = new SalesInvoiceItemStates(this.Session).Sent; ObjectState paid = new SalesInvoiceItemStates(this.Session).Paid; ObjectState writtenOff = new SalesInvoiceItemStates(this.Session).WrittenOff; ObjectState cancelled = new SalesInvoiceItemStates(this.Session).Cancelled; config.Deny(this.ObjectType, sent, Operations.Write, Operations.Execute); config.Deny(this.ObjectType, paid, Operations.Write, Operations.Execute); config.Deny(this.ObjectType, writtenOff, Operations.Write, Operations.Execute); config.Deny(this.ObjectType, cancelled, Operations.Write, Operations.Execute); }
public void BaseOnDerive(ObjectOnDerive method) { var derivation = method.Derivation; var salesInvoice = this.SalesInvoiceWhereSalesInvoiceItem; var salesInvoiceItemStates = new SalesInvoiceItemStates(derivation.Session); derivation.Validation.AssertExistsAtMostOne(this, M.SalesInvoiceItem.Product, M.SalesInvoiceItem.ProductFeatures, M.SalesInvoiceItem.Part); derivation.Validation.AssertExistsAtMostOne(this, M.SalesInvoiceItem.SerialisedItem, M.SalesInvoiceItem.ProductFeatures, M.SalesInvoiceItem.Part); if (!this.ExistDerivationTrigger) { this.DerivationTrigger = Guid.NewGuid(); } if (this.ExistSerialisedItem && !this.ExistNextSerialisedItemAvailability && salesInvoice.SalesInvoiceType.Equals(new SalesInvoiceTypes(this.Session()).SalesInvoice)) { derivation.Validation.AssertExists(this, this.Meta.NextSerialisedItemAvailability); } if (this.Part != null && this.Part.InventoryItemKind.IsSerialised && this.Quantity != 1) { derivation.Validation.AddError(this, M.SalesInvoiceItem.Quantity, ErrorMessages.InvalidQuantity); } if (this.Part != null && this.Part.InventoryItemKind.IsNonSerialised && this.Quantity == 0) { derivation.Validation.AddError(this, M.SalesInvoiceItem.Quantity, ErrorMessages.InvalidQuantity); } if (this.ExistInvoiceItemType && this.InvoiceItemType.MaxQuantity.HasValue && this.Quantity > this.InvoiceItemType.MaxQuantity.Value) { derivation.Validation.AddError(this, M.SalesInvoiceItem.Quantity, ErrorMessages.InvalidQuantity); } this.DerivedVatRegime = this.ExistAssignedVatRegime ? this.AssignedVatRegime : this.SalesInvoiceWhereSalesInvoiceItem?.DerivedVatRegime; this.VatRate = this.DerivedVatRegime?.VatRates.First(v => v.FromDate <= salesInvoice.InvoiceDate && (!v.ExistThroughDate || v.ThroughDate >= salesInvoice.InvoiceDate)); this.DerivedIrpfRegime = this.ExistAssignedIrpfRegime ? this.AssignedIrpfRegime : this.SalesInvoiceWhereSalesInvoiceItem?.DerivedIrpfRegime; this.IrpfRate = this.DerivedIrpfRegime?.IrpfRates.First(v => v.FromDate <= salesInvoice.InvoiceDate && (!v.ExistThroughDate || v.ThroughDate >= salesInvoice.InvoiceDate)); if (this.ExistInvoiceItemType && this.IsSubTotalItem().Result == true && this.Quantity <= 0) { derivation.Validation.AssertExists(this, this.Meta.Quantity); } this.AmountPaid = 0; foreach (PaymentApplication paymentApplication in this.PaymentApplicationsWhereInvoiceItem) { this.AmountPaid += paymentApplication.AmountApplied; } if (salesInvoice != null && salesInvoice.SalesInvoiceState.IsReadyForPosting && this.SalesInvoiceItemState.IsCancelledByInvoice) { this.SalesInvoiceItemState = salesInvoiceItemStates.ReadyForPosting; } // SalesInvoiceItem States if (salesInvoice != null && this.IsValid) { if (salesInvoice.SalesInvoiceState.IsWrittenOff) { this.SalesInvoiceItemState = salesInvoiceItemStates.WrittenOff; } if (salesInvoice.SalesInvoiceState.IsCancelled) { this.SalesInvoiceItemState = salesInvoiceItemStates.CancelledByInvoice; } } }
public void BaseOnDerive(ObjectOnDerive method) { var derivation = method.Derivation; var salesInvoice = this.SalesInvoiceWhereSalesInvoiceItem; var salesInvoiceItemStates = new SalesInvoiceItemStates(derivation.Session); derivation.Validation.AssertExistsAtMostOne(this, M.SalesInvoiceItem.Product, M.SalesInvoiceItem.ProductFeatures, M.SalesInvoiceItem.Part); derivation.Validation.AssertExistsAtMostOne(this, M.SalesInvoiceItem.SerialisedItem, M.SalesInvoiceItem.ProductFeatures, M.SalesInvoiceItem.Part); if (!this.ExistDerivationTrigger) { this.DerivationTrigger = Guid.NewGuid(); } if (this.ExistSerialisedItem && !this.ExistNextSerialisedItemAvailability && salesInvoice.SalesInvoiceType.Equals(new SalesInvoiceTypes(this.Session()).SalesInvoice)) { derivation.Validation.AssertExists(this, this.Meta.NextSerialisedItemAvailability); } if (this.Part != null && this.Part.InventoryItemKind.IsSerialised && this.Quantity != 1) { derivation.Validation.AddError(this, M.SalesInvoiceItem.Quantity, ErrorMessages.InvalidQuantity); } if (this.Part != null && this.Part.InventoryItemKind.IsNonSerialised && this.Quantity == 0) { derivation.Validation.AddError(this, M.SalesInvoiceItem.Quantity, ErrorMessages.InvalidQuantity); } if (this.ExistInvoiceItemType && this.InvoiceItemType.MaxQuantity.HasValue && this.Quantity > this.InvoiceItemType.MaxQuantity.Value) { derivation.Validation.AddError(this, M.SalesInvoiceItem.Quantity, ErrorMessages.InvalidQuantity); } this.VatRegime = this.ExistAssignedVatRegime ? this.AssignedVatRegime : this.SalesInvoiceWhereSalesInvoiceItem?.VatRegime; this.VatRate = this.VatRegime?.VatRate; this.IrpfRegime = this.ExistAssignedIrpfRegime ? this.AssignedIrpfRegime : this.SalesInvoiceWhereSalesInvoiceItem?.IrpfRegime; this.IrpfRate = this.IrpfRegime?.IrpfRate; if (this.ExistInvoiceItemType && this.IsSubTotalItem().Result == true && this.Quantity <= 0) { derivation.Validation.AssertExists(this, this.Meta.Quantity); } this.AmountPaid = 0; foreach (PaymentApplication paymentApplication in this.PaymentApplicationsWhereInvoiceItem) { this.AmountPaid += paymentApplication.AmountApplied; } if (salesInvoice != null && salesInvoice.SalesInvoiceState.IsReadyForPosting && this.SalesInvoiceItemState.IsCancelledByInvoice) { this.SalesInvoiceItemState = salesInvoiceItemStates.ReadyForPosting; } // SalesInvoiceItem States if (salesInvoice != null && this.IsValid) { if (salesInvoice.SalesInvoiceState.IsWrittenOff) { this.SalesInvoiceItemState = salesInvoiceItemStates.WrittenOff; } if (salesInvoice.SalesInvoiceState.IsCancelled) { this.SalesInvoiceItemState = salesInvoiceItemStates.CancelledByInvoice; } } // TODO: Move to Custom if (derivation.ChangeSet.IsCreated(this) && !this.ExistDescription) { if (this.ExistSerialisedItem) { var builder = new StringBuilder(); var part = this.SerialisedItem.PartWhereSerialisedItem; if (part != null && part.ExistManufacturedBy) { builder.Append($", Manufacturer: {part.ManufacturedBy.PartyName}"); } if (part != null && part.ExistBrand) { builder.Append($", Brand: {part.Brand.Name}"); } if (part != null && part.ExistModel) { builder.Append($", Model: {part.Model.Name}"); } builder.Append($", SN: {this.SerialisedItem.SerialNumber}"); if (this.SerialisedItem.ExistManufacturingYear) { builder.Append($", YOM: {this.SerialisedItem.ManufacturingYear}"); } foreach (SerialisedItemCharacteristic characteristic in this.SerialisedItem.SerialisedItemCharacteristics) { if (characteristic.ExistValue) { var characteristicType = characteristic.SerialisedItemCharacteristicType; if (characteristicType.ExistUnitOfMeasure) { var uom = characteristicType.UnitOfMeasure.ExistAbbreviation ? characteristicType.UnitOfMeasure.Abbreviation : characteristicType.UnitOfMeasure.Name; builder.Append( $", {characteristicType.Name}: {characteristic.Value} {uom}"); } else { builder.Append($", {characteristicType.Name}: {characteristic.Value}"); } } } var details = builder.ToString(); if (details.StartsWith(",")) { details = details.Substring(2); } this.Description = details; } else if (this.ExistProduct && this.Product is UnifiedGood unifiedGood) { var builder = new StringBuilder(); if (unifiedGood != null && unifiedGood.ExistManufacturedBy) { builder.Append($", Manufacturer: {unifiedGood.ManufacturedBy.PartyName}"); } if (unifiedGood != null && unifiedGood.ExistBrand) { builder.Append($", Brand: {unifiedGood.Brand.Name}"); } if (unifiedGood != null && unifiedGood.ExistModel) { builder.Append($", Model: {unifiedGood.Model.Name}"); } foreach (SerialisedItemCharacteristic characteristic in unifiedGood.SerialisedItemCharacteristics) { if (characteristic.ExistValue) { var characteristicType = characteristic.SerialisedItemCharacteristicType; if (characteristicType.ExistUnitOfMeasure) { var uom = characteristicType.UnitOfMeasure.ExistAbbreviation ? characteristicType.UnitOfMeasure.Abbreviation : characteristicType.UnitOfMeasure.Name; builder.Append($", {characteristicType.Name}: {characteristic.Value} {uom}"); } else { builder.Append($", {characteristicType.Name}: {characteristic.Value}"); } } } var details = builder.ToString(); if (details.StartsWith(",")) { details = details.Substring(2); } this.Description = details; } } }
public void BaseOnDerive(ObjectOnDerive method) { var derivation = method.Derivation; var session = this.Session(); var internalOrganisations = new Organisations(session).InternalOrganisations(); if (!this.ExistBilledFrom && internalOrganisations.Count() == 1) { this.BilledFrom = internalOrganisations.First(); } if (!this.ExistStore && this.ExistBilledFrom) { var stores = new Stores(session).Extent(); stores.Filter.AddEquals(M.Store.InternalOrganisation, this.BilledFrom); this.Store = stores.FirstOrDefault(); } if (!this.ExistInvoiceNumber && this.ExistStore) { this.InvoiceNumber = this.Store.NextTemporaryInvoiceNumber(); } if (!this.ExistBilledFromContactMechanism && this.ExistBilledFrom) { this.BilledFromContactMechanism = this.BilledFrom.ExistBillingAddress ? this.BilledFrom.BillingAddress : this.BilledFrom.GeneralCorrespondence; } if (!this.ExistBillToContactMechanism && this.ExistBillToCustomer) { this.BillToContactMechanism = this.BillToCustomer.BillingAddress; } if (!this.ExistBillToEndCustomerContactMechanism && this.ExistBillToEndCustomer) { this.BillToEndCustomerContactMechanism = this.BillToEndCustomer.BillingAddress; } if (!this.ExistShipToEndCustomerAddress && this.ExistShipToEndCustomer) { this.ShipToEndCustomerAddress = this.ShipToEndCustomer.ShippingAddress; } if (!this.ExistShipToAddress && this.ExistShipToCustomer) { this.ShipToAddress = this.ShipToCustomer.ShippingAddress; } if (!this.ExistCurrency && this.ExistBilledFrom) { if (this.ExistBillToCustomer && (this.BillToCustomer.ExistPreferredCurrency || this.BillToCustomer.ExistLocale)) { this.Currency = this.BillToCustomer.ExistPreferredCurrency ? this.BillToCustomer.PreferredCurrency : this.BillToCustomer.Locale.Country.Currency; } else { this.Currency = this.BilledFrom.ExistPreferredCurrency ? this.BilledFrom.PreferredCurrency : session.GetSingleton().DefaultLocale.Country.Currency; } } this.VatRegime = this.VatRegime ?? this.BillToCustomer?.VatRegime; this.IsRepeating = this.ExistRepeatingSalesInvoiceWhereSource; foreach (SalesInvoiceItem salesInvoiceItem in this.SalesInvoiceItems) { foreach (OrderItemBilling orderItemBilling in salesInvoiceItem.OrderItemBillingsWhereInvoiceItem) { if (orderItemBilling.OrderItem is SalesOrderItem salesOrderItem && !this.SalesOrders.Contains(salesOrderItem.SalesOrderWhereSalesOrderItem)) { this.AddSalesOrder(salesOrderItem.SalesOrderWhereSalesOrderItem); } } foreach (WorkEffortBilling workEffortBilling in salesInvoiceItem.WorkEffortBillingsWhereInvoiceItem) { if (!this.WorkEfforts.Contains(workEffortBilling.WorkEffort)) { this.AddWorkEffort(workEffortBilling.WorkEffort); } } foreach (TimeEntryBilling timeEntryBilling in salesInvoiceItem.TimeEntryBillingsWhereInvoiceItem) { if (!this.WorkEfforts.Contains(timeEntryBilling.TimeEntry.WorkEffort)) { this.AddWorkEffort(timeEntryBilling.TimeEntry.WorkEffort); } } } this.IsRepeatingInvoice = this.ExistRepeatingSalesInvoiceWhereSource && (!this.RepeatingSalesInvoiceWhereSource.ExistFinalExecutionDate || this.RepeatingSalesInvoiceWhereSource.FinalExecutionDate.Value.Date >= this.Strategy.Session.Now().Date); this.SalesInvoiceItems = this.SalesInvoiceItems.ToArray(); if (this.ExistBillToCustomer && this.BillToCustomer.ExistLocale) { this.Locale = this.BillToCustomer.Locale; } else { this.Locale = session.GetSingleton().DefaultLocale; } if (this.ExistSalesTerms) { foreach (AgreementTerm term in this.SalesTerms) { if (term.TermType.Equals(new InvoiceTermTypes(session).PaymentNetDays)) { if (int.TryParse(term.TermValue, out var netDays)) { this.PaymentDays = netDays; } } } } else if (this.BillToCustomer?.PaymentNetDays().HasValue == true) { this.PaymentDays = this.BillToCustomer.PaymentNetDays().Value; } else if (this.ExistStore && this.Store.ExistPaymentNetDays) { this.PaymentDays = this.Store.PaymentNetDays; } if (!this.ExistPaymentDays) { this.PaymentDays = 0; } if (this.ExistInvoiceDate) { this.DueDate = this.InvoiceDate.AddDays(this.PaymentNetDays); } var validInvoiceItems = this.SalesInvoiceItems.Where(v => v.IsValid).ToArray(); this.ValidInvoiceItems = validInvoiceItems; var currentPriceComponents = new PriceComponents(this.Strategy.Session).CurrentPriceComponents(this.InvoiceDate); var quantityByProduct = validInvoiceItems .Where(v => v.ExistProduct) .GroupBy(v => v.Product) .ToDictionary(v => v.Key, v => v.Sum(w => w.Quantity)); // First run to calculate price foreach (var salesInvoiceItem in validInvoiceItems) { decimal quantityOrdered = 0; if (salesInvoiceItem.ExistProduct) { quantityByProduct.TryGetValue(salesInvoiceItem.Product, out quantityOrdered); } this.CalculatePrices(derivation, salesInvoiceItem, currentPriceComponents, quantityOrdered, 0); } var totalBasePriceByProduct = validInvoiceItems .Where(v => v.ExistProduct) .GroupBy(v => v.Product) .ToDictionary(v => v.Key, v => v.Sum(w => w.TotalBasePrice)); // Second run to calculate price (because of order value break) foreach (var salesInvoiceItem in validInvoiceItems) { decimal quantityOrdered = 0; decimal totalBasePrice = 0; if (salesInvoiceItem.ExistProduct) { quantityByProduct.TryGetValue(salesInvoiceItem.Product, out quantityOrdered); totalBasePriceByProduct.TryGetValue(salesInvoiceItem.Product, out totalBasePrice); } this.CalculatePrices(derivation, salesInvoiceItem, currentPriceComponents, quantityOrdered, totalBasePrice); } // Calculate Totals if (this.ExistSalesInvoiceItems) { this.TotalBasePrice = 0; this.TotalDiscount = 0; this.TotalSurcharge = 0; this.TotalExVat = 0; this.TotalFee = 0; this.TotalShippingAndHandling = 0; this.TotalVat = 0; this.TotalIncVat = 0; this.TotalListPrice = 0; foreach (var item in validInvoiceItems) { this.TotalBasePrice += item.TotalBasePrice; this.TotalDiscount += item.TotalDiscount; this.TotalSurcharge += item.TotalSurcharge; this.TotalExVat += item.TotalExVat; this.TotalVat += item.TotalVat; this.TotalIncVat += item.TotalIncVat; this.TotalListPrice += item.UnitPrice; } if (this.ExistDiscountAdjustment) { var discount = this.DiscountAdjustment.Percentage.HasValue ? Math.Round(this.TotalExVat * this.DiscountAdjustment.Percentage.Value / 100, 2) : this.DiscountAdjustment.Amount ?? 0; this.TotalDiscount += discount; this.TotalExVat -= discount; if (this.ExistVatRegime) { var vat = Math.Round(discount * this.VatRegime.VatRate.Rate / 100, 2); this.TotalVat -= vat; this.TotalIncVat -= discount + vat; } } if (this.ExistSurchargeAdjustment) { var surcharge = this.SurchargeAdjustment.Percentage.HasValue ? Math.Round(this.TotalExVat * this.SurchargeAdjustment.Percentage.Value / 100, 2) : this.SurchargeAdjustment.Amount ?? 0; this.TotalSurcharge += surcharge; this.TotalExVat += surcharge; if (this.ExistVatRegime) { var vat = Math.Round(surcharge * this.VatRegime.VatRate.Rate / 100, 2); this.TotalVat += vat; this.TotalIncVat += surcharge + vat; } } if (this.ExistFee) { var fee = this.Fee.Percentage.HasValue ? Math.Round(this.TotalExVat * this.Fee.Percentage.Value / 100, 2) : this.Fee.Amount ?? 0; this.TotalFee += fee; this.TotalExVat += fee; if (this.Fee.ExistVatRate) { var vat1 = Math.Round(fee * this.Fee.VatRate.Rate / 100, 2); this.TotalVat += vat1; this.TotalIncVat += fee + vat1; } } if (this.ExistShippingAndHandlingCharge) { var shipping = this.ShippingAndHandlingCharge.Percentage.HasValue ? Math.Round(this.TotalExVat * this.ShippingAndHandlingCharge.Percentage.Value / 100, 2) : this.ShippingAndHandlingCharge.Amount ?? 0; this.TotalShippingAndHandling += shipping; this.TotalExVat += shipping; if (this.ShippingAndHandlingCharge.ExistVatRate) { var vat2 = Math.Round(shipping * this.ShippingAndHandlingCharge.VatRate.Rate / 100, 2); this.TotalVat += vat2; this.TotalIncVat += shipping + vat2; } } //// Only take into account items for which there is data at the item level. //// Skip negative sales. decimal totalUnitBasePrice = 0; decimal totalListPrice = 0; foreach (var item1 in validInvoiceItems) { if (item1.TotalExVat > 0) { totalUnitBasePrice += item1.UnitBasePrice; totalListPrice += item1.UnitPrice; } } } var salesInvoiceItemStates = new SalesInvoiceItemStates(derivation.Session); var salesInvoiceStates = new SalesInvoiceStates(derivation.Session); foreach (var invoiceItem in validInvoiceItems) { if (!invoiceItem.SalesInvoiceItemState.Equals(salesInvoiceItemStates.ReadyForPosting)) { if (invoiceItem.AmountPaid == 0) { invoiceItem.SalesInvoiceItemState = salesInvoiceItemStates.NotPaid; } else if (invoiceItem.ExistAmountPaid && invoiceItem.AmountPaid > 0 && invoiceItem.AmountPaid >= invoiceItem.TotalIncVat) { invoiceItem.SalesInvoiceItemState = salesInvoiceItemStates.Paid; } else { invoiceItem.SalesInvoiceItemState = salesInvoiceItemStates.PartiallyPaid; } } } if (validInvoiceItems.Any() && !this.SalesInvoiceState.Equals(salesInvoiceStates.ReadyForPosting)) { if (this.SalesInvoiceItems.All(v => v.SalesInvoiceItemState.IsPaid)) { this.SalesInvoiceState = salesInvoiceStates.Paid; } else if (this.SalesInvoiceItems.All(v => v.SalesInvoiceItemState.IsNotPaid)) { this.SalesInvoiceState = salesInvoiceStates.NotPaid; } else { this.SalesInvoiceState = salesInvoiceStates.PartiallyPaid; } } this.AmountPaid = this.AdvancePayment; this.AmountPaid += this.PaymentApplicationsWhereInvoice.Sum(v => v.AmountApplied); //// Perhaps payments are recorded at the item level. if (this.AmountPaid == 0) { this.AmountPaid = this.InvoiceItems.Sum(v => v.AmountPaid); } // If receipts are not matched at invoice level if (this.AmountPaid > 0) { if (this.AmountPaid >= this.TotalIncVat) { this.SalesInvoiceState = salesInvoiceStates.Paid; } else { this.SalesInvoiceState = salesInvoiceStates.PartiallyPaid; } foreach (var invoiceItem in validInvoiceItems) { if (!invoiceItem.SalesInvoiceItemState.Equals(salesInvoiceItemStates.CancelledByInvoice) && !invoiceItem.SalesInvoiceItemState.Equals(salesInvoiceItemStates.WrittenOff)) { if (this.AmountPaid >= this.TotalIncVat) { invoiceItem.SalesInvoiceItemState = salesInvoiceItemStates.Paid; } else { invoiceItem.SalesInvoiceItemState = salesInvoiceItemStates.PartiallyPaid; } } } } if (this.ExistVatRegime && this.VatRegime.ExistVatClause) { this.DerivedVatClause = this.VatRegime.VatClause; } else { if (Equals(this.VatRegime, new VatRegimes(session).ServiceB2B)) { this.DerivedVatClause = new VatClauses(session).ServiceB2B; } else if (Equals(this.VatRegime, new VatRegimes(session).IntraCommunautair)) { this.DerivedVatClause = new VatClauses(session).Intracommunautair; } } this.DerivedVatClause = this.ExistAssignedVatClause ? this.AssignedVatClause : this.DerivedVatClause; this.BaseOnDeriveCustomers(derivation); if (this.ExistBillToCustomer && !this.BillToCustomer.BaseIsActiveCustomer(this.BilledFrom, this.InvoiceDate)) { derivation.Validation.AddError(this, M.SalesInvoice.BillToCustomer, ErrorMessages.PartyIsNotACustomer); } if (this.ExistShipToCustomer && !this.ShipToCustomer.BaseIsActiveCustomer(this.BilledFrom, this.InvoiceDate)) { derivation.Validation.AddError(this, M.SalesInvoice.ShipToCustomer, ErrorMessages.PartyIsNotACustomer); } this.PreviousBillToCustomer = this.BillToCustomer; this.PreviousShipToCustomer = this.ShipToCustomer; // this.BaseOnDeriveRevenues(derivation); var singleton = this.Session().GetSingleton(); this.AddSecurityToken(new SecurityTokens(this.Session()).DefaultSecurityToken); this.Sync(this.Session()); this.ResetPrintDocument(); }