Price integration
Prices are either handles in Norce and then sent to the ERP or the other way around.
Update prices in Norce
For some client some prices are calculated in the ERP, in those cases it is often one standard price for each product, but can also be many other different price lists, like contract prices for specific customers (companies) or temporary campaigns.
These are imported using Norce Commerce Connect. The endpoints that can be used are:
- ImportProducts ImportProducts allows for one price list to be added to the large contract of updating almost everything else on the product. This could be any price list, but only one is allowed.
- ImportSkuPriceList ImportSkuPriceList takes many pricelists and products at a time, use this if you have many prices that needs to be updated and more often than other product data.
- ImportPriceList ImportPriceList updates metadata on the price list, not on the products. Use this to create or update new price lists. For example if you get new Contract price lists
Important information
Field | Entity | Description | Usage |
---|---|---|---|
PartNo | SkuPriceList | Required, identifies the product that should be updated | |
PriceListCode / Code | SkuPriceList / PriceList | Required, identifies the pricelist | |
IsActive | SkuPriceList | Default is true. If you send in PriceSale, it will forcibly be set to true. | |
PriceCatalog | SkuPriceList | A alternative amount, to keep track of | |
PriceRecommended | SkuPriceList | An alternative amount to keep track of | |
PriceSale | SkuPriceList | If sent in, the price rule will automatically be set to "fixed price" and isactive will be set to true | |
QuantityBreak | SkuPriceList | Threshold value, determines minimum number of items required for getting this price, you can have many prices therefore on same product and price list, if they have different quantitybreak | |
Name | PriceList | Name of the price list | |
CurrencyCode | PriceList | the currency of the price list (The data model allows for different currency on each price record, but this functionality is deprecated. All prices should be in same currency as is defined on its price list, if you find discrepancies this is an error that should be reported) | |
StartDate | PriceList | Optional start date | |
EndDate | PriceList | Optional end date | |
IsPublic | PriceList | a flag that decides if the pricelist is public on the application (the application specified in the http header), which means that it will be automatically applied on the application. | |
(Warehouse)Code | Warehouse | Pricelists should have at least one warehouse and location, decides which warehouses that should be part of the availability aggregations in Norce | |
(Location)Code | WarehouseLocation | Pricelists should have at least one warehouse and location, decides which warehouses that should be part of the availability aggregations in Norce |
Example calling ImportSkuPriceList in Norce Commerce Connect
https://connect.lab.storm.io/4.0//api/Product/ImportSkuPriceLists
- Simple import with fixed prices only
{ "AccountId": 0, "FullFile": false, "SerializationType": 0, "_SkuPriceListFieldsThatAreSet_Explanation": "PriceSale", "SkuPriceListFieldsThatAreSet": [3] }
[ { "_comment": "import fixed price ", "PartNo": "266639", "PriceListCode": "pl_campaign_mm", "PriceSale": 100, "QuantityBreak": 1 }, { "_comment": "import fixed price, w qty break", "PartNo": "266639", "PriceListCode": "pl_campaign_mm", "PriceSale": 90, "QuantityBreak": 10 } ]
- Import with other price fields, except SalePrice The price record is not activated by the integration, require population rule and price rules on the price list. Some fields will be ignored if they are null, while some others will update the price record with null.
{ "AccountId": 0, "FullFile": false, "_IgnoreSkuPriceListFieldsWhenEmpty_Explanation": "CostPurchase, PriceRecommended", "IgnoreSkuPriceListFieldsWhenEmpty": [4, 6], "SerializationType": 0, "_SkuPriceListFieldsThatAreSet_Explanation": "CostUnit, PriceRecommended, IsActive", "SkuPriceListFieldsThatAreSet": [5, 6, 10] }
[ { "_comment": "Price recommended and cost will be updated, overwrite values that already exist", "CostUnit": 2000, "CurrencyCode": "SEK", "IsActive": 1, "PartNo": "ERPPartNo0000004-1", "PriceListCode": "STD", "PriceRecommended": 4999, "QuantityBreak": 1 }, { "_comment": "Price recommended will be updated, costs will be ignored since they are null", "CostUnit": null, "CurrencyCode": "SEK", "IsActive": 1, "PartNo": "ERPPartNo0000004-2", "PriceListCode": "STD", "PriceRecommended": 5999, "QuantityBreak": 1 } ]
Company price lists
To set company or customer price lists you need to do three things
- Create the price list
- Update the price list with SkuPriceList items
- Add the price list to the customer or company
Example calling ImportPriceList in Norce Commerce Connect
- Create a price list
https://connect.lab.storm.io/4.0//api/Product/ImportPriceLists
{ "AccountId": 0, "FullFile": false, "_PriceListFieldsThatAreSet_Explanation": "Name, CurrencyCode, StartDate, EndDate, IsPublic, Warehouses, Description", "PriceListFieldsThatAreSet": [0, 1, 2, 3, 4, 7, 9], "SerializationType": 0, "_WarehouseFieldsThatAreSet_Explanation": "No values, only code is used.", "WarehouseFieldsThatAreSet": [], "_WarehouseLocationFieldsThatAreSet_Explanation": "No values, only code is used.", "WarehouseLocationFieldsThatAreSet": [] }
[ { "_comment": "Company price list, with fixed price rule Use recommended price Fixed price", "Code": "ContractYYY", "CurrencyCode": "SEK", "Description": "Price list from the ERP System with contract prices for Company XXX", "EndDate": "2025-10-01Z", "IsPublic": false, "Name": "Contract prices for customer XXX", "StartDate": "2023-04-01Z", "Warehouses": [ { "_comment": "A price list must have association to at least one warehouse.", "Code": "STD", "Locations": [ { "Code": "STD" } ] } ] } ]
- Update SkuPriceLists
Same as examples above
- Add the price list to the customer or company (showing Companies, since that is the most common scenario)
https://connect.lab.storm.io/4.0/api/Customer/ImportCompanies
{ "AccountId": 0, "FullFile": false, "_AccountFieldsThatAreSet_Explanation": "n/a", "AccountFieldsThatAreSet": [], "_CompanyFieldsThatAreSet_Explanation": "Code, PriceLists", "CompanyFieldsThatAreSet": [2, 19], "_CustomerFieldsThatAreSet_Explanation": "None", "CustomerFieldsThatAreSet": [] }
[ { "Id": null, "Code": "XXX", "Name": "Company XXX", "PriceLists": [ { "Code": "ContractYYY", "IsExclusive": false } ] } ]
Update prices in ERP
For many scenarios, prices are handled in Norce, and later passed on to other systems, like the ERP. In this case, the ERP can handle other related information like cost that Norce need to set up its rules, see cost (coming) for more. But the primary responsibility for the ERP integration is to listen for changes to the prices in Norce and pass those on to the ERP. This is done by listening to events and calling Norce Commerce Query for the relevant information.
For Norce [Storm] clients:
Important information
The most important fields and their purpose:
Field | Entity | Description |
---|---|---|
PartNo | ProductSkuPricelist | Identifies the product |
PriceListId | ProductSkuPricelist | Identifies the price list (internal norce id, lookup id from code in separate lookup) |
QtyBreak | ProductSkuPricelist | Threshold value, determines minimum number of items required for getting this price, you can have many prices therefore on same product and price list, if they have different quantitybreak |
CurrencyId | ProductSkuPricelist | the currency of the price list (internal Norce id, lookup id form code in separate lookup) |
PriceSale | ProductSkuPricelist | calculated sale price, either a fixed value or calculated based on price rules |
CostPurchase | ProductSkuPricelist | the cost of the item or service when purchased from supplier, see cost (coming) for more. |
PriceStandard | ProductSkuPricelist | old price, inherited from parent, is null if no parent price list exist |
PriceRecommended | ProductSkuPricelist | recommended price, MSRP. Can be inherited from parent or from supplier |
ChosenSupplierId | ProductSkuPricelist | if exist, there is a preferred supplier that the pricing business rules uses, lookup the supplier code separately if needed. |
ChosenSupplierPartNo | ProductSkuPricelist | the product identifier for the supplier, if you need to create a purchase request |
ChosenSupplierPriceListId | ProductSkuPricelist | the supplier's price list id, lookup separately if needed |
ChosenSupplierQtyBreak | ProductSkuPricelist | threshold value from the supplier pricelist (rarely used) |
IsActive | ProductSkuPricelist | if false, the price is disabled and the product is disabled on the pricelist, note that a disabled price record is no longer updated from business rules in Norce. |
An example fetching price information from Norce Commerce Query
https://query.lab.storm.io/2.0//Products/ProductSkuPriceLists?$filter=in ('MyPartNo1', 'MyPartNo2') and PriceListId eq 1 and IsActive eq true&$select=PartNo,PriceListId,QtyBreak,CurrencyId,PriceSale,CostPurchase,PriceStandard,PriceRecommended,ChosenSupplierId,ChosenSupplierPartNo,ChosenSupplierPriceListId,ChosenSupplierQtyBreak
{ "@odata.context": "https://query.lab.storm.io/Query/2.0/Products/$metadata#ProductSkuPriceLists(PartNo,PriceListId,QtyBreak,CurrencyId,PriceSale,CostPurchase,PriceStandard,PriceRecommended,ChosenSupplierId,ChosenSupplierPartNo,ChosenSupplierPriceListId,ChosenSupplierQtyBreak)", "value": [ { "PartNo": "MyPartNo1", "PriceListId": 1, "QtyBreak": 1, "CurrencyId": 2, "PriceSale": 6375.2000, "CostPurchase": 5734.3440, "PriceStandard": 0.0000, "PriceRecommended": null, "ChosenSupplierId": 1545, "ChosenSupplierPartNo": "MySupplierPartNo1", "ChosenSupplierPriceListId": 16810, "ChosenSupplierQtyBreak": 1 }, { "PartNo": "MyPartNo2", "PriceListId": 1, "QtyBreak": 1, "CurrencyId": 2, "PriceSale": 583.0645, "CostPurchase": 1087.5480, "PriceStandard": 0.0000, "PriceRecommended": null, "ChosenSupplierId": 1545, "ChosenSupplierPartNo": "MySupplierPartNo2", "ChosenSupplierPriceListId": 16810, "ChosenSupplierQtyBreak": 1 } ] }
Event settings
Add events that should be used
You can either listen to SkuChangedNotification or SkuPriceChangedNotification.
SkuPriceChangedNotification is easier to set up, but will only trigger if SalePrice has changed, other changes, like PriceRecommended or a Cost will not trigger the event.
SkuPriceListChangedNotification will return several fields in the event message that you can use:
- PartNo
- PricelistId
- PricelistCode
- PriceSaleValue
- QuantityBreak
SkuPriceChangedNotification only includes PartNo and EntityChanged, and you must look up additional information in the Norce Commerce Query API. Below is an example of the required configuration:
Entity | On Insert | On Update | On Delete | Filter |
---|---|---|---|---|
tClientProductSkuPriceList | Yes | Yes (see important fields above) | No | Filter on relevant price lists that the ERP needs |
Note that there is only one configured event per client and type, so if you already need SkuChangedNotification to other integrations, you need to add these settings to the same listener and merge your business logic.
Optional metadata
To get more information on entities referred only with an id in query, you need to do extra lookups. Make sure to look up many at a time, instead of doing lookups for each product fetch. Put the response in your memory cache instead.
Price Lists
To access price list information, you can use two key endpoints:
ClientPriceLists
This endpoint provides detailed information about individual price lists, including their start and end dates, name, currency, and other metadata.ApplicationPricelist This endpoint lists all price lists specifically associated with the application, such as public price lists. It includes an important attribute, IsPrimary, which identifies the main price list for the application. This primary price list contains the standard prices and assortments.
Field | Entity | Description |
---|---|---|
PriceListId | ClientPriceList | Identifies the price list (internal norce id, lookup id from code in separate lookup) |
Name | ClientPriceList | Name of the price list in the default language |
Agreement | ClientPriceList | Identifier of the Price list (Note, renamed to Code in all contracts) |
CurrencyId | ClientPriceList | the currency of the price list (internal Norce id, lookup id form code in separate lookup) |
ParentPriceListId | ClientPriceList | point to the parent, if one exist |
StartDate | ClientPriceList | Optional start date |
EndDate | ClientPriceList | Optional end date |
SalesAreaId | ClientPriceList | Price lists can be tag:ed with a sales area, this lets Norce calculate and round prices correctly for prices inc vat |
Note, the entity PriceList has some of the same fields as ClientPriceList, they are mostly deprecated, use ClientPriceList!
An example fetching price list information from Norce Commerce Query
Fetching all price lists https://query.lab.storm.io/2.0/Application/ClientPriceLists?$select=PriceListId,Name,Agreement,CurrencyId,ParentPriceListId,StartDate,EndDate,SalesAreaId
Fetching the primary price list for the current application: https://query.lab.storm.io/2.0/Application/ApplicationPriceLists?$filter=IsPrimary eq true
Lookup currency https://query.lab.storm.io/2.0/Core/Currencies
Sales area, see here
Supplier information
Sometimes you want additional supplier information about the price from Norce.
Note, you can read more about suppliers here (coming) .
An example lookup up more on chosen supplier from Norce Commerce Query
https://query.lab.storm.io/2.0/Products/SupplierProductSkus?$filter=PartNo eq 'chosensupplierpartno' and SupplierId eq supplierid&$expand=PriceLists($expand=PriceList($select=Id,DefaultName,Code);$select=SupplierId,SupplierPriceListId,QtyBreak,CurrencyId,CostPurchase,CostPurchaseLastChecked;$filter=SupplierPriceListId eq 16810),OnHands($select=WarehouseId,LocationId,OnHandValue,OnHandLastChecked)&$select=PartNo,SupplierId,Name
{ "@odata.context": "https://query.lab.storm.io/Query/2.0/Products/$metadata#SupplierProductSkus(PartNo,SupplierId,Name,PriceLists(SupplierId,SupplierPriceListId,QtyBreak,CurrencyId,CostPurchase,CostPurchaseLastChecked,PriceList(Id,DefaultName,Code)),OnHands(WarehouseId,LocationId,OnHandValue,OnHandLastChecked))", "value": [ { "PartNo": "chosensupplierpartno", "SupplierId": chosensupplierid, "Name": "", "PriceLists": [ { "SupplierId": chosensupplierid, "SupplierPriceListId": chosensupplierpricelistid, "QtyBreak": 1, "CurrencyId": 1, "CostPurchase": 580.0000, "CostPurchaseLastChecked": "2017-02-14T09:40:44.96+01:00", "PriceList": { "Id": 16810, "DefaultName": "Premium Supplies Standard Pricelist", "Code": "STD1" } } ], "OnHands": [ { "WarehouseId": 811, "LocationId": 811, "OnHandValue": 100.000, "OnHandLastChecked": "2017-02-14T09:40:44.96+01:00" } ] } ] }