From b027fd5f5b017bd576d8a256eec8f86cb2828fc4 Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Fri, 8 Nov 2024 11:29:41 +0100 Subject: [PATCH 01/18] Added RC release notes --- .../release-notes/v14.0.0-alpha.md | 179 ------------------ 15/umbraco-commerce/release-notes/v14.0.0.md | 125 ------------ .../release-notes/v15.0.0-rc.md | 81 ++++++++ 3 files changed, 81 insertions(+), 304 deletions(-) delete mode 100644 15/umbraco-commerce/release-notes/v14.0.0-alpha.md delete mode 100644 15/umbraco-commerce/release-notes/v14.0.0.md create mode 100644 15/umbraco-commerce/release-notes/v15.0.0-rc.md diff --git a/15/umbraco-commerce/release-notes/v14.0.0-alpha.md b/15/umbraco-commerce/release-notes/v14.0.0-alpha.md deleted file mode 100644 index 947f4d5e938..00000000000 --- a/15/umbraco-commerce/release-notes/v14.0.0-alpha.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -description: >- - Umbraco Commerce v14.0.0-Alpha release notes. ---- - -# Umbraco Commerce v14.0.0-Alpha - -Umbraco Commerce v14.0.0-Alpha is the initial release of Umbraco Commerce for Umbraco CMS v14. Being an alpha, this is an early preview of the Umbraco Commerce product and as such should be considered a work in progress. - -## Key Takeaways - -* Contains [core functionality](#core-functionality) for store setup, order management and key property editors. -* Some [functionality / sections missing](#missing-features). -* Some [breaking changes](#breaking-changes) to be expected. -* Brand new [Management API](#management-api). -* New more flexible [UI extension points](#ui-extension-points) added. -* [Localization](#localization) support added (in progress). - -## Core Functionality - -The key focus of this alpha release is to provide the core functionality required to be able to setup and run a store in Umbraco Commerce allowing users to get started on v14 right away. - -![Umbraco Commerce v14 Order Editor](../media/v14/order-editor.png) - -![Umbraco Commerce v14 Settings Section](../media/v14/store-settings.png) - -The key features included in this release are: - -* Store Creation / Editing -* Location Creation / Editing -* Order Status Creation / Editing -* Payment Method Creation / Editing -* Shipping Method Creation / Editing -* Country & Region Creation / Editing -* Currency Creation / Editing -* Tax Class Creation / Editing -* Email Template Creation / Editing -* Print Template Creation / Editing -* Export Template Creation / Editing -* Order View / Editing -* Order / Order Line Properties Editing - -## Missing Features - -Within these sections there are some known missing features: - -* Missing text filtering on collection views -* Missing bulk operations implementation -* Missing sort functionality -* Missing advanced order searching -* Missing order filter menus - -In addition to these, there are also some complete sections currently outstanding: - -* Store overview dashboard -* Cart section -* Discounts section -* Gift cards section -* Analytics section -* Product Attributes + Product Attribute Presets section - -Lastly, there is also some property editors still yet to implement: - -* Variants - -Needless to say, these will all be implemented for the final v14 release, but in order to get a usable Umbraco Commerce product into your hands as quickly as possible, these features / sections were put at lower priorities at this stage of the conversion. - -## Breaking Changes - -With the new backoffice UI, there has inevitably been the need to change some functionalities and use such breaking changes couldn't be avoided. These have tried to be minimized as much as possible, whilst also ensuring we embrace the new front end architecture to it's fullest. - -The key breaking changes to expect are: - -* **UI Config Files Remove** - - In previous versions of Umbraco Commerce it was possible to configure the back office order list view, order editor and analytics dashboards using JSON UI config files. These have now all been updated to use the new manifests pattern in Umbraco v14. See the [UI Extension Points](#ui-extension-points) section bellow for more details. - - In addition to this, the UI Config Files were also used in the backoffice to extract key order properties for things like extracting the shipping address in order to calculate shipping rates. This functionality has now been split such that this mapping functionality has now moved to a new server based configuration API. - - ``` - builder.WithOrderPropertyConfigs() - .Add("myStoreAlias", b => b - .For(x => x.Customer.FirstName).MapFrom("firstName") - .For(x => x.Customer.LastName).MapFrom("lastName") - ... - ); - ``` - -* **Web Notification Events Removed** - - The following notifications are no longer being fired. - - * `AnalyticsDashboardConfigParsingNotification` - * `CartEditorConfigParsingNotification` - * `OrderEditorConfigParsingNotification` - * `StoreActionsRenderingNotification` - * `ActivityLogEntriesRenderingNotification` - -* **Web Controllers / Models Removed** - - With the new Management API this does mean any controllers / models that previously lived in the `Umbraco.Commerce.Cms.Web` will now have been removed. Please use the Management API instead. - - The only exception to this is the `PaymentController` which is used as a callback for payment gateways. This is currently kept at the same URL to prevent breakages. We will be reviewing this to see if some other endpoint location makes more sense. - -## UI Extension Points - -With the new backoffice comes a new extensions system for the UI and we have tried to use this to the maximum. These means converting the old UI configs system to using the new manifests system. - -With the new extension points it is possible to: - -* Change the properties used by the order editor. -* Add properties to the order line properties editor. -* Add properties to the Notes, Additional Info and Customer Details modals. -* Add properties to the order collection view. -* Add analytics widgets (still in progress) -* Define custom views for properties to control value rendering. - -Here is an example of how you would configure such properties - -```javascript -export const manifests : Array = [ - { - type: 'ucOrderLineProperty', - alias: 'Uc.OrderLineProperty.Color', - name: 'Order Line Color', - weight: 100, - meta: { - propertyAlias: 'color', - editorUiAlias: 'Umb.PropertyEditorUi.EyeDropper', - labelElementName: 'uc-mini-color-swatch' - } - }, - { - type: 'ucOrderLineProperty', - alias: 'Uc.OrderLineProperty.GiftMessage', - name: 'Order Line Gift Message', - weight: 100, - meta: { - propertyAlias: 'giftMessage', - editorUiAlias: 'Umb.PropertyEditorUi.TextArea', - summaryStyle: 'table' - } - } -]; -``` - -With these extension points, the Umbraco Commerce order editor is now more flexible than it has ever been before. - -{% hint style="info" %} -We are yet to launch an Umbraco Commerce NPM module so these points are not yet currently available to use externally but we wanted to give you a heads up of what is coming so you can prepare. -{% endhint %} - -## Management API - -As with the CMS, with the new UI comes a whole new API layer. - -![Umbraco Commerce Management API](../media/v14/management-api.png) - -With the Umbraco Commerce API we have aimed to keep it aligned with the Storefront API with support for filtering an expansion where possible. - -I key thought whilst developing this API has been to ensure external developers might use this to build other UI's for Umbraco Commerce such as a dedicated mobile app and so we've tried to ensure there are no "special" endpoints just for the Umbraco CMS UI. - -## Localization - -One of the things that has been on the Umbraco Commerce TODO list for a while is to add backoffice localization support. Given the fresh start it was only logical that we take the time to ensure that everything we built fully supported localization so this will be included in this release. - -We haven't quite caught everything yet, but we'll be sure to do a full check before the final release to ensure all hard coded strings are fully configurable. - -With this update, we'll also be making some changes to things like payment and shipping providers, and other CSharp extension points where we define properties. These will no longer require hard coded labels / descriptions and instead will look these values up from the localization file. - -## Add-on Updates - -We are still yet to tackle adding v14 support to the **Umbraco.Commerce.Deploy** and **Umbraco.Commerce.Checkout** add-ons so these are currently unavailable. These will likely be made available after the initial v14 release. - -## What to Test and How to Give Feedback - -We would welcome feedback on any installation / upgrade issues along with bugs found in any of the completed sections as detailed above. - -Issues can be raised on the Umbraco Commerce issue tracker at [https://github.com/umbraco/Umbraco.Commerce.Issues/issues](https://github.com/umbraco/Umbraco.Commerce.Issues/issues). diff --git a/15/umbraco-commerce/release-notes/v14.0.0.md b/15/umbraco-commerce/release-notes/v14.0.0.md deleted file mode 100644 index 786314c3ef4..00000000000 --- a/15/umbraco-commerce/release-notes/v14.0.0.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -description: >- - Umbraco Commerce v14.0.0 release notes. ---- - -# Umbraco Commerce v14.0.0 - -This release marks the v14 build of Umbraco Commerce, now feature complete and ready for developers to start using it. - -## Key Takeaways - -* [New backoffice UI](#new-backoffice-ui) build with web-components. -* Some [breaking changes](#breaking-changes) to be expected. -* New more flexible [UI extension points](#ui-extension-points) added. -* New [Management API](#management-api) added. -* [Localization](#localization) support added (in progress). - -## New Backoffice UI - -As with everything v14, this is a complete rebuild of the backoffice UI using web components. This ensures Umbraco Commerce is set for the future and creates a solid foundation to develop new features and functionality. - -![Umbraco Commerce v14 Order Editor](../media/v14/order-editor.png) - -![Umbraco Commerce v14 Settings Section](../media/v14/store-settings.png) - -## Breaking Changes - -With the new backoffice UI, there has inevitably been the need to change some functionalities, and as such breaking changes could not be avoided. These have tried to be minimized as much as possible, whilst also ensuring we embrace the new front-end architecture to its fullest. - -The key breaking changes to expect are: - -* **UI Config Files Removed** - -Previously, in Umbraco Commerce, it was possible to configure the backoffice order list view, order editor, and analytics dashboards using JSON UI config files. These have now all been updated to use the new manifests pattern in Umbraco v14. For more details, see the [UI Extension Points](#ui-extension-points) section below. - -In addition to this, the UI config files were also used in the backoffice to extract key order properties. For example, extracting the shipping address to calculate shipping rates. This functionality has now been split, and the mapping functionality has been moved to a new server-based configuration API. - - ``` - builder.WithOrderPropertyConfigs() - .Add("myStoreAlias", b => b - .For(x => x.Customer.FirstName).MapFrom("firstName") - .For(x => x.Customer.LastName).MapFrom("lastName") - ... - ); - ``` - -* **Web Notification Events Removed** - - The following notifications are no longer being fired: - - * `AnalyticsDashboardConfigParsingNotification` - * `CartEditorConfigParsingNotification` - * `OrderEditorConfigParsingNotification` - * `StoreActionsRenderingNotification` - * `ActivityLogEntriesRenderingNotification` - -* **Web Controllers/Models Removed** - - With the new Management API, any controllers or models previously located in `Umbraco.Commerce.Cms.Web` have been removed. Please use the **Management API** instead. - -The only exception to this rule is the `PaymentController`, which serves as a callback for payment gateways. It is currently located at the same URL to avoid disrupting existing transaction communications. However, all new integrations should communicate with a new Payments API. - -## UI Extension Points - -With the new backoffice comes a new extensions system for the UI, and we have tried to maximize its use. This means converting the old UI configs system to use the new manifests system. - -With the new extension points it is possible to: - -* Change the properties used by the order editor. -* Add properties to the order line properties editor. -* Add properties to the Notes, Additional Info, and Customer Details modals. -* Add properties to the order collection view. -* Add analytics widgets (still in progress) -* Define custom views for properties to control value rendering. - -Here is an example of how you would configure these properties: - -```javascript -export const manifests : Array = [ - { - type: 'ucOrderLineProperty', - alias: 'Uc.OrderLineProperty.Color', - name: 'Order Line Color', - weight: 100, - meta: { - propertyAlias: 'color', - editorUiAlias: 'Umb.PropertyEditorUi.EyeDropper', - labelElementName: 'uc-mini-color-swatch' - } - }, - { - type: 'ucOrderLineProperty', - alias: 'Uc.OrderLineProperty.GiftMessage', - name: 'Order Line Gift Message', - weight: 100, - meta: { - propertyAlias: 'giftMessage', - editorUiAlias: 'Umb.PropertyEditorUi.TextArea', - summaryStyle: 'table' - } - } -]; -``` - -With these extension points, the Umbraco Commerce order editor is now more flexible than it has ever been before. - -{% hint style="info" %} -We are yet to launch an Umbraco Commerce NPM module, so these functionalities are not currently available for external use. However, we wanted to give you a heads-up about what is coming so you can prepare. -{% endhint %} - -## Management API - -With the new UI, a new API layer is also introduced, similar to the CMS. - -![Umbraco Commerce Management API](../media/v14/management-api.png) - -With the Umbraco Commerce API, we have aimed to keep it aligned with the Storefront API with support for filtering and expansion where possible. - -We developed this API for external developers who can use it to create different UIs for Umbraco Commerce, such as a dedicated mobile app. We have made sure that there are no "special" endpoints exclusively for the Umbraco CMS UI. - -## Localization - -Given the fresh start, we made sure that everything we built fully supports localization, so this will be included in this release. - -In this update, we have made some changes to payment and shipping providers, as well as other CSharp extension points where properties are defined. These changes mean that labels and descriptions will no longer be hard-coded; instead, the values will be looked up from the localization file. diff --git a/15/umbraco-commerce/release-notes/v15.0.0-rc.md b/15/umbraco-commerce/release-notes/v15.0.0-rc.md new file mode 100644 index 00000000000..9fb799ac587 --- /dev/null +++ b/15/umbraco-commerce/release-notes/v15.0.0-rc.md @@ -0,0 +1,81 @@ +--- +description: >- + Umbraco Commerce v15.0.0-rc release notes. +--- + +# Umbraco Commerce v15.0.0-rc + +Umbraco Commerce v15.0.0-rc is the initial release of Umbraco Commerce for Umbraco CMS v15. Because of + +## Key Takeaways + +* Everything is now [async](#async). +* [Storefront API](#storefront-api) aligned with Management API +* A number of [Umbraco v15 updates](#umbraco-v15-updates). + +## Async + +The key focus of this release is the move to a fully asyncronus code base. In order to reduce the maintenance burden, the decision was made to go fully async without maintaining backwards compatibility. This will therfore require code updates to use the new async methods. + +### Previous behavior +Previously all C# API's were synchronous and thus blocking by nature. + +```csharp + // Fluent API example + order.AddProduct(productRef, 1) + .SetPaymentMethod(paymentMethodId) + .SetShippingMethod(shippingMethodId); + + // Service method examples + orderService.SaveOrder(order); + emailTemplateService.SendEmail(emailTemplateId, order); + + // Notification events + public class MyNotification : NotificationEventHandlerBase + { + public override void Handle(OrderFinalizedNotification evt) + { + // Implement your custom logic here + } + } +``` + +### New behavior +All API's are now asynchronous and thus are suffixed with Async and return a Task result + + // Fluent API example + await order.AddProductAsync(productRef, 1) + .SetPaymentMethodAsync(paymentMethodId) + .SetShippingMethodAsync(shippingMethodId); + + // Service method examples + await orderService.SaveOrderAsync(order); + await emailTemplateService.SendEmailAsync(emailTemplateId, order); + + // Notification events + public class MyNotification : NotificationEventHandlerBase + { + public override Task HandleAsync(OrderFinalizedNotification evt, CancelationToken cancelationToken) + { + // Implement your custom logic here + } + } + +## Storefront API + +When implementing the Management API in v14 we learnt a lot about API structure, and also found some common models between the Management API and the Storefront API. To aid with maintenance, and align approaches, the Storefront API was updated to similar patterns. + +For the most part the API should stay the same, the key different being changes in operation IDs allowing the Storefront API to be used with client generators. + +## Umbraco v15 updates + +As well as the async works, Umbraco Commerce v15 has also been updated to depend on Umbraco v15 which consists of the following updates. + +* Runs against .NET 9 +* Variants property editor supports content variants + +## What to Test and How to Give Feedback + +We would welcome feedback on any installation / upgrade issues along with bugs found in any of the completed sections as detailed above. + +Issues can be raised on the Umbraco Commerce issue tracker at [https://github.com/umbraco/Umbraco.Commerce.Issues/issues](https://github.com/umbraco/Umbraco.Commerce.Issues/issues). From 71a9452763eebc76399cbb70b9102c0004c4951e Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Fri, 8 Nov 2024 11:30:04 +0100 Subject: [PATCH 02/18] Fixed code snippets --- .../release-notes/v15.0.0-rc.md | 62 ++++++++++--------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/15/umbraco-commerce/release-notes/v15.0.0-rc.md b/15/umbraco-commerce/release-notes/v15.0.0-rc.md index 9fb799ac587..3ebccb6b682 100644 --- a/15/umbraco-commerce/release-notes/v15.0.0-rc.md +++ b/15/umbraco-commerce/release-notes/v15.0.0-rc.md @@ -21,45 +21,47 @@ The key focus of this release is the move to a fully asyncronus code base. In or Previously all C# API's were synchronous and thus blocking by nature. ```csharp - // Fluent API example - order.AddProduct(productRef, 1) - .SetPaymentMethod(paymentMethodId) - .SetShippingMethod(shippingMethodId); - - // Service method examples - orderService.SaveOrder(order); - emailTemplateService.SendEmail(emailTemplateId, order); - - // Notification events - public class MyNotification : NotificationEventHandlerBase +// Fluent API example +order.AddProduct(productRef, 1) + .SetPaymentMethod(paymentMethodId) + .SetShippingMethod(shippingMethodId); + +// Service method examples +orderService.SaveOrder(order); +emailTemplateService.SendEmail(emailTemplateId, order); + +// Notification events +public class MyNotification : NotificationEventHandlerBase +{ + public override void Handle(OrderFinalizedNotification evt) { - public override void Handle(OrderFinalizedNotification evt) - { - // Implement your custom logic here - } + // Implement your custom logic here } +} ``` ### New behavior All API's are now asynchronous and thus are suffixed with Async and return a Task result - // Fluent API example - await order.AddProductAsync(productRef, 1) - .SetPaymentMethodAsync(paymentMethodId) - .SetShippingMethodAsync(shippingMethodId); - - // Service method examples - await orderService.SaveOrderAsync(order); - await emailTemplateService.SendEmailAsync(emailTemplateId, order); - - // Notification events - public class MyNotification : NotificationEventHandlerBase +```csharp +// Fluent API example +await order.AddProductAsync(productRef, 1) + .SetPaymentMethodAsync(paymentMethodId) + .SetShippingMethodAsync(shippingMethodId); + +// Service method examples +await orderService.SaveOrderAsync(order); +await emailTemplateService.SendEmailAsync(emailTemplateId, order); + +// Notification events +public class MyNotification : NotificationEventHandlerBase +{ + public override Task HandleAsync(OrderFinalizedNotification evt, CancelationToken cancelationToken) { - public override Task HandleAsync(OrderFinalizedNotification evt, CancelationToken cancelationToken) - { - // Implement your custom logic here - } + // Implement your custom logic here } +} +``` ## Storefront API From 0a2de700e25afb1d28a657901d5323ba8b7861f0 Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Fri, 8 Nov 2024 12:29:55 +0100 Subject: [PATCH 03/18] Updated key concepts to async --- 15/umbraco-commerce/SUMMARY.md | 72 +++++++++++++++- .../getting-started/requirements.md | 4 +- .../key-concepts/calculators.md | 4 +- .../discount-rules-and-rewards.md | 6 +- .../key-concepts/fluent-api.md | 24 +++--- .../key-concepts/payment-providers.md | 14 ++-- 15/umbraco-commerce/key-concepts/pipelines.md | 4 +- .../key-concepts/price-amount-adjustments.md | 2 +- .../key-concepts/price-freezing.md | 6 +- .../key-concepts/product-adapters.md | 16 ++-- .../key-concepts/product-bundles.md | 8 +- .../key-concepts/properties.md | 10 +-- .../readonly-and-writable-entities.md | 16 ++-- ...xt-providers.md => sales-tax-providers.md} | 0 .../key-concepts/search-specifications.md | 4 +- .../shipping-package-factories.md | 4 +- .../shipping-range-and-rate-providers.md | 8 +- .../key-concepts/unit-of-work.md | 34 ++++---- 15/umbraco-commerce/release-notes/README.md | 84 +------------------ 19 files changed, 155 insertions(+), 165 deletions(-) rename 15/umbraco-commerce/key-concepts/{sales-taxt-providers.md => sales-tax-providers.md} (100%) diff --git a/15/umbraco-commerce/SUMMARY.md b/15/umbraco-commerce/SUMMARY.md index f541dd6068c..f0fc2425e01 100644 --- a/15/umbraco-commerce/SUMMARY.md +++ b/15/umbraco-commerce/SUMMARY.md @@ -2,8 +2,7 @@ * [Umbraco Commerce Documentation](README.md) * [Release Notes](release-notes/README.md) - * [v14.0.0](release-notes/v14.0.0.md) - * [v14.0.0-Alpha](release-notes/v14.0.0-alpha.md) + * [v15.0.0-Rc](release-notes/v15.0.0-rc.md) ## Commerce Products @@ -15,23 +14,92 @@ * [Requirements](getting-started/requirements.md) * [Installation](getting-started/install.md) +* [Licensing](getting-started/the-licensing-model.md) +* [Configuration](getting-started/umbraco-configuration.md) +* [User Interface](getting-started/user-interface.md) ## Upgrading * [Upgrading Umbraco Commerce](upgrading/upgrade.md) * [Version Specific Upgrade Notes](upgrading/version-specific-upgrades.md) +* [Migrate from Vendr to Umbraco Commerce](upgrading/migrate-from-vendr-to-umbraco-commerce/README.md) + * [Migrate Umbraco Commerce Checkout](upgrading/migrate-from-vendr-to-umbraco-commerce/migrate-umbraco-commerce-checkout.md) + * [Migrate custom Payment Providers](upgrading/migrate-from-vendr-to-umbraco-commerce/migrate-custom-payment-providers.md) ## How-To Guides * [Overview](how-to-guides/overview.md) +* [Configure SQLite support](how-to-guides/configure-sqlite-support.md) +* [Limit Order Line Quantity](how-to-guides/limit-orderline-quantity.md) +* [Use an Alternative Database for Umbraco Commerce Tables](how-to-guides/use-an-alternative-database-for-umbraco-commerce-tables.md) ## Key Concepts * [Get to know the main features](key-concepts/overview.md) +* [Base Currency](key-concepts/base-currency.md) +* [Calculators](key-concepts/calculators.md) +* [Currency Exchange Rate Service Provider](key-concepts/currency-exchange-rate-service-providers.md) +* [Dependency Injection](key-concepts/dependency-injection.md) +* [Discount Rules / Rewards](key-concepts/discount-rules-and-rewards.md) +* [Events](key-concepts/events/README.md) + * [List of validation events](key-concepts/events/list-of-validation-events.md) + * [List of notification events](key-concepts/events/list-of-notification-events.md) +* [Fluent API](key-concepts/fluent-api.md) +* [Order Calculation State](key-concepts/order-calculation-state.md) +* [Payment Forms](key-concepts/payment-forms.md) +* [Payment Providers](key-concepts/payment-providers.md) +* [Pipelines](key-concepts/pipelines.md) +* [Price/Amount Adjustments](key-concepts/price-amount-adjustments.md) +* [Price Freezing](key-concepts/price-freezing.md) +* [Product Adapters](key-concepts/product-adapters.md) +* [Product Bundles](key-concepts/product-bundles.md) +* [Product Variants](key-concepts/product-variants/README.md) + * [Complex Variants](key-concepts/product-variants/complex-variants.md) +* [Properties](key-concepts/properties.md) +* [ReadOnly and Writable Entities](key-concepts/readonly-and-writable-entities.md) +* [Sales Tax Providers](key-concepts/sales-tax-providers.md) +* [Search Specifications](key-concepts/search-specifications.md) +* [Settings Objects](key-concepts/settings-objects.md) +* [Shipping Package Factories](key-concepts/shipping-package-factories.md) +* [Shipping Providers](key-concepts/shipping-providers.md) +* [Shipping Range/Rate Providers](key-concepts/shipping-range-and-rate-providers.md) +* [Tax Sources](key-concepts/tax-sources.md) +* [UI Extensions](key-concepts/ui-extensions/README.md) + * [Analytics Widgets](key-concepts/ui-extensions/analytics-widgets.md) + * [Entity Quick Actions](key-concepts/ui-extensions/entity-quick-actions.md) + * [Order Properties](key-concepts/ui-extensions/order-properties.md) + * [Order Collection Properties](key-concepts/ui-extensions/order-collection-properties.md) + * [Order Line Properties](key-concepts/ui-extensions/order-line-properties.md) + * [Store Menu Items](key-concepts/ui-extensions/store-menu-items.md) +* [Umbraco Properties](key-concepts/umbraco-properties.md) +* [Unit of Work](key-concepts/unit-of-work.md) +* [Umbraco Commerce Builder](key-concepts/umbraco-commerce-builder.md) +* [Webhooks](key-concepts/webhooks.md) ## Reference * [Stores](reference/stores/README.md) +* [Shipping](reference/shipping/README.md) + * [Fixed Rate Shipping](reference/shipping/fixed-rate-shipping.md) + * [Dynamic Rate Shipping](reference/shipping/dynamic-rate-shipping.md) + * [Realtime Rate Shipping](reference/shipping/realtime-rate-shipping.md) +* [Taxes](reference/taxes/README.md) + * [Fixed Tax Rates](reference/taxes/fixed-tax-rates.md) + * [Calculated Tax Rates](reference/taxes/calculated-tax-rates.md) +* [Storefront API](reference/storefront-api/README.md) + * [Endpoints](reference/storefront-api/endpoints/README.md) + * [Order](reference/storefront-api/endpoints/order.md) + * [Checkout](reference/storefront-api/endpoints/checkout.md) + * [Product](reference/storefront-api/endpoints/product.md) + * [Customer](reference/storefront-api/endpoints/customer.md) + * [Store](reference/storefront-api/endpoints/store.md) + * [Currency](reference/storefront-api/endpoints/currency.md) + * [Country](reference/storefront-api/endpoints/country.md) + * [Payment method](reference/storefront-api/endpoints/payment-method.md) + * [Shipping method](reference/storefront-api/endpoints/shipping-method.md) + * [Content](reference/storefront-api/endpoints/content.md) +* [Management API](reference/management-api/README.md) +* [Go behind the scenes](reference/go-behind-the-scenes.md) ## Tutorials diff --git a/15/umbraco-commerce/getting-started/requirements.md b/15/umbraco-commerce/getting-started/requirements.md index 51b3d636f50..a4ee3439e88 100644 --- a/15/umbraco-commerce/getting-started/requirements.md +++ b/15/umbraco-commerce/getting-started/requirements.md @@ -6,7 +6,7 @@ description: Getting Started with Umbraco Commerce. In this article, you will find the key steps needed to get started with Umbraco Commerce. -It is assumed that you have an Umbraco 14+ website configured and ready for the Umbraco Commerce installation. +It is assumed that you have an Umbraco 15+ website configured and ready for the Umbraco Commerce installation. {% hint style="info" %} For detailed instructions on installing the latest version of Umbraco, refer to the [Umbraco CMS documentation](https://docs.umbraco.com/umbraco-cms/fundamentals/setup/install). @@ -16,7 +16,7 @@ For detailed instructions on installing the latest version of Umbraco, refer to The minimum requirements for using Umbraco Commerce are: -* Umbraco CMS version 14+ +* Umbraco CMS version 15+ * SQL Server 2015+ Database * **SQLite** is acceptable for testing but not recommended for live deployments. For more details, see the [Configuring SQLite support](../how-to-guides/configure-sqlite-support.md) article. diff --git a/15/umbraco-commerce/key-concepts/calculators.md b/15/umbraco-commerce/key-concepts/calculators.md index d1cff883162..9edaabdf8ae 100644 --- a/15/umbraco-commerce/key-concepts/calculators.md +++ b/15/umbraco-commerce/key-concepts/calculators.md @@ -25,12 +25,12 @@ public class MyProductCalculator : ProductCalculator : base(taxService, storeService) { } - public override TaxRate CalculateProductTaxRate(IProductSnapshot productSnapshot, TaxSource taxSource, TaxRate fallbackTaxRate) + public override async Task CalculateProductTaxRateAsync(IProductSnapshot productSnapshot, TaxSource taxSource, TaxRate fallbackTaxRate) { // Do custom tax rate calculation here } - public override Price CalculateProductPrice(IProductSnapshot productSnapshot, Guid currencyId, TaxRate taxRate) + public override async Task CalculateProductPriceAsync(IProductSnapshot productSnapshot, Guid currencyId, TaxRate taxRate) { // Do custom price calculation here } diff --git a/15/umbraco-commerce/key-concepts/discount-rules-and-rewards.md b/15/umbraco-commerce/key-concepts/discount-rules-and-rewards.md index b09fc6b0cfb..4c412a923f6 100644 --- a/15/umbraco-commerce/key-concepts/discount-rules-and-rewards.md +++ b/15/umbraco-commerce/key-concepts/discount-rules-and-rewards.md @@ -26,7 +26,7 @@ An example of an Order Discount Rule Provider would look something like this: [DiscountRuleProvider("myCustomOrderRule")] public class MyCustomOrderRuleProvider : OrderDiscountRuleProviderBase { - public override DiscountRuleResult ValidateRule(DiscountRuleContext ctx, MyCustomOrderRuleProviderSettings settings) + public override async Task ValidateRuleAsync(DiscountRuleContext ctx, MyCustomOrderRuleProviderSettings settings) { if (/* Some custom logic */) return Fulfilled(); @@ -69,7 +69,7 @@ An example of an Order Line Discount Rule Provider would look something like thi [DiscountRuleProvider("myCustomOrderLineRule")] public class MyCustomOrderLineRuleProvider : OrderLineDiscountRuleProviderBase { - public override DiscountRuleResult ValidateRule(DiscountRuleContext ctx, MyCustomOrderLineRuleProviderSettings settings) + public override async Task ValidateRuleAsync(DiscountRuleContext ctx, MyCustomOrderLineRuleProviderSettings settings) { if (/* Some custom logic */) return Fulfilled(fulfilledOrderLines); @@ -100,7 +100,7 @@ An example of a Discount Reward Provider would look something like this: [DiscountRewardProvider("myDiscountReward")] public class MyDiscountRewardProvider : DiscountRewardProviderBase { - public override DiscountRewardCalculation CalculateReward(DiscountRewardContext ctx, MyDiscountRewardProviderSettings settings) + public override async Task CalculateRewardAsync(DiscountRewardContext ctx, MyDiscountRewardProviderSettings settings) { var result = new DiscountRewardCalculation(); diff --git a/15/umbraco-commerce/key-concepts/fluent-api.md b/15/umbraco-commerce/key-concepts/fluent-api.md index e40b2e9f4df..318769ff3f2 100644 --- a/15/umbraco-commerce/key-concepts/fluent-api.md +++ b/15/umbraco-commerce/key-concepts/fluent-api.md @@ -11,22 +11,22 @@ An added side effect of having [ReadOnly and Writable entities](readonly-and-wri You could perform a write operation as follows: ```csharp -_uowProvider.Execute(uow => +await _uowProvider.ExecuteAsync(async (uow) => { // Fetch the currency - var currency = _currencyService.GetCurrency(currencyId); + var currency = await _currencyService.GetCurrencyAsync(currencyId); // Convert the currency into it's Writable form - var writableCurrency = currency.AsWritable(uow); + var writableCurrency = await currency.AsWritableAsync(uow); // Perform the write operation - writableCurrency.SetName("New Name"); + await writableCurrency.SetNameAsync("New Name"); // Persist the changes to the database - _currencyService.SaveCurrency(currency); + await _currencyService.SaveCurrencyAsync(currency); // Close the transaction - uow.Complete(); + await uow.CompleteAsync(); }); ``` @@ -34,15 +34,15 @@ _uowProvider.Execute(uow => This could be simplified further by defining these actions fluently, chaining all of the entity methods into a succinct command sequence as follows: ```csharp -_uowProvider.Execute(uow => +await _uowProvider.ExecuteAsync(async (uow) => { - var currency = _currencyService.GetCurrency(currencyId) - .AsWritable(uow) - .SetName("New Name"); + var currency = await _currencyService.GetCurrencyAsync(currencyId) + .AsWritableAsync(uow) + .SetNameAsync("New Name"); - _currencyService.SaveCurrency(currency); + await _currencyService.SaveCurrencyAsync(currency); - uow.Complete(); + await uow.CompleteAsync(); }); ``` diff --git a/15/umbraco-commerce/key-concepts/payment-providers.md b/15/umbraco-commerce/key-concepts/payment-providers.md index 4b446a2d5bd..11ea13ab507 100644 --- a/15/umbraco-commerce/key-concepts/payment-providers.md +++ b/15/umbraco-commerce/key-concepts/payment-providers.md @@ -52,9 +52,9 @@ The Payment Capture workflow can be the hardest part of a Payment Provider. This Generally, there are three methods within a Payment Provider that you may need to implement, and each one has a specific responsibility. -* **GenerateForm** - The `GenerateForm` method is responsible for generating an HTML form that will redirect the customer to the given payment gateway payment form. In this method you may need to communicate with the payment gateway in order to initialize a payment, letting the payment gateway know how much to capture. This often results in some kind of code or redirect URL being returned which will need to be embedded into the generated form. The generated form is then usually displayed on a checkout **Review** page, the last page before payment is captured and will have an implementer-defined **Continue to Payment** button to submit the form and redirect the customer to the gateway. -* **ProcessCallback** - The `ProcessCallback` method is responsible for handling the response coming back from the payment gateway and processing whether the payment was successful or not. This can sometimes occur _synchronously_, if the payment gateway sends information back as part of the confirmation page redirect, or can occur _asynchronously_ if the payment gateway sends the information back via an out-of-band webhook request. -* **GetOrderReference** - The `GetOrderReference` method is responsible for extracting an order reference number from a request when the payment gateway uses an asynchronous webhook to finalize an Order **and** it uses a global webhook URL strategy for all notifications rather than a notification URL per transaction. Where a webhook URL can be passed per transaction, then Umbraco Commerce provides you with a unique callback URL you can register with the gateway that already identifies the order reference as part of the URL parameters, making implementing this method unnecessary. +* **GenerateFormAsync** - The `GenerateFormAsync` method is responsible for generating an HTML form that will redirect the customer to the given payment gateway payment form. In this method you may need to communicate with the payment gateway in order to initialize a payment, letting the payment gateway know how much to capture. This often results in some kind of code or redirect URL being returned which will need to be embedded into the generated form. The generated form is then usually displayed on a checkout **Review** page, the last page before payment is captured and will have an implementer-defined **Continue to Payment** button to submit the form and redirect the customer to the gateway. +* **ProcessCallbackAsync** - The `ProcessCallbackAsync` method is responsible for handling the response coming back from the payment gateway and processing whether the payment was successful or not. This can sometimes occur _synchronously_, if the payment gateway sends information back as part of the confirmation page redirect, or can occur _asynchronously_ if the payment gateway sends the information back via an out-of-band webhook request. +* **GetOrderReferenceAsync** - The `GetOrderReferenceAsync` method is responsible for extracting an order reference number from a request when the payment gateway uses an asynchronous webhook to finalize an Order **and** it uses a global webhook URL strategy for all notifications rather than a notification URL per transaction. Where a webhook URL can be passed per transaction, then Umbraco Commerce provides you with a unique callback URL you can register with the gateway that already identifies the order reference as part of the URL parameters, making implementing this method unnecessary. _\* denotes a required method implementation_. @@ -70,10 +70,10 @@ These features are optional and not required for Payment Provider developers to The implementable management methods are: -* **FetchPaymentStatus** - The `FetchPaymentStatus` method communicates with the 3rd party payment gateway in order to fetch the current status of the given transaction. -* **CapturePayment** - The `CapturePayment` method communicates with the 3rd party payment gateway to capture a previously authorized payment associated with the given transaction. -* **CancelPayment** - The `CancelPayment` method communicates with the 3rd party payment gateway to cancel a previously authorized payment associated with the given transaction. -* **RefundPayment** - The `RefundPayment` method communicates with the 3rd party payment gateway to refund a previously captured payment associated with the given transaction. +* **FetchPaymentStatusAsync** - The `FetchPaymentStatusAsync` method communicates with the 3rd party payment gateway in order to fetch the current status of the given transaction. +* **CapturePaymentAsync** - The `CapturePaymentAsync` method communicates with the 3rd party payment gateway to capture a previously authorized payment associated with the given transaction. +* **CancelPaymentAsync** - The `CancelPaymentAsync` method communicates with the 3rd party payment gateway to cancel a previously authorized payment associated with the given transaction. +* **RefundPaymentAsync** - The `RefundPaymentAsync` method communicates with the 3rd party payment gateway to refund a previously captured payment associated with the given transaction. For each implemented method above, developers should also implement a corresponding boolean property returning a `true` value. This is to let Umbraco Commerce know that the given feature is supported by the Payment Provider. diff --git a/15/umbraco-commerce/key-concepts/pipelines.md b/15/umbraco-commerce/key-concepts/pipelines.md index 8bcbb534198..8bc0086f97c 100644 --- a/15/umbraco-commerce/key-concepts/pipelines.md +++ b/15/umbraco-commerce/key-concepts/pipelines.md @@ -22,7 +22,7 @@ An example of a Pipeline task would look something like this: ```csharp public class AddCustomAttachmentTask : PipelineTaskWithTypedArgsBase { - public override PipelineResult Execute(EmailSendPipelineArgs args) + public override Task> ExecuteAsync(EmailSendPipelineArgs args) { var attachment = new Attachment(File.OpenRead("path\to\license.lic"), "license.lic"); @@ -33,7 +33,7 @@ public class AddCustomAttachmentTask : PipelineTaskWithTypedArgsBase`. `TPipelineArgs` is the type of arguments supported by the pipeline and `TModel` is the pipeline's return model Type. You then need to implement an `Execute` method that accepts an instance of the argument's type as input and expects a `PipelineResult` as its output. Inside this method, you can perform your custom logic as required. To complete the pipeline task, you can call `Ok(TModel)` if the task was successful. This will pass in the updated `TModel` instance to returnæ. Otherwise, you can call `Fail()` to fail the whole pipeline. +All Pipeline tasks inherit from a base class `PipelineTaskWithTypedArgsBase`. `TPipelineArgs` is the type of arguments supported by the pipeline and `TModel` is the pipeline's return model Type. You then need to implement an `ExecuteAsync` method that accepts an instance of the argument's type as input and expects a `Task>` as its output. Inside this method, you can perform your custom logic as required. To complete the pipeline task, you can call `Ok(TModel)` if the task was successful. This will pass in the updated `TModel` instance to returnæ. Otherwise, you can call `Fail()` to fail the whole pipeline. All pipelines occur within a [Unit of Work](unit-of-work.md). In case a Pipeline task fails, the whole pipeline will fail and no changes will persist. diff --git a/15/umbraco-commerce/key-concepts/price-amount-adjustments.md b/15/umbraco-commerce/key-concepts/price-amount-adjustments.md index c8b681b6d13..6d2a9fed0e0 100644 --- a/15/umbraco-commerce/key-concepts/price-amount-adjustments.md +++ b/15/umbraco-commerce/key-concepts/price-amount-adjustments.md @@ -18,7 +18,7 @@ Adjustments are applied using a `IPriceAdjuster` or `IAmountAdjuster` with devel ```csharp public class MyPriceAdjuster : PriceAdjusterBase { - public override void ApplyPriceAdjustments(PriceAdjusterArgs args) + public override async Task ApplyPriceAdjustmentsAsync(PriceAdjusterArgs args) { // Calculate Adjustment // Discount adjustments should be negative diff --git a/15/umbraco-commerce/key-concepts/price-freezing.md b/15/umbraco-commerce/key-concepts/price-freezing.md index b08affefcc0..a31be8230b0 100644 --- a/15/umbraco-commerce/key-concepts/price-freezing.md +++ b/15/umbraco-commerce/key-concepts/price-freezing.md @@ -12,18 +12,18 @@ A product's price is frozen from the point it is added to the current Order, and There are times when you may wish to control when a frozen price should expire. This could be if a product was incorrectly priced, or if you have rules on how long an Order-session is allowed to maintain price. -On these occasions, you can force frozen prices to expire by using the `IPriceFreezerService` and its `ThawPrices` method. +On these occasions, you can force frozen prices to expire by using the `IPriceFreezerService` and its `ThawPricesAsync` method. All frozen prices have an `OrderId` property and a `Key` that uniquely identifies them. For product prices, this key consists of a generated token of the following format `{StoreId}_{OrderId}_{ProductReference}`. In addition, the product prices Currency, and date of the freeze are also tracked. It is important to know these details as we can use all of these attributes to target which prices we wish to thaw. For example, to thaw all prices for a product with the reference `c0296b75-1764-4f62-b59c-7005c2348fdd` we could call: ```csharp -_priceFreezerService.ThawPrices(partialKey: "c0296b75-1764-4f62-b59c-7005c2348fdd"); +await _priceFreezerService.ThawPricesAsync(partialKey: "c0296b75-1764-4f62-b59c-7005c2348fdd"); ``` Or to thaw all prices for a given Currency that are greater than 30 days old we could call: ```csharp -_priceFreezerService.ThawPrices(currencyId: currency.Id, olderThan: DateTime.Now.AddDays(-30)); +await _priceFreezerService.ThawPricesAsync(currencyId: currency.Id, olderThan: DateTime.Now.AddDays(-30)); ``` diff --git a/15/umbraco-commerce/key-concepts/product-adapters.md b/15/umbraco-commerce/key-concepts/product-adapters.md index 9bb69fab26d..f5bc1066464 100644 --- a/15/umbraco-commerce/key-concepts/product-adapters.md +++ b/15/umbraco-commerce/key-concepts/product-adapters.md @@ -15,17 +15,17 @@ An example of a Product Adapter would look something like this: ```csharp public class MyCustomProductAdapter : IProductAdapter { - public IProductSnapshot GetProductSnapshot(string productReference, string languageIsoCode) + public Task GetProductSnapshotAsync(string productReference, string languageIsoCode) { // Lookup a product by productReference and convert to IProductSnapshot } - public IProductSnapshot GetProductSnapshot(string productReference, string productVariantReference, string languageIsoCode) + public Task GetProductSnapshotAsync(string productReference, string productVariantReference, string languageIsoCode) { // Lookup a product by productVariantReference and convert to IProductSnapshot } - public bool TryGetProductReference(Guid storeId, string sku, out string productReference, out string productVariantReference) + Task> TryGetProductReferenceAsync(Guid storeId, string sku) { // Try lookup a product / variant reference by store + sku } @@ -35,8 +35,8 @@ public class MyCustomProductAdapter : IProductAdapter All Product Adapters implement the `IProductAdapter` interface which requires three method implementations: -* Two `GetProductSnapshot` methods that retrieve a Product Snapshot for either a product or product variant by reference parameters. -* A `TryGetProductReference` method which retrieves a product/variant reference for a product that belongs to a given `storeId` and has the given `sku`. +* Two `GetProductSnapshotAsync` methods that retrieve a Product Snapshot for either a product or product variant by reference parameters. +* A `TryGetProductReferenceAsync` method which retrieves a product/variant reference for a product that belongs to a given `storeId` and has the given `sku`. A Product Snapshot consists of the following properties in order to present a Product to Umbraco Commerce in a standard way. @@ -85,17 +85,17 @@ public class MyCustomProductAdapter : ProductAdapterBase { ... - public override PagedResult SearchProductSummaries(Guid storeId, string languageIsoCode, string searchTerm, long currentPage = 1, long itemsPerPage = 50) + public override Task> SearchProductSummariesAsync(Guid storeId, string languageIsoCode, string searchTerm, long currentPage = 1, long itemsPerPage = 50) { // Search for products matching the given search term and convert to a IProductSummary } - public override IEnumerable GetProductVariantAttributes(Guid storeId, string productReference, string languageIsoCode) + public override Task> GetProductVariantAttributesAsync(Guid storeId, string productReference, string languageIsoCode) { // Lookup the in-use product attributes of a primary product } - public override PagedResult SearchProductVariantSummaries(Guid storeId, string productReference, string languageIsoCode, string searchTerm, IDictionary> attributes, long currentPage = 1, long itemsPerPage = 50) + public override Task> SearchProductVariantSummariesAsync(Guid storeId, string productReference, string languageIsoCode, string searchTerm, IDictionary> attributes, long currentPage = 1, long itemsPerPage = 50) { // Search for product variants matching the given search term and/or the given attributes and convert to a IProductVariantSummary } diff --git a/15/umbraco-commerce/key-concepts/product-bundles.md b/15/umbraco-commerce/key-concepts/product-bundles.md index 7e1b74db372..22d8a5781ba 100644 --- a/15/umbraco-commerce/key-concepts/product-bundles.md +++ b/15/umbraco-commerce/key-concepts/product-bundles.md @@ -15,23 +15,23 @@ To create a bundle, we first add the primary product to an order as we normally var bundleId = "MyUniqueBundleId"; // Add the primary product to the order giving it a bundle ID -order.AddProduct(productReference, productQuantity, bundleId); +await order.AddProductAsync(productReference, productQuantity, bundleId); ``` ## Adding Sub Products to a Bundle -With the primary product added as a bundle, we can then add sub-products to that bundle by calling one of the `AddProductToBundle` order methods. +With the primary product added as a bundle, we can then add sub-products to that bundle by calling one of the `AddProductToBundleAsync` order methods. ```csharp // Define a unique bundle id for the order line var bundleId = "MyUniqueBundleId"; // Add the primary product to the order giving it a bundle ID -order.AddProduct(productReference, productQuantity, bundleId); +await order.AddProductAsync(productReference, productQuantity, bundleId); // Add a sub product to the bundle by calling a AddProductToBundle method // passing in the same bundle ID as the primary order line -order.AddProductToBundle(bundleId, subProductReference, subProductQuantity); +await order.AddProductToBundleAsync(bundleId, subProductReference, subProductQuantity); ``` ## Order Line Price Calculation diff --git a/15/umbraco-commerce/key-concepts/properties.md b/15/umbraco-commerce/key-concepts/properties.md index 674abee0bf2..08ad1347caf 100644 --- a/15/umbraco-commerce/key-concepts/properties.md +++ b/15/umbraco-commerce/key-concepts/properties.md @@ -16,17 +16,17 @@ To set a Property on an Order or Order Line, it needs to be [in its Writable sta ```csharp // Set a single property -order.SetProperty("propertyAlias", "Property Value"); +await order.SetPropertyAsync("propertyAlias", "Property Value"); // Set multiple properties at once -order.SetProperties(new Dictionary{ +await order.SetPropertiesAsync(new Dictionary{ { "propertyAlias1", "Property Value 1" }, { "propertyAlias2", "Property Value 2" }, { "propertyAlias3", "Property Value 3" } }) // Remove a property -order.RemoveProperty("propertyAlias"); +await order.RemovePropertyAsync("propertyAlias"); ``` @@ -34,10 +34,10 @@ Property values can either be a `string`, or a Umbraco Commerce `PropertyValue` ```csharp // Set a string property -order.SetProperty("propertyAlias", "Property Value"); +await order.SetPropertyAsync("propertyAlias", "Property Value"); // Set a PropertyValue property as Read Only -order.SetProperty("propertyAlias", new PropertyValue("Property Value", isReadOnly: true)); +await order.SetPropertyAsync("propertyAlias", new PropertyValue("Property Value", isReadOnly: true)); ``` ## System Properties diff --git a/15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md b/15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md index 0e83991743d..579f333f9ae 100644 --- a/15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md +++ b/15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md @@ -17,29 +17,29 @@ The reason why we have split entities in this way for a number of reasons, howev ## Converting a ReadOnly entity into a Writable entity -To convert a ReadOnly entity into its Writable form, we achieve this by calling the entities `AsWritable(uow)` method, passing in a valid Unit of Work instance to perform the write operations on. Once we have a Writable entity, we can then perform the write operations we desire and persist those changes back to the database. +To convert a ReadOnly entity into its Writable form, we achieve this by calling the entities `AsWritableAsync(uow)` method, passing in a valid Unit of Work instance to perform the write operations on. Once we have a Writable entity, we can then perform the write operations we desire and persist those changes back to the database. ```csharp -_uowProvider.Execute(uow => +await _uowProvider.ExecuteAsync(async (uow) => { // Fetch the currency - var currency = _currencyService.GetCurrency(currencyId); + var currency = await _currencyService.GetCurrencyAsync(currencyId); // Convert the currency into it's Writable form - var writableCurrency = currency.AsWritable(uow); + var writableCurrency = await currency.AsWritableAsync(uow); // Peform our write operation - writableCurrency.SetName("New Name"); + await writableCurrency.SetNameAsync("New Name"); // Persist the changes to the database - _currencyService.SaveCurrency(currency); + await _currencyService.SaveCurrencyAsync(currency); // Close our transaction - uow.Complete(); + await uow.CompleteAsync(); }); ``` {% hint style="info" %} -All write operations must occur within a Unit of Work so by passing in a Unit of Work instance into the entities `AsWritable` method, we are ensuring that you are in fact within an active Unit of Work. +All write operations must occur within a Unit of Work so by passing in a Unit of Work instance into the entities `AsWritableAsync` method, we are ensuring that you are in fact within an active Unit of Work. {% endhint %} diff --git a/15/umbraco-commerce/key-concepts/sales-taxt-providers.md b/15/umbraco-commerce/key-concepts/sales-tax-providers.md similarity index 100% rename from 15/umbraco-commerce/key-concepts/sales-taxt-providers.md rename to 15/umbraco-commerce/key-concepts/sales-tax-providers.md diff --git a/15/umbraco-commerce/key-concepts/search-specifications.md b/15/umbraco-commerce/key-concepts/search-specifications.md index 34327612443..d56a4f66a83 100644 --- a/15/umbraco-commerce/key-concepts/search-specifications.md +++ b/15/umbraco-commerce/key-concepts/search-specifications.md @@ -21,7 +21,7 @@ To perform a search using specifications you'll need to use one of the search me To use one of the search methods, the implementation will look something like the following: ```csharp -var results = _orderService.SearchOrders( +var results = await _orderService.SearchOrdersAsync( (where) => where .FromStore(storeId) .And(where.HasOrderNumber(orderNumber).Or(where.ByCustomer(customerEmail)))) @@ -36,7 +36,7 @@ Because the API is fluent it is also self-documenting, with Visual Studio intell Alongside the query specifications documented above, we also have to sort specifications that allow a similar fluent API for defining the order in which results are returned. These are passed in a similar way to the search methods as demonstrated below. ```csharp -var results = _orderService.SearchOrders( +var results = await _orderService.SearchOrdersAsync( (where) => where .FromStore(storeId) .And(where.HasOrderNumber(orderNumber).Or(where.ByCustomer(customerEmail))), diff --git a/15/umbraco-commerce/key-concepts/shipping-package-factories.md b/15/umbraco-commerce/key-concepts/shipping-package-factories.md index bb33d1f212c..611532b2310 100644 --- a/15/umbraco-commerce/key-concepts/shipping-package-factories.md +++ b/15/umbraco-commerce/key-concepts/shipping-package-factories.md @@ -32,7 +32,7 @@ There are some limitations of the Stacked Shortest Dimension Package Factory tha Given the limitations of the Stacked Shortest Dimension Package Factory, it may become necessary to implement your own packaging algorithm. This can be achieved by implementing your package factory class and swapping out the default one in the DI container. -To implement your own package factory you need to implement the `ShippingPackageFactoryBase` class and implement the `CreatePackages` method. +To implement your own package factory you need to implement the `ShippingPackageFactoryBase` class and implement the `CreatePackagesAsync` method. ```csharp public class MyPackageFactory : ShippingPackageFactoryBase @@ -41,7 +41,7 @@ public class MyPackageFactory : ShippingPackageFactoryBase : base(umbracoCommerce) { } - public override IEnumerable CreatePackages(ShippingMethodReadOnly shippingMethod, OrderReadOnly order) + public override Task> CreatePackagesAsync(ShippingMethodReadOnly shippingMethod, OrderReadOnly order) { // Calculate and return packages } diff --git a/15/umbraco-commerce/key-concepts/shipping-range-and-rate-providers.md b/15/umbraco-commerce/key-concepts/shipping-range-and-rate-providers.md index bf8dd7ec38d..f307104a933 100644 --- a/15/umbraco-commerce/key-concepts/shipping-range-and-rate-providers.md +++ b/15/umbraco-commerce/key-concepts/shipping-range-and-rate-providers.md @@ -27,7 +27,7 @@ Should you wish to define some other unit on which to calculate rates, you can c SortOrder: 30)] public class MyShippingRateRangeProvider : ShippingRateRangeProvider { - public override Attempt TryFindRangeIndex(ShippingRateRangeCalculationContext ctx) + public override Task> TryFindRangeIndexAsync(ShippingRateRangeCalculationContext ctx) { // Use the ctx.Ranges property to find the index that that ctx.Order falls within // return Attempt.Succeed(index); @@ -35,7 +35,7 @@ public class MyShippingRateRangeProvider : ShippingRateRangeProvider } ``` -The class should be decorated with the `ShippingRateRangeProviderAttribute` which defines an alias and editor alias for the provider. It implements a single method `TryFindRangeIndex` which, given a `ShippingRateRangeCalculationContext`, should find the index the current order falls within a series of preconfigured ranges. The `ShippingRateRangeCalculationContext` contains a series of useful properties that you can use to form your calculation. +The class should be decorated with the `ShippingRateRangeProviderAttribute` which defines an alias and editor alias for the provider. It implements a single method `TryFindRangeIndexAsync` which, given a `ShippingRateRangeCalculationContext`, should find the index the current order falls within a series of preconfigured ranges. The `ShippingRateRangeCalculationContext` contains a series of useful properties that you can use to form your calculation. * **Ranges** - A list of configured ranges from the UI from which to find the index of the given order. * **Order** - The order to use when finding the current range. @@ -85,7 +85,7 @@ Should you wish to define some other rate calculation logic, you can create your SortOrder: 30)] public class MyShippingRateProvider : ShippingRateProvider { - public override Attempt TryGetRate(ShippingRateCalculationContext ctx) + public override Task> TryGetRateAsync(ShippingRateCalculationContext ctx) { // Use the context parameter to calculate a rate ammount // return Attempt.Succeed(Price.Calculate(amount, ctx.TaxRate, ctx.Currency.Id, ctx.Store.PricesIncludeTax)); @@ -93,7 +93,7 @@ public class MyShippingRateProvider : ShippingRateProvider } ``` -The class should be decorated with the `ShippingRateProviderAttribute` which defines an alias and editor alias for the provider. It implements a single method `TryGetRate` which, given a `ShippingRateCalculationContext`, should calculate the relevant rate. The `ShippingRateCalculationContext` contains a series of useful properties that you can use to form your calculation. +The class should be decorated with the `ShippingRateProviderAttribute` which defines an alias and editor alias for the provider. It implements a single method `TryGetRateAsync` which, given a `ShippingRateCalculationContext`, should calculate the relevant rate. The `ShippingRateCalculationContext` contains a series of useful properties that you can use to form your calculation. * **Model** - The value for this rate provider captured from the UI. * **Order** - The order associated with this calculation. diff --git a/15/umbraco-commerce/key-concepts/unit-of-work.md b/15/umbraco-commerce/key-concepts/unit-of-work.md index eabac773e45..e29045eb999 100644 --- a/15/umbraco-commerce/key-concepts/unit-of-work.md +++ b/15/umbraco-commerce/key-concepts/unit-of-work.md @@ -15,16 +15,16 @@ Creating a unit of work will require access to Umbraco Commerce's `IUnitOfWorkPr Once you have access to either of these entry points, you can define a Unit of Work as follows ```csharp -_uowProvider.Execute(uow => +await _uowProvider.ExecuteAsync(async (uow) => { // Perform your write operations here - uow.Complete(); + await uow.CompleteAsync(); }); ``` -The anatomy of a Unit of Work is an `Execute` method call on the `IUnitOfWorkProvider` instance which accepts a delegate function with a `uow` argument. Inside the delegate, we perform our tasks and confirm the Unit of Work as complete by calling `uow.Complete()`. If we fail to call `uow.Complete()` either due to forgetting to add the `uow.Complete()` call or due to an exception in our code, then any write operations that occur within that code block will **not** be persisted in the database. +The anatomy of a Unit of Work is an `ExecuteAsync` method call on the `IUnitOfWorkProvider` instance which accepts an async delegate function with a `uow` argument. Inside the delegate, we perform our tasks and confirm the Unit of Work as complete by calling `await uow.CompleteAsync()`. If we fail to call `await uow.CompleteAsync()` either due to forgetting to add the `await uow.CompleteAsync()` call or due to an exception in our code, then any write operations that occur within that code block will **not** be persisted in the database. ### Unit of Work Best Practice @@ -35,19 +35,19 @@ Perform all write operations in a single Unit of Work {% endhint %} ```csharp -_uowProvider.Execute(uow => +await _uowProvider.ExecuteAsync(async (uow) => { // Create a Country - var country = Country.Create(uow, storeId, "DK", "Denmark"); + var country = await Country.CreateAsync(uow, storeId, "DK", "Denmark"); - _countryService.Save(country); + await _countryService.SaveCountryAsync(country); // Create a Currency - var currency = Currency.Create(uow, storeId, "DKK", "Danish Kroner", "da-DK"); + var currency = await Currency.CreateAsync(uow, storeId, "DKK", "Danish Kroner", "da-DK"); - _currencyService.Save(currency); + await _currencyService.SaveCurrencyAsync(currency); - uow.Complete(); + await uow.CompleteAsync(); }); ``` @@ -56,23 +56,23 @@ It is not recommended to create a Unit of Work per write operation. {% endhint %} ```csharp -_uowProvider.Execute(uow => +await _uowProvider.ExecuteAsync(async (uow) => { // Create a Country - var country = Country.Create(uow, storeId, "DK", "Denmark"); + var country = await Country.CreateAsync(uow, storeId, "DK", "Denmark"); - _countryService.Save(country); + await _countryService.SaveCountryAsync(country); - uow.Complete(); + await uow.CompleteAsync(); }); -_uowProvider.Execute(uow => +await _uowProvider.ExecuteAsync(async (uow) => { // Create a Currency - var currency = Currency.Create(uow, storeId, "DKK", "Danish Kroner", "da-DK"); + var currency = await Currency.CreateAsync(uow, storeId, "DKK", "Danish Kroner", "da-DK"); - _currencyService.Save(currency); + await _currencyService.SaveCurrencyAsync(currency); - uow.Complete(); + await uow.CompleteAsync(); }); ``` diff --git a/15/umbraco-commerce/release-notes/README.md b/15/umbraco-commerce/release-notes/README.md index bd3423fdac2..59a16408429 100644 --- a/15/umbraco-commerce/release-notes/README.md +++ b/15/umbraco-commerce/release-notes/README.md @@ -17,89 +17,11 @@ If you are upgrading to a new major version, check the breaking changes in the [ This section contains the release notes for Umbraco Commerce 14 including all changes for this version. -#### 14.0.0 (23rd August 2024) +#### 15.0.0-rc1 (24th May 2024) -Read the [v14.0.0 release post](./v14.0.0.md) for more information about this release. +Read the [v15.0.0-rc release post](./v15.0.0-rc.md) for further background on this release. -* Added "No results" messages to collection views -* Upgraded Umbraco CMS dependency to v14.2.0 - -#### 14.0.0-rc3 (12th August 2024) - -* Added warning on store dashboard/analytics section if the store has multiple currencies when no currency exchange rate service is configured. -* Added nullable type support to payment provider/shipping provider settings models. -* Added `UcStoreContext` to exported NPM package. -* Added background task licenses resolver to allow Umbraco Commerce to run background tasks without error. -* Added delete support to carts and orders. -* Updated store create dialog to redirect to store editor on create. -* Fixed error on store dashboard when using SQL Server due to group by issue in SQL statement [#547](https://github.com/umbraco/Umbraco.Commerce.Issues/issues/547). -* Fixed errors in v14 migrations when using a separate table for Umbraco Commerce. -* Fixed error in v14 migrations where data types are not correctly migrated. -* Fixed store tree not updating when a new store is created. -* Fixed shipping provider advanced settings now showing in an advanced dropdown editor UI. -* Fixed broken localization keys. - -#### 14.0.0-rc2 (29th July 2024) - -* Fixed issue in rc1 DB migration script. - -#### 14.0.0-rc1 (29th July 2024) - -* Added sort modals to all sortable entities. -* Added basic text search across all entity collection views. -* Added cart status filter option to carts collection view. -* Added advanced properties support to payment/shipping provider settings. -* Added order activity log funcationality back in. -* Added commerce section dashboard. -* Added async pipeline implementation. -* Added front end NPM package for UI extension points. -* Localized all hard coded strings. -* Replaced `Newtonsoft.Json` with `System.Text.Json` throughout. -* Removed `ExchangeRateHost` as the default exchange rate service as it now requires an API key. -* Fixed validation error for Region code not matching the description example. -* Fixed bug in payment provider URL generation containing a rogue `$` symbol. - -#### 14.0.0-beta1 (16th July 2024) - -* Added Product Attributes section -* Added Product Attribute Presets section -* Added Variants property editor to create complex product variants -* Fixed issues with property editor value converters -* Fixed issue with stock synchronization - -#### 14.0.0-alpha4 (3rd July 2024) - -* Added Carts section with ability to create/edit customer carts -* Refactored order endpoints to use a defined model for customer/billing/shipping details rather than using order properties collection -* Merged in v13 bug fixes - -#### 14.0.0-alpha3 (24th June 2024) - -* Added Analytics section -* Added Create Country modal to allow creating countries from ISO 3166 presets -* Added license warning component throughout the commerce section -* Updated Regions workspace app to now be hidden until the country is persisted -* Update Payment Provider / Shipping Provider label keys to convert kebab case provider aliases to camel case keys for consistency -* Fixed bug in Payment Providers section throwing error due to unmapped `sku` property -* Fixed issue due to use of `JSON_PATH_EXISTS` in migration scripts only supported in SQL Server 2022+. Resorted to just using `JSON_VALUE` queries instead [(#521)](https://github.com/umbraco/Umbraco.Commerce.Issues/issues/521) - -#### 14.0.0-alpha2 (7th June 2024) - -* Added section condition to commerce section to only show it when the current user has permission to see it -* Setup Management APIs for Product Attributes, Discounts, Gift Cards and Analytics sections -* Created an new Umbraco Commerce Payment API to handle payment gateway interactions (old endpoints are depricated) -* Added a basic store dashboard with current days stats and order search -* Added Gift Cards section -* Added Discounts section -* Various bug fixes -* Backoffice resources are now lazy loaded -* Upgraded Umbraco dependency to v14 final - -#### 14.0.0-alpha1 (24th May 2024) - -Read the [v14.0.0-Alpha release post](./v14.0.0-alpha.md) for further background on this release. - -* v14 initial alpha release +* v15 initial release candidate ## Legacy release notes From 553417aec072244b5d10c7efa61e1e634c4ed2ed Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Fri, 8 Nov 2024 12:33:38 +0100 Subject: [PATCH 04/18] Updated how to guides --- .../how-to-guides/limit-orderline-quantity.md | 8 ++++---- .../upgrading/version-specific-upgrades.md | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/15/umbraco-commerce/how-to-guides/limit-orderline-quantity.md b/15/umbraco-commerce/how-to-guides/limit-orderline-quantity.md index 41bc1edd17a..e8c045c7a56 100644 --- a/15/umbraco-commerce/how-to-guides/limit-orderline-quantity.md +++ b/15/umbraco-commerce/how-to-guides/limit-orderline-quantity.md @@ -23,12 +23,12 @@ public class ProductAddValidationHandler : ValidationEventHandlerBase x.ProductReference == productReference).Sum(x => x.Quantity) ?? 0; @@ -53,12 +53,12 @@ public class OrderLineQuantityValidationHandler : ValidationEventHandlerBase stock.Value) evt.Fail($"Only {stock} quantities can be purchased for {productReference}."); diff --git a/15/umbraco-commerce/upgrading/version-specific-upgrades.md b/15/umbraco-commerce/upgrading/version-specific-upgrades.md index 3bf928c7672..687c2e20a48 100644 --- a/15/umbraco-commerce/upgrading/version-specific-upgrades.md +++ b/15/umbraco-commerce/upgrading/version-specific-upgrades.md @@ -5,7 +5,7 @@ description: >- # Version Specific Upgrade Notes -This page covers specific upgrade documentation for when migrating to major 14 of Umbraco Commerce. +This page covers specific upgrade documentation for when migrating to major 15 of Umbraco Commerce. {% hint style="info" %} If you are upgrading to a new minor or patch version, you can find information about the breaking changes in the [Release Notes](../release-notes.md) article. @@ -13,9 +13,9 @@ If you are upgrading to a new minor or patch version, you can find information a ## Version Specific Upgrade Notes History -#### 14.0.0 +#### 15.0.0 -* UI Config file configurations will need to use the new UI Extensions API +* API method calls will need to use the async alternatives #### Umbraco Commerce Launch From 0b9835d030b1db8972d96ab4d7dd0e97fedb69c4 Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Fri, 8 Nov 2024 14:36:17 +0100 Subject: [PATCH 05/18] Replace uow.Complete --- 15/umbraco-commerce/key-concepts/fluent-api.md | 4 ++-- .../key-concepts/readonly-and-writable-entities.md | 2 +- 15/umbraco-commerce/key-concepts/unit-of-work.md | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/15/umbraco-commerce/key-concepts/fluent-api.md b/15/umbraco-commerce/key-concepts/fluent-api.md index 318769ff3f2..7f8faee7d20 100644 --- a/15/umbraco-commerce/key-concepts/fluent-api.md +++ b/15/umbraco-commerce/key-concepts/fluent-api.md @@ -26,7 +26,7 @@ await _uowProvider.ExecuteAsync(async (uow) => await _currencyService.SaveCurrencyAsync(currency); // Close the transaction - await uow.CompleteAsync(); + uow.Complete(); }); ``` @@ -42,7 +42,7 @@ await _uowProvider.ExecuteAsync(async (uow) => await _currencyService.SaveCurrencyAsync(currency); - await uow.CompleteAsync(); + uow.Complete(); }); ``` diff --git a/15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md b/15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md index 579f333f9ae..35872f9eaaf 100644 --- a/15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md +++ b/15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md @@ -35,7 +35,7 @@ await _uowProvider.ExecuteAsync(async (uow) => await _currencyService.SaveCurrencyAsync(currency); // Close our transaction - await uow.CompleteAsync(); + uow.Complete(); }); ``` diff --git a/15/umbraco-commerce/key-concepts/unit-of-work.md b/15/umbraco-commerce/key-concepts/unit-of-work.md index e29045eb999..7faac1282ba 100644 --- a/15/umbraco-commerce/key-concepts/unit-of-work.md +++ b/15/umbraco-commerce/key-concepts/unit-of-work.md @@ -19,12 +19,12 @@ await _uowProvider.ExecuteAsync(async (uow) => { // Perform your write operations here - await uow.CompleteAsync(); + uow.Complete(); }); ``` -The anatomy of a Unit of Work is an `ExecuteAsync` method call on the `IUnitOfWorkProvider` instance which accepts an async delegate function with a `uow` argument. Inside the delegate, we perform our tasks and confirm the Unit of Work as complete by calling `await uow.CompleteAsync()`. If we fail to call `await uow.CompleteAsync()` either due to forgetting to add the `await uow.CompleteAsync()` call or due to an exception in our code, then any write operations that occur within that code block will **not** be persisted in the database. +The anatomy of a Unit of Work is an `ExecuteAsync` method call on the `IUnitOfWorkProvider` instance which accepts an async delegate function with a `uow` argument. Inside the delegate, we perform our tasks and confirm the Unit of Work as complete by calling `uow.Complete()`. If we fail to call `uow.Complete()` either due to forgetting to add the `uow.Complete()` call or due to an exception in our code, then any write operations that occur within that code block will **not** be persisted in the database. ### Unit of Work Best Practice @@ -47,7 +47,7 @@ await _uowProvider.ExecuteAsync(async (uow) => await _currencyService.SaveCurrencyAsync(currency); - await uow.CompleteAsync(); + uow.Complete(); }); ``` @@ -63,7 +63,7 @@ await _uowProvider.ExecuteAsync(async (uow) => await _countryService.SaveCountryAsync(country); - await uow.CompleteAsync(); + uow.Complete(); }); await _uowProvider.ExecuteAsync(async (uow) => @@ -73,6 +73,6 @@ await _uowProvider.ExecuteAsync(async (uow) => await _currencyService.SaveCurrencyAsync(currency); - await uow.CompleteAsync(); + uow.Complete(); }); ``` From dbef177b23ad252df97f5839e1e86e75d7362d35 Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Mon, 11 Nov 2024 10:43:55 +0100 Subject: [PATCH 06/18] Updated licensing docs inline with changes in Umbraco.Licenses --- 15/umbraco-commerce/getting-started/the-licensing-model.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/15/umbraco-commerce/getting-started/the-licensing-model.md b/15/umbraco-commerce/getting-started/the-licensing-model.md index 7e26653ae39..8d8bdf9515c 100644 --- a/15/umbraco-commerce/getting-started/the-licensing-model.md +++ b/15/umbraco-commerce/getting-started/the-licensing-model.md @@ -62,11 +62,15 @@ Once you have received your license code it needs to be installed on your site. ```json "Umbraco": { "Licenses": { - "Umbraco.Commerce": "YOUR_LICENSE_KEY" + "Products": { + "Umbraco.Commerce": "YOUR_LICENSE_KEY" + } } } ``` + + ### Verify the license installation You can verify that your license is successfully installed by logging into your project's backoffice and navigating to the settings section. Here you will see a license dashboard which should display the status of your license. From cc8beebe0e8f6ec8f5cdf967500cb60fd448a136 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:56:23 +0100 Subject: [PATCH 07/18] Update 15/umbraco-commerce/release-notes/v15.0.0-rc.md --- 15/umbraco-commerce/release-notes/v15.0.0-rc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/umbraco-commerce/release-notes/v15.0.0-rc.md b/15/umbraco-commerce/release-notes/v15.0.0-rc.md index 3ebccb6b682..e2fe1180cc7 100644 --- a/15/umbraco-commerce/release-notes/v15.0.0-rc.md +++ b/15/umbraco-commerce/release-notes/v15.0.0-rc.md @@ -15,7 +15,7 @@ Umbraco Commerce v15.0.0-rc is the initial release of Umbraco Commerce for Umbra ## Async -The key focus of this release is the move to a fully asyncronus code base. In order to reduce the maintenance burden, the decision was made to go fully async without maintaining backwards compatibility. This will therfore require code updates to use the new async methods. +The key focus of this release is the move to a fully asynchronous code base. To reduce the maintenance burden, the decision was made to go fully async without maintaining backward compatibility. This will therefore require code updates to use the new async methods. ### Previous behavior Previously all C# API's were synchronous and thus blocking by nature. From e8ab269dde575c93159cdcea2428ebf0ccbcde8f Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:56:37 +0100 Subject: [PATCH 08/18] Update 15/umbraco-commerce/key-concepts/payment-providers.md --- 15/umbraco-commerce/key-concepts/payment-providers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/umbraco-commerce/key-concepts/payment-providers.md b/15/umbraco-commerce/key-concepts/payment-providers.md index 11ea13ab507..06afc24e38f 100644 --- a/15/umbraco-commerce/key-concepts/payment-providers.md +++ b/15/umbraco-commerce/key-concepts/payment-providers.md @@ -53,7 +53,7 @@ The Payment Capture workflow can be the hardest part of a Payment Provider. This Generally, there are three methods within a Payment Provider that you may need to implement, and each one has a specific responsibility. * **GenerateFormAsync** - The `GenerateFormAsync` method is responsible for generating an HTML form that will redirect the customer to the given payment gateway payment form. In this method you may need to communicate with the payment gateway in order to initialize a payment, letting the payment gateway know how much to capture. This often results in some kind of code or redirect URL being returned which will need to be embedded into the generated form. The generated form is then usually displayed on a checkout **Review** page, the last page before payment is captured and will have an implementer-defined **Continue to Payment** button to submit the form and redirect the customer to the gateway. -* **ProcessCallbackAsync** - The `ProcessCallbackAsync` method is responsible for handling the response coming back from the payment gateway and processing whether the payment was successful or not. This can sometimes occur _synchronously_, if the payment gateway sends information back as part of the confirmation page redirect, or can occur _asynchronously_ if the payment gateway sends the information back via an out-of-band webhook request. +* **ProcessCallbackAsync** - The `ProcessCallbackAsync` method handles the response coming back from the payment gateway and processing whether the payment was successful or not. This can occur _synchronously_, if the payment gateway sends information back during the confirmation page redirect. It can also occur _asynchronously_ if the payment gateway sends the information back via an out-of-band webhook request. * **GetOrderReferenceAsync** - The `GetOrderReferenceAsync` method is responsible for extracting an order reference number from a request when the payment gateway uses an asynchronous webhook to finalize an Order **and** it uses a global webhook URL strategy for all notifications rather than a notification URL per transaction. Where a webhook URL can be passed per transaction, then Umbraco Commerce provides you with a unique callback URL you can register with the gateway that already identifies the order reference as part of the URL parameters, making implementing this method unnecessary. _\* denotes a required method implementation_. From 8610e2ba0a52f6169e0d932068884659109a6c3f Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:56:47 +0100 Subject: [PATCH 09/18] Update 15/umbraco-commerce/key-concepts/payment-providers.md --- 15/umbraco-commerce/key-concepts/payment-providers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/umbraco-commerce/key-concepts/payment-providers.md b/15/umbraco-commerce/key-concepts/payment-providers.md index 06afc24e38f..2ee18f3939c 100644 --- a/15/umbraco-commerce/key-concepts/payment-providers.md +++ b/15/umbraco-commerce/key-concepts/payment-providers.md @@ -52,7 +52,7 @@ The Payment Capture workflow can be the hardest part of a Payment Provider. This Generally, there are three methods within a Payment Provider that you may need to implement, and each one has a specific responsibility. -* **GenerateFormAsync** - The `GenerateFormAsync` method is responsible for generating an HTML form that will redirect the customer to the given payment gateway payment form. In this method you may need to communicate with the payment gateway in order to initialize a payment, letting the payment gateway know how much to capture. This often results in some kind of code or redirect URL being returned which will need to be embedded into the generated form. The generated form is then usually displayed on a checkout **Review** page, the last page before payment is captured and will have an implementer-defined **Continue to Payment** button to submit the form and redirect the customer to the gateway. +* **GenerateFormAsync** - The `GenerateFormAsync` method generates an HTML form that will redirect the customer to the given payment gateway payment form. In this method you may need to communicate with the payment gateway to initialize a payment, letting the payment gateway know how much to capture. This often results in some kind of code or redirect URL being returned which will need to be embedded into the generated form. The form appears on a checkout **Review** page before payment, featuring a **Continue to Payment** button to submit the form and redirect to the gateway. * **ProcessCallbackAsync** - The `ProcessCallbackAsync` method handles the response coming back from the payment gateway and processing whether the payment was successful or not. This can occur _synchronously_, if the payment gateway sends information back during the confirmation page redirect. It can also occur _asynchronously_ if the payment gateway sends the information back via an out-of-band webhook request. * **GetOrderReferenceAsync** - The `GetOrderReferenceAsync` method is responsible for extracting an order reference number from a request when the payment gateway uses an asynchronous webhook to finalize an Order **and** it uses a global webhook URL strategy for all notifications rather than a notification URL per transaction. Where a webhook URL can be passed per transaction, then Umbraco Commerce provides you with a unique callback URL you can register with the gateway that already identifies the order reference as part of the URL parameters, making implementing this method unnecessary. From ed4c57505ae76ec8721626e310553b1a57a26c9d Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:57:07 +0100 Subject: [PATCH 10/18] Update 15/umbraco-commerce/release-notes/v15.0.0-rc.md --- 15/umbraco-commerce/release-notes/v15.0.0-rc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/umbraco-commerce/release-notes/v15.0.0-rc.md b/15/umbraco-commerce/release-notes/v15.0.0-rc.md index e2fe1180cc7..eec191d62dd 100644 --- a/15/umbraco-commerce/release-notes/v15.0.0-rc.md +++ b/15/umbraco-commerce/release-notes/v15.0.0-rc.md @@ -41,7 +41,7 @@ public class MyNotification : NotificationEventHandlerBase result +All APIs are now asynchronous and thus are suffixed with Async and return a Task result. ```csharp // Fluent API example From 1aee2aef1f056a28981dcfc93143735fe4d86c1d Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:57:25 +0100 Subject: [PATCH 11/18] Update 15/umbraco-commerce/release-notes/v15.0.0-rc.md --- 15/umbraco-commerce/release-notes/v15.0.0-rc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/umbraco-commerce/release-notes/v15.0.0-rc.md b/15/umbraco-commerce/release-notes/v15.0.0-rc.md index eec191d62dd..47b8c29bfbc 100644 --- a/15/umbraco-commerce/release-notes/v15.0.0-rc.md +++ b/15/umbraco-commerce/release-notes/v15.0.0-rc.md @@ -65,7 +65,7 @@ public class MyNotification : NotificationEventHandlerBase Date: Tue, 12 Nov 2024 10:57:48 +0100 Subject: [PATCH 12/18] Update 15/umbraco-commerce/release-notes/v15.0.0-rc.md --- 15/umbraco-commerce/release-notes/v15.0.0-rc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/umbraco-commerce/release-notes/v15.0.0-rc.md b/15/umbraco-commerce/release-notes/v15.0.0-rc.md index 47b8c29bfbc..5727be9e5da 100644 --- a/15/umbraco-commerce/release-notes/v15.0.0-rc.md +++ b/15/umbraco-commerce/release-notes/v15.0.0-rc.md @@ -71,7 +71,7 @@ For the most part the API should stay the same, the key different being changes ## Umbraco v15 updates -As well as the async works, Umbraco Commerce v15 has also been updated to depend on Umbraco v15 which consists of the following updates. +In addition to the asynchronous work, Umbraco Commerce v15 has been updated to depend on Umbraco v15, which includes the following updates: * Runs against .NET 9 * Variants property editor supports content variants From 7c65bc5663994f12623f6d74d26be70d96095711 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:57:58 +0100 Subject: [PATCH 13/18] Update 15/umbraco-commerce/release-notes/v15.0.0-rc.md --- 15/umbraco-commerce/release-notes/v15.0.0-rc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/umbraco-commerce/release-notes/v15.0.0-rc.md b/15/umbraco-commerce/release-notes/v15.0.0-rc.md index 5727be9e5da..d20097469dc 100644 --- a/15/umbraco-commerce/release-notes/v15.0.0-rc.md +++ b/15/umbraco-commerce/release-notes/v15.0.0-rc.md @@ -78,6 +78,6 @@ In addition to the asynchronous work, Umbraco Commerce v15 has been updated to d ## What to Test and How to Give Feedback -We would welcome feedback on any installation / upgrade issues along with bugs found in any of the completed sections as detailed above. +We welcome any feedback on installation or upgrade issues, as well as any bugs found in the sections mentioned above. Issues can be raised on the Umbraco Commerce issue tracker at [https://github.com/umbraco/Umbraco.Commerce.Issues/issues](https://github.com/umbraco/Umbraco.Commerce.Issues/issues). From f3707a50d596150d5a4287620d6c1074e3f4adb4 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:20:53 +0100 Subject: [PATCH 14/18] Update 15/umbraco-commerce/SUMMARY.md --- 15/umbraco-commerce/SUMMARY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/15/umbraco-commerce/SUMMARY.md b/15/umbraco-commerce/SUMMARY.md index f0fc2425e01..445dab1519d 100644 --- a/15/umbraco-commerce/SUMMARY.md +++ b/15/umbraco-commerce/SUMMARY.md @@ -100,6 +100,7 @@ * [Content](reference/storefront-api/endpoints/content.md) * [Management API](reference/management-api/README.md) * [Go behind the scenes](reference/go-behind-the-scenes.md) +* [Telemetry](reference/telemetry/README.md) ## Tutorials From 3700cca0f181bc9ff8e89134a978f224c5564c26 Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Wed, 13 Nov 2024 10:40:02 +0000 Subject: [PATCH 15/18] Update 15/umbraco-commerce/key-concepts/unit-of-work.md Co-authored-by: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> --- 15/umbraco-commerce/key-concepts/unit-of-work.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/umbraco-commerce/key-concepts/unit-of-work.md b/15/umbraco-commerce/key-concepts/unit-of-work.md index 7faac1282ba..e66eb79b8b2 100644 --- a/15/umbraco-commerce/key-concepts/unit-of-work.md +++ b/15/umbraco-commerce/key-concepts/unit-of-work.md @@ -24,7 +24,7 @@ await _uowProvider.ExecuteAsync(async (uow) => ``` -The anatomy of a Unit of Work is an `ExecuteAsync` method call on the `IUnitOfWorkProvider` instance which accepts an async delegate function with a `uow` argument. Inside the delegate, we perform our tasks and confirm the Unit of Work as complete by calling `uow.Complete()`. If we fail to call `uow.Complete()` either due to forgetting to add the `uow.Complete()` call or due to an exception in our code, then any write operations that occur within that code block will **not** be persisted in the database. +The anatomy of a Unit of Work includes an `ExecuteAsync` method call on the `IUnitOfWorkProvider` instance. This method accepts an async delegate function with a `uow` argument. Inside the delegate, perform tasks and confirm the Unit of Work as complete by calling `uow.Complete()`. If you forget to call `uow.Complete()` or encounter an exception, then any write operations within that code will **not** be persisted in the database. ### Unit of Work Best Practice From d23f16d1e6120302a1143393d8b76838e74af449 Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Wed, 13 Nov 2024 10:40:26 +0000 Subject: [PATCH 16/18] Update 15/umbraco-commerce/release-notes/v15.0.0-rc.md Co-authored-by: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> --- 15/umbraco-commerce/release-notes/v15.0.0-rc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/umbraco-commerce/release-notes/v15.0.0-rc.md b/15/umbraco-commerce/release-notes/v15.0.0-rc.md index d20097469dc..46fe51994fc 100644 --- a/15/umbraco-commerce/release-notes/v15.0.0-rc.md +++ b/15/umbraco-commerce/release-notes/v15.0.0-rc.md @@ -67,7 +67,7 @@ public class MyNotification : NotificationEventHandlerBase Date: Wed, 13 Nov 2024 11:59:24 +0100 Subject: [PATCH 17/18] Update 15/umbraco-commerce/key-concepts/payment-providers.md --- 15/umbraco-commerce/key-concepts/payment-providers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/umbraco-commerce/key-concepts/payment-providers.md b/15/umbraco-commerce/key-concepts/payment-providers.md index 2ee18f3939c..bb69586fb96 100644 --- a/15/umbraco-commerce/key-concepts/payment-providers.md +++ b/15/umbraco-commerce/key-concepts/payment-providers.md @@ -54,7 +54,7 @@ Generally, there are three methods within a Payment Provider that you may need t * **GenerateFormAsync** - The `GenerateFormAsync` method generates an HTML form that will redirect the customer to the given payment gateway payment form. In this method you may need to communicate with the payment gateway to initialize a payment, letting the payment gateway know how much to capture. This often results in some kind of code or redirect URL being returned which will need to be embedded into the generated form. The form appears on a checkout **Review** page before payment, featuring a **Continue to Payment** button to submit the form and redirect to the gateway. * **ProcessCallbackAsync** - The `ProcessCallbackAsync` method handles the response coming back from the payment gateway and processing whether the payment was successful or not. This can occur _synchronously_, if the payment gateway sends information back during the confirmation page redirect. It can also occur _asynchronously_ if the payment gateway sends the information back via an out-of-band webhook request. -* **GetOrderReferenceAsync** - The `GetOrderReferenceAsync` method is responsible for extracting an order reference number from a request when the payment gateway uses an asynchronous webhook to finalize an Order **and** it uses a global webhook URL strategy for all notifications rather than a notification URL per transaction. Where a webhook URL can be passed per transaction, then Umbraco Commerce provides you with a unique callback URL you can register with the gateway that already identifies the order reference as part of the URL parameters, making implementing this method unnecessary. +* **GetOrderReferenceAsync** - The `GetOrderReferenceAsync` method extracts an order reference number from a request when a payment gateway uses an asynchronous webhook to finalize an order. This method is specifically used where the payment gateway uses a global webhook URL strategy for all notifications rather than a notification URL per transaction. Where a webhook URL can be passed per transaction, then Umbraco Commerce provides a unique callback URL that identifies the order reference as part of the URL parameters. When using the per transaction URL provided, implementing this method becomes unnecessary. _\* denotes a required method implementation_. From cd154dc25b8d01f76e3c7a2b6385464d6b85d0d1 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Wed, 13 Nov 2024 12:00:03 +0100 Subject: [PATCH 18/18] Update 15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md --- .../key-concepts/readonly-and-writable-entities.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md b/15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md index 35872f9eaaf..fefebea82fd 100644 --- a/15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md +++ b/15/umbraco-commerce/key-concepts/readonly-and-writable-entities.md @@ -17,7 +17,7 @@ The reason why we have split entities in this way for a number of reasons, howev ## Converting a ReadOnly entity into a Writable entity -To convert a ReadOnly entity into its Writable form, we achieve this by calling the entities `AsWritableAsync(uow)` method, passing in a valid Unit of Work instance to perform the write operations on. Once we have a Writable entity, we can then perform the write operations we desire and persist those changes back to the database. +To convert a ReadOnly entity to its Writable form, call the entity's `AsWritableAsync(uow)` method. Pass in a valid Unit of Work instance associated with this operation. Once a Writable entity is available, perform the desired write operations and persist the changes back to the database. ```csharp await _uowProvider.ExecuteAsync(async (uow) =>