Last updated

Working with baskets

A core part to the shopping experience using Norce Commerce Services is the Basket. This is the container to the list of items the visitor is interested in. The basket in Norce contains a lot of functionality and is dependent on many business rules that are evaluated and applied for every action the visitor does from your commerce application.

Aside from the most common use of the basket object (the cart), there is also other ways to use it. Like wish lists, approval/attests, saved for later, sent to punch out, subscriptions/recurring orders, etc. These functions are not addressed in this document.

An example basket

{
  "Id": 6600304,
  "CustomerId": null,
  "CompanyId": null,
  "SalesContactId": null,
  "StatusId": 3,
  "CurrencyId": 2,
  "CurrencyCode": "SEK",
  "Comment": null,
  "OrderReference": null,
  "DiscountCode": null,
  "ReferId": null,
  "ReferUrl": null,
  "ValidTo": null,
  "IsEditable": true,
  "Items": [
    {
      "Id": 16030464,
      "LineNo": 1,
      "ParentLineNo": null,
      "ProductId": 31234584,
      "PartNo": "PRD0001270",
      "ManufacturerPartNo": "T540XP",
      "Name": "T540XP",
      "SubHeader": "<p>Detta är en kort beskrivning.</p>",
      "ThumbnailImage": "2/thumb_p31234584.jpg",
      "FlagIdSeed": "915,1884",
      "Type": 1,
      "PriceDisplay": 5743.20,
      "Price": 0.00,
      "PriceOriginal": 5743.20,
      "Cost": 5734.34,
      "VatRate": 1.2500,
      "Quantity": 1.000,
      "UOM": "st",
      "UOMCount": 1.000,
      "Comment": null,
      "PriceListId": 4654,
      "ReferId": null,
      "ReferUrl": null,
      "IsEditable": true,
      "IsDiscountable": true,
      "Info": [
        {
          "TypeId": 209,
          "Value": "",
          "Code": "bit_size"
        },
        {
          "TypeId": 241,
          "Value": "",
          "Code": "bit_del_time"
        },
        {
          "TypeId": 95,
          "Value": "",
          "Code": "bit_additionalinformation"
        }
      ],
      "OptionalItems": [],
      "OnHandValue": 0.000,
      "IncomingValue": 0.000,
      "NextDeliveryDate": null,
      "LeadtimeDayCount": null,
      "PromotionIdSeed": "",
      "ImageKey": "39e4b7ec-12d8-4f6e-b9c1-cbd7334190e1",
      "ManufacturerName": "Husqvarna",
      "CategoryId": 41722,
      "OnHand": {
        "Value": 0.000,
        "IncomingValue": 0.000,
        "NextDeliveryDate": null,
        "LeadtimeDayCount": null,
        "LastChecked": null,
        "IsActive": false,
        "IsReturnable": true,
        "Info": null
      },
      "OnHandSupplier": {
        "Value": 200.000,
        "IncomingValue": 0.000,
        "NextDeliveryDate": null,
        "LeadtimeDayCount": 7,
        "LastChecked": null,
        "IsActive": true,
        "IsReturnable": true,
        "Info": null
      },
      "PriceRecommended": 7000.00,
      "ManufacturerId": 1685,
      "UniqueName": "t540xp",
      "StatusId": 1,
      "StockDisplayBreakPoint": null,
      "PriceCatalog": null,
      "IsBuyable": true,
      "SubDescription": null,
      "CategoryIdSeed": "41722",
      "RecommendedQuantity": 4.000,
      "IsRecommendedQuantityFixed": false,
      "AppliedPromotions": [],
      "RequirementPromotionIdSeed": "5093",
      "IsSubscribable": false,
      "DescriptionHeader": "Husqvarna T540XP",
      "IsPriceManual": false,
      "PriceStandard": 6375.20,
      "EanCode": "123123123123123",
      "CostUnit": 0.00,
      "PriceDisplayIncVat": 7179.00
    },
    {
      "Id": 16030465,
      "LineNo": 2,
      "ParentLineNo": null,
      "ProductId": 24706222,
      "PartNo": "PRD0001212",
      "ManufacturerPartNo": "FREIGHT01",
      "Name": "Freight",
      "SubHeader": null,
      "ThumbnailImage": null,
      "FlagIdSeed": "915",
      "Type": 3,
      "PriceDisplay": 0.00,
      "Price": 0.00,
      "PriceOriginal": 0.00,
      "Cost": 0.00,
      "VatRate": 1.25,
      "Quantity": 1.000,
      "UOM": "st",
      "UOMCount": 1.000,
      "Comment": null,
      "PriceListId": 1,
      "ReferId": null,
      "ReferUrl": null,
      "IsEditable": true,
      "IsDiscountable": true,
      "Info": [
        {
          "TypeId": 209,
          "Value": "",
          "Code": "bit_size"
        },
        {
          "TypeId": 241,
          "Value": "",
          "Code": "bit_del_time"
        },
        {
          "TypeId": 95,
          "Value": "",
          "Code": "bit_additionalinformation"
        }
      ],
      "OptionalItems": [],
      "OnHandValue": 0.000,
      "IncomingValue": 0.000,
      "NextDeliveryDate": null,
      "LeadtimeDayCount": 0,
      "PromotionIdSeed": null,
      "ImageKey": null,
      "ManufacturerName": "Miscellaneous",
      "CategoryId": null,
      "OnHand": {
        "Value": 0.000,
        "IncomingValue": 0.000,
        "NextDeliveryDate": null,
        "LeadtimeDayCount": 0,
        "LastChecked": "/Date(1325504774807+0100)/",
        "IsActive": true,
        "IsReturnable": true,
        "Info": null
      },
      "OnHandSupplier": {
        "Value": 0.000,
        "IncomingValue": 0.000,
        "NextDeliveryDate": null,
        "LeadtimeDayCount": null,
        "LastChecked": null,
        "IsActive": false,
        "IsReturnable": true,
        "Info": null
      },
      "PriceRecommended": null,
      "ManufacturerId": 4335,
      "UniqueName": "freight",
      "StatusId": 1,
      "StockDisplayBreakPoint": null,
      "PriceCatalog": null,
      "IsBuyable": true,
      "SubDescription": null,
      "CategoryIdSeed": "",
      "RecommendedQuantity": 1.000,
      "IsRecommendedQuantityFixed": false,
      "AppliedPromotions": [],
      "RequirementPromotionIdSeed": null,
      "IsSubscribable": false,
      "DescriptionHeader": null,
      "IsPriceManual": false,
      "PriceStandard": 0.00,
      "EanCode": "",
      "CostUnit": 0.00,
      "PriceDisplayIncVat": 0.00
    },
    {
      "Id": 0,
      "LineNo": 3,
      "ParentLineNo": 1,
      "ProductId": 31234588,
      "PartNo": "PRD0001274",
      "ManufacturerPartNo": "Underhållskit",
      "Name": "Underhållskit Motorsåg",
      "SubHeader": null,
      "ThumbnailImage": "2/thumb_p31234588.png",
      "FlagIdSeed": "915",
      "Type": 1,
      "PriceDisplay": 111.20,
      "Price": 0.00,
      "PriceOriginal": 111.20,
      "Cost": 100.25,
      "VatRate": 1.25,
      "Quantity": 1,
      "UOM": "st",
      "UOMCount": 1.000,
      "Comment": null,
      "PriceListId": 1,
      "ReferId": null,
      "ReferUrl": null,
      "IsEditable": false,
      "IsDiscountable": true,
      "Info": [
        {
          "TypeId": 209,
          "Value": "",
          "Code": "bit_size"
        },
        {
          "TypeId": 241,
          "Value": "",
          "Code": "bit_del_time"
        },
        {
          "TypeId": 95,
          "Value": "",
          "Code": "bit_additionalinformation"
        }
      ],
      "OptionalItems": [],
      "OnHandValue": 12.000,
      "IncomingValue": 0.000,
      "NextDeliveryDate": null,
      "LeadtimeDayCount": 0,
      "PromotionIdSeed": "",
      "ImageKey": null,
      "ManufacturerName": "Husqvarna",
      "CategoryId": 41722,
      "OnHand": {
        "Value": 12.000,
        "IncomingValue": 0.000,
        "NextDeliveryDate": null,
        "LeadtimeDayCount": 0,
        "LastChecked": null,
        "IsActive": true,
        "IsReturnable": true,
        "Info": null
      },
      "OnHandSupplier": {
        "Value": 133.000,
        "IncomingValue": 0.000,
        "NextDeliveryDate": null,
        "LeadtimeDayCount": 5,
        "LastChecked": "/Date(1487085555163+0100)/",
        "IsActive": true,
        "IsReturnable": true,
        "Info": null
      },
      "PriceRecommended": null,
      "ManufacturerId": 1685,
      "UniqueName": "underhallskit-motorsag",
      "StatusId": 1,
      "StockDisplayBreakPoint": null,
      "PriceCatalog": null,
      "IsBuyable": true,
      "SubDescription": null,
      "CategoryIdSeed": "41722",
      "RecommendedQuantity": 1.000,
      "IsRecommendedQuantityFixed": false,
      "AppliedPromotions": [],
      "RequirementPromotionIdSeed": "",
      "IsSubscribable": false,
      "DescriptionHeader": null,
      "IsPriceManual": false,
      "PriceStandard": 0.00,
      "EanCode": "345345345345345",
      "CostUnit": 0.00,
      "PriceDisplayIncVat": 139.00
    }
  ],
  "Info": [
    {
      "TypeId": 169,
      "Value": "",
      "Code": "bit_expecteddeliverydate"
    },
    {
      "TypeId": 293,
      "Value": "",
      "Code": "bit_additionalorderinfo"
    },
    {
      "TypeId": 445,
      "Value": "",
      "Code": "Norce_Gender"
    },
    {
      "TypeId": 493,
      "Value": "",
      "Code": "recurring"
    }
  ],
  "Summary": {
    "Items": {
      "Amount": 5854.40,
      "Vat": 1463.60,
      "AmountIncVat": 7318.00
    },
    "Freigt": {
      "Amount": 0.00,
      "Vat": 0.00,
      "AmountIncVat": 0.00
    },
    "Fees": {
      "Amount": 0.00,
      "Vat": 0.00,
      "AmountIncVat": 0.00
    },
    "Total": {
      "Amount": 5854.40,
      "Vat": 1463.60,
      "AmountIncVat": 7318.00
    }
  },
  "AppliedPromotions": [
    {
      "Id": 5093,
      "Name": "Add service",
      "Header": "",
      "ShortDescription": "",
      "Description1": "",
      "Description2": "",
      "StartDate": null,
      "EndDate": null,
      "ImageKey": null,
      "RequirementSeed": "3",
      "DiscountCode": null,
      "IsExcludedFromPriceCalculation": false,
      "AllowProductListing": false,
      "Images": [],
      "ProductFilters": [
        {
          "ManufacturerId": null,
          "CategorySeed": null,
          "TypeId": null,
          "ProductId": null,
          "VariantProductId": null,
          "PartNo": "PRD0001274",
          "PricelistId": 1,
          "FlagId": null
        },
        {
          "ManufacturerId": null,
          "CategorySeed": null,
          "TypeId": null,
          "ProductId": null,
          "VariantProductId": null,
          "PartNo": null,
          "PricelistId": null,
          "FlagId": 1884
        }
      ],
      "AppliedAmount": 0.00,
      "EffectSeed": "5",
      "FreightDiscountPct": null,
      "IsStackable": true,
      "AppliedAmountIncVat": 0.00
    }
  ],
  "IpAddress": "151.236.200.213",
  "AttestedBy": null,
  "TypeId": 1,
  "DoHold": false,
  "IsBuyable": true,
  "InvoiceReference": null,
  "PaymentMethodId": null,
  "DeliveryMethodId": 1,
  "SalesAreaId": 1
}


<Basket xmlns="Enferno.Services.Contracts.Expose.Shopping" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <Id>6600304</Id>
    <CustomerId i:nil="true"/>
    <CompanyId i:nil="true"/>
    <SalesContactId i:nil="true"/>
    <StatusId>3</StatusId>
    <CurrencyId>2</CurrencyId>
    <CurrencyCode>SEK</CurrencyCode>
    <Comment i:nil="true"/>
    <OrderReference i:nil="true"/>
    <DiscountCode i:nil="true"/>
    <ReferId i:nil="true"/>
    <ReferUrl i:nil="true"/>
    <ValidTo i:nil="true"/>
    <IsEditable>true</IsEditable>
    <Items>
        <BasketItem>
            <Id>16030464</Id>
            <LineNo>1</LineNo>
            <ParentLineNo i:nil="true"/>
            <ProductId>31234584</ProductId>
            <PartNo>PRD0001270</PartNo>
            <ManufacturerPartNo>T540XP</ManufacturerPartNo>
            <Name>T540XP</Name>
            <SubHeader>&lt;p&gt;Detta är en kort beskrivning.&lt;/p&gt;</SubHeader>
            <ThumbnailImage>2/thumb_p31234584.jpg</ThumbnailImage>
            <FlagIdSeed>915,1884</FlagIdSeed>
            <Type>1</Type>
            <PriceDisplay>5743.20</PriceDisplay>
            <Price>0.00</Price>
            <PriceOriginal>5743.20</PriceOriginal>
            <Cost>5734.34</Cost>
            <VatRate>1.25</VatRate>
            <Quantity>1</Quantity>
            <UOM>st</UOM>
            <UOMCount>1.000</UOMCount>
            <Comment i:nil="true"/>
            <PriceListId>4654</PriceListId>
            <ReferId i:nil="true"/>
            <ReferUrl i:nil="true"/>
            <IsEditable>true</IsEditable>
            <IsDiscountable>true</IsDiscountable>
            <Info>
                <Info>
                    <TypeId>209</TypeId>
                    <Value/>
                    <Code>bit_size</Code>
                </Info>
                <Info>
                    <TypeId>241</TypeId>
                    <Value/>
                    <Code>bit_del_time</Code>
                </Info>
                <Info>
                    <TypeId>95</TypeId>
                    <Value/>
                    <Code>bit_additionalinformation</Code>
                </Info>
            </Info>
            <OptionalItems/>
            <OnHandValue>0.000</OnHandValue>
            <IncomingValue>0.000</IncomingValue>
            <NextDeliveryDate i:nil="true"/>
            <LeadtimeDayCount i:nil="true"/>
            <PromotionIdSeed/>
            <ImageKey>39e4b7ec-12d8-4f6e-b9c1-cbd7334190e1</ImageKey>
            <ManufacturerName>Husqvarna</ManufacturerName>
            <CategoryId>41722</CategoryId>
            <OnHand xmlns:a="Enferno.Services.Contracts.Expose.Products">
                <a:Value>0.000</a:Value>
                <a:IncomingValue>0.000</a:IncomingValue>
                <a:NextDeliveryDate i:nil="true"/>
                <a:LeadtimeDayCount i:nil="true"/>
                <a:LastChecked i:nil="true"/>
                <a:IsActive>false</a:IsActive>
                <a:IsReturnable>true</a:IsReturnable>
                <a:Info i:nil="true" xmlns:b="Enferno.Services.Contracts.Expose"/>
            </OnHand>
            <OnHandSupplier xmlns:a="Enferno.Services.Contracts.Expose.Products">
                <a:Value>200.000</a:Value>
                <a:IncomingValue>0.000</a:IncomingValue>
                <a:NextDeliveryDate i:nil="true"/>
                <a:LeadtimeDayCount>7</a:LeadtimeDayCount>
                <a:LastChecked i:nil="true"/>
                <a:IsActive>true</a:IsActive>
                <a:IsReturnable>true</a:IsReturnable>
                <a:Info i:nil="true" xmlns:b="Enferno.Services.Contracts.Expose"/>
            </OnHandSupplier>
            <PriceRecommended>7000.00</PriceRecommended>
            <ManufacturerId>1685</ManufacturerId>
            <UniqueName>t540xp</UniqueName>
            <StatusId>1</StatusId>
            <StockDisplayBreakPoint i:nil="true"/>
            <PriceCatalog i:nil="true"/>
            <IsBuyable>true</IsBuyable>
            <SubDescription i:nil="true"/>
            <CategoryIdSeed>41722</CategoryIdSeed>
            <RecommendedQuantity>4.000</RecommendedQuantity>
            <IsRecommendedQuantityFixed>false</IsRecommendedQuantityFixed>
            <AppliedPromotions/>
            <RequirementPromotionIdSeed>5093</RequirementPromotionIdSeed>
            <IsSubscribable>false</IsSubscribable>
            <DescriptionHeader>Husqvarna T540XP</DescriptionHeader>
            <IsPriceManual>false</IsPriceManual>
            <PriceStandard>6375.20</PriceStandard>
            <EanCode>123123123123123</EanCode>
            <CostUnit>0.00</CostUnit>
            <PriceDisplayIncVat>7179.00</PriceDisplayIncVat>
        </BasketItem>
        <BasketItem>
            <Id>16030465</Id>
            <LineNo>2</LineNo>
            <ParentLineNo i:nil="true"/>
            <ProductId>24706222</ProductId>
            <PartNo>PRD0001212</PartNo>
            <ManufacturerPartNo>FREIGHT01</ManufacturerPartNo>
            <Name>Freight</Name>
            <SubHeader i:nil="true"/>
            <ThumbnailImage i:nil="true"/>
            <FlagIdSeed>915</FlagIdSeed>
            <Type>3</Type>
            <PriceDisplay>0.00</PriceDisplay>
            <Price>0.00</Price>
            <PriceOriginal>0.00</PriceOriginal>
            <Cost>0.00</Cost>
            <VatRate>1.25</VatRate>
            <Quantity>1</Quantity>
            <UOM>st</UOM>
            <UOMCount>1.000</UOMCount>
            <Comment i:nil="true"/>
            <PriceListId>1</PriceListId>
            <ReferId i:nil="true"/>
            <ReferUrl i:nil="true"/>
            <IsEditable>true</IsEditable>
            <IsDiscountable>true</IsDiscountable>
            <Info>
                <Info>
                    <TypeId>209</TypeId>
                    <Value/>
                    <Code>bit_size</Code>
                </Info>
                <Info>
                    <TypeId>241</TypeId>
                    <Value/>
                    <Code>bit_del_time</Code>
                </Info>
                <Info>
                    <TypeId>95</TypeId>
                    <Value/>
                    <Code>bit_additionalinformation</Code>
                </Info>
            </Info>
            <OptionalItems/>
            <OnHandValue>0.000</OnHandValue>
            <IncomingValue>0.000</IncomingValue>
            <NextDeliveryDate i:nil="true"/>
            <LeadtimeDayCount>0</LeadtimeDayCount>
            <PromotionIdSeed i:nil="true"/>
            <ImageKey i:nil="true"/>
            <ManufacturerName>Miscellaneous</ManufacturerName>
            <CategoryId i:nil="true"/>
            <OnHand xmlns:a="Enferno.Services.Contracts.Expose.Products">
                <a:Value>0.000</a:Value>
                <a:IncomingValue>0.000</a:IncomingValue>
                <a:NextDeliveryDate i:nil="true"/>
                <a:LeadtimeDayCount>0</a:LeadtimeDayCount>
                <a:LastChecked>2012-01-02T12:46:14.807</a:LastChecked>
                <a:IsActive>true</a:IsActive>
                <a:IsReturnable>true</a:IsReturnable>
                <a:Info i:nil="true" xmlns:b="Enferno.Services.Contracts.Expose"/>
            </OnHand>
            <OnHandSupplier xmlns:a="Enferno.Services.Contracts.Expose.Products">
                <a:Value>0.000</a:Value>
                <a:IncomingValue>0.000</a:IncomingValue>
                <a:NextDeliveryDate i:nil="true"/>
                <a:LeadtimeDayCount i:nil="true"/>
                <a:LastChecked i:nil="true"/>
                <a:IsActive>false</a:IsActive>
                <a:IsReturnable>true</a:IsReturnable>
                <a:Info i:nil="true" xmlns:b="Enferno.Services.Contracts.Expose"/>
            </OnHandSupplier>
            <PriceRecommended i:nil="true"/>
            <ManufacturerId>4335</ManufacturerId>
            <UniqueName>freight</UniqueName>
            <StatusId>1</StatusId>
            <StockDisplayBreakPoint i:nil="true"/>
            <PriceCatalog i:nil="true"/>
            <IsBuyable>true</IsBuyable>
            <SubDescription i:nil="true"/>
            <CategoryIdSeed/>
            <RecommendedQuantity>1.000</RecommendedQuantity>
            <IsRecommendedQuantityFixed>false</IsRecommendedQuantityFixed>
            <AppliedPromotions/>
            <RequirementPromotionIdSeed i:nil="true"/>
            <IsSubscribable>false</IsSubscribable>
            <DescriptionHeader i:nil="true"/>
            <IsPriceManual>false</IsPriceManual>
            <PriceStandard>0.00</PriceStandard>
            <EanCode/>
            <CostUnit>0.00</CostUnit>
            <PriceDisplayIncVat>0.00</PriceDisplayIncVat>
        </BasketItem>
        <BasketItem>
            <Id>0</Id>
            <LineNo>3</LineNo>
            <ParentLineNo>1</ParentLineNo>
            <ProductId>31234588</ProductId>
            <PartNo>PRD0001274</PartNo>
            <ManufacturerPartNo>Underhållskit</ManufacturerPartNo>
            <Name>Underhållskit Motorsåg</Name>
            <SubHeader i:nil="true"/>
            <ThumbnailImage>2/thumb_p31234588.png</ThumbnailImage>
            <FlagIdSeed>915</FlagIdSeed>
            <Type>1</Type>
            <PriceDisplay>111.20</PriceDisplay>
            <Price>0.00</Price>
            <PriceOriginal>111.20</PriceOriginal>
            <Cost>100.25</Cost>
            <VatRate>1.25</VatRate>
            <Quantity>1</Quantity>
            <UOM>st</UOM>
            <UOMCount>1.000</UOMCount>
            <Comment i:nil="true"/>
            <PriceListId>1</PriceListId>
            <ReferId i:nil="true"/>
            <ReferUrl i:nil="true"/>
            <IsEditable>false</IsEditable>
            <IsDiscountable>true</IsDiscountable>
            <Info>
                <Info>
                    <TypeId>209</TypeId>
                    <Value/>
                    <Code>bit_size</Code>
                </Info>
                <Info>
                    <TypeId>241</TypeId>
                    <Value/>
                    <Code>bit_del_time</Code>
                </Info>
                <Info>
                    <TypeId>95</TypeId>
                    <Value/>
                    <Code>bit_additionalinformation</Code>
                </Info>
            </Info>
            <OptionalItems/>
            <OnHandValue>12.000</OnHandValue>
            <IncomingValue>0.000</IncomingValue>
            <NextDeliveryDate i:nil="true"/>
            <LeadtimeDayCount>0</LeadtimeDayCount>
            <PromotionIdSeed/>
            <ImageKey i:nil="true"/>
            <ManufacturerName>Husqvarna</ManufacturerName>
            <CategoryId>41722</CategoryId>
            <OnHand xmlns:a="Enferno.Services.Contracts.Expose.Products">
                <a:Value>12.000</a:Value>
                <a:IncomingValue>0.000</a:IncomingValue>
                <a:NextDeliveryDate i:nil="true"/>
                <a:LeadtimeDayCount>0</a:LeadtimeDayCount>
                <a:LastChecked i:nil="true"/>
                <a:IsActive>true</a:IsActive>
                <a:IsReturnable>true</a:IsReturnable>
                <a:Info i:nil="true" xmlns:b="Enferno.Services.Contracts.Expose"/>
            </OnHand>
            <OnHandSupplier xmlns:a="Enferno.Services.Contracts.Expose.Products">
                <a:Value>133.000</a:Value>
                <a:IncomingValue>0.000</a:IncomingValue>
                <a:NextDeliveryDate i:nil="true"/>
                <a:LeadtimeDayCount>5</a:LeadtimeDayCount>
                <a:LastChecked>2017-02-14T16:19:15.163</a:LastChecked>
                <a:IsActive>true</a:IsActive>
                <a:IsReturnable>true</a:IsReturnable>
                <a:Info i:nil="true" xmlns:b="Enferno.Services.Contracts.Expose"/>
            </OnHandSupplier>
            <PriceRecommended i:nil="true"/>
            <ManufacturerId>1685</ManufacturerId>
            <UniqueName>underhallskit-motorsag</UniqueName>
            <StatusId>1</StatusId>
            <StockDisplayBreakPoint i:nil="true"/>
            <PriceCatalog i:nil="true"/>
            <IsBuyable>true</IsBuyable>
            <SubDescription i:nil="true"/>
            <CategoryIdSeed>41722</CategoryIdSeed>
            <RecommendedQuantity>1.000</RecommendedQuantity>
            <IsRecommendedQuantityFixed>false</IsRecommendedQuantityFixed>
            <AppliedPromotions/>
            <RequirementPromotionIdSeed/>
            <IsSubscribable>false</IsSubscribable>
            <DescriptionHeader i:nil="true"/>
            <IsPriceManual>false</IsPriceManual>
            <PriceStandard>0.00</PriceStandard>
            <EanCode>345345345345345</EanCode>
            <CostUnit>0.00</CostUnit>
            <PriceDisplayIncVat>139.00</PriceDisplayIncVat>
        </BasketItem>
    </Items>
    <Info>
        <Info>
            <TypeId>169</TypeId>
            <Value/>
            <Code>bit_expecteddeliverydate</Code>
        </Info>
        <Info>
            <TypeId>293</TypeId>
            <Value/>
            <Code>bit_additionalorderinfo</Code>
        </Info>
        <Info>
            <TypeId>445</TypeId>
            <Value/>
            <Code>Norce_Gender</Code>
        </Info>
        <Info>
            <TypeId>493</TypeId>
            <Value/>
            <Code>recurring</Code>
        </Info>
    </Info>
    <Summary>
        <Items>
            <Amount>5854.40</Amount>
            <Vat>1463.60</Vat>
            <AmountIncVat>7318.00</AmountIncVat>
        </Items>
        <Freigt>
            <Amount>0.00</Amount>
            <Vat>0.00</Vat>
            <AmountIncVat>0.00</AmountIncVat>
        </Freigt>
        <Fees>
            <Amount>0.00</Amount>
            <Vat>0.00</Vat>
            <AmountIncVat>0.00</AmountIncVat>
        </Fees>
        <Total>
            <Amount>5854.40</Amount>
            <Vat>1463.60</Vat>
            <AmountIncVat>7318.00</AmountIncVat>
        </Total>
    </Summary>
    <AppliedPromotions>
        <Promotion>
            <Id>5093</Id>
            <Name>Add service</Name>
            <Header/>
            <ShortDescription/>
            <Description1/>
            <Description2/>
            <StartDate i:nil="true"/>
            <EndDate i:nil="true"/>
            <ImageKey i:nil="true"/>
            <RequirementSeed>3</RequirementSeed>
            <DiscountCode i:nil="true"/>
            <IsExcludedFromPriceCalculation>false</IsExcludedFromPriceCalculation>
            <AllowProductListing>false</AllowProductListing>
            <Images xmlns:a="Enferno.Services.Contracts.Expose"/>
            <ProductFilters>
                <Filter>
                    <ManufacturerId i:nil="true"/>
                    <CategorySeed i:nil="true"/>
                    <TypeId i:nil="true"/>
                    <ProductId i:nil="true"/>
                    <VariantProductId i:nil="true"/>
                    <PartNo>PRD0001274</PartNo>
                    <PricelistId>1</PricelistId>
                    <FlagId i:nil="true"/>
                </Filter>
                <Filter>
                    <ManufacturerId i:nil="true"/>
                    <CategorySeed i:nil="true"/>
                    <TypeId i:nil="true"/>
                    <ProductId i:nil="true"/>
                    <VariantProductId i:nil="true"/>
                    <PartNo i:nil="true"/>
                    <PricelistId i:nil="true"/>
                    <FlagId>1884</FlagId>
                </Filter>
            </ProductFilters>
            <AppliedAmount>0.00</AppliedAmount>
            <EffectSeed>5</EffectSeed>
            <FreightDiscountPct i:nil="true"/>
            <IsStackable>true</IsStackable>
            <AppliedAmountIncVat>0.00</AppliedAmountIncVat>
        </Promotion>
    </AppliedPromotions>
    <IpAddress>151.236.200.213</IpAddress>
    <AttestedBy i:nil="true"/>
    <TypeId>1</TypeId>
    <DoHold>false</DoHold>
    <IsBuyable>true</IsBuyable>
    <InvoiceReference i:nil="true"/>
    <PaymentMethodId i:nil="true"/>
    <DeliveryMethodId>1</DeliveryMethodId>
    <SalesAreaId>1</SalesAreaId>
</Basket>

The basket data model

Basket data model

The basket contains many properties, here are some important ones.

  • Id, the identifier of the basket. For the visitors active basket, this is usually stored in a persisted cookie
  • Status, basket can have different statuses, depending on the usage. For a cart the most common are "Basket" (3), "Ready for payment" (7), "Payment pending" (12), "Payment Accepted" (8), "Order" (10).
  • Currency, if the application allowed for different currencies this field can be changed. The basket will the convert the prices and amounts to the chosen currency.
  • IsEditable and IsBuyable, in some instances the basket is locked and cannot be updated by the visitor or not able to be processed through a checkout. Some examples are when the basket has become an order, or during the checkout process.
  • Summary, this contains summary information on the total amount and freight.
  • Items, are a collection of all the products added to the basket, with
    • Id, the identifier of the BasketItem (this is required for the update calls)
    • LineNo, a friendly number of the row
    • ParentLineNo, for complex items (like packages), or for user friendly grouping of items
    • ProductId and PartNo, identifiers of the product. A basket item must be connected to a product in Norce Commerce
    • Type, the product type
    • PriceDisplay, the price in a friendly format, for read only
    • Quantity, number of items in the basket
    • PriceListId, the price list the price is based from
    • IsEditable, in some instances the basket item cannot be updated by the visitor
Restrictions

Norce handles quite a lot of the basket business logic behind the scenes.

For example if you add an item to the basket that already exists, Norce does not increment the existing row´s quantity, instead a new line is added to the basket. This is because many solutions needs to have this flexibility, for example: A B2B sales model often needs to separate items into rows and add delivery or invoice references separately for each item.

A common practice is to add these simplifications in your own backend in a service layer where your Norce Commerce requests pass through. This lets you simplify the workflow specific to your needs.

The update pattern

When working with baskets there is a lot of possible changes that will happen to the basket for every action the visitor does. Therefore Norce Commerce Shopping Service always return the whole basket object whenever a change is done. A good common practice is to have the basket stored in a cache, or (if concurrency is an issue i.e. if many clients work with the same lists) ask for the basket first before mapping in your changes and then call the update in the API.

Update pattern

  1. A user action has occurred.
  2. A basket object is fetched, either from Norce Commerce or from a local cache
  3. The changes are mapped into the basket item (from the model object)
  4. The update is called (UpdateBasket, UpdateBasketItem or similar)
  5. The whole basket is returned from Norce
  6. The returned basket is mapped to a model object, written to a local cache and returned to the front end

A basket can change even without user action. For example the state of an item can change so that it is not buyable anymore (not in stock anymore, status set to inactive, etc) or a campaign or a promotion can stop being valid. This is something that your application needs to take into consideration in the fault and exception handling.

Context

There is a lot of contextual information on all gets and updates that you need to make sure to always send in to Norce Commerce Services if you are using them, for example: pricelistSeed, cultureCode, currencyId. They are optional but if you use any one of them in your application, they need to be passed in on all calls.

Another input variable of note is the createdBy, that should be passed in when a known user is working with their baskets, if user is a guest/unknown set this to 1.

Lifecycle

Create Basket

A basket is created when the CreateBasket method is called. Preferably this is done when the first item(s) are added to the visitors basket. You can create a basket with default values, by passing in a whole basket object.

A good idea is to pass in CustomerId and CompanyId for logged in users, default PaymentMethodId and default DeliveryMethodId. Then you dont need to make these update calls in the checkout later.

Add Items

There are several methods to add items to the basket - InsertBasketItem, InsertBasketItems, InsertBasketItemsWithChildren, but also the UpdateBasketItem calls can increment the quantity on an existing item.

  • InsertBasketItem, takes a basketitem as payload and appends it to the basket items collection, generating a LineNo and a unique Id to the line.
  • InsertBasketItems, takes a collection of basketitems as payload and appends them to the basket items collection.
  • InsertBasketItemWithChildren, takes a collection of basketitems as payload and appends them to the basket items collection. The first item gets to be parent to all the others.
  • If you instead of appending wants to increment the quantity on already existing items you need to resolve it yourself before calling a basket metod. Use UpdateBasketItem or its sibling methods.
Recommended Quantity

Norce has a setting called RecommendedQuantity on the product, which suggest how many of the item that should automatically be added to the cart, check this field when calling InsertBasketItem.

Note that this field is not enforced by Norce, unless it it also followed with the setting IsRecommendedQuantityFixed then it is not possible to break up a multiple of the RecommendedQuantity value.

Remove Items

Use DeleteBasketItem to removes one whole row, UpdateBasketItem calls can decrement quantity on existing items and ClearBasket removes all items on the basket.

Note

UpdateBasketItem with quantity = 0 is the same as calling DeleteBasketItem.

Change Basket

Use UpdateBasket2 to change information on the header of the basket, like status, comment fields, etc. (mostly this is done in the checkout process, see the checkout guide )

Change BasketItems

UpdateBasketItem, UpdateBasketItems lets you update item information on one or several items at the same time. A required field to send in to Norce Commerce Shopping Service is the Id on the item, without it the update wont take. Make sure to keep it in your cache. Most common field to update is the Quantity of course, but other fields are Comment and Price, read more about this in the checkout process. Read also about some common scenarios under common business logic below.

Remove or reopen the basket

When a basket has been successfully processed through the checkout the status is changed to "Payment Accepted" or a bit later to "Order". Then the basket is locked and should be removed from the active basket slot in session and cookie. If a basket is still there your application should remove it silently and create a new basket when the end customer needs it.

If anything happened on a basket that has moved further in the process, you might not be allowed to continue to make changes on it. An easy way to keep the items and information on the basket is to create a new one passing in the old. Everything that is allowed to be updated to the new one will be. You clone an old basket by calling CreateBasket with the old one as payload.

See a postman example here.

Common business logic

There are some more common business logic that is handled from the basket management code on your side.

Overriding the price

In some scenarios, you might want to manually override the calculated price from Norce. This might be if you create a sales quotation, or want to add an offer to the item from a 3rd party. To do this you must add your new price in the InsertBasketItem or UpdateBasketItem in the field Price, and confirm this by specifically adding IsPriceManual : true as well.

Note the the Price field takes the unit price, not the row amount.

Here is an example:


{
  "PartNo": "TestPartNo",
  "Price": 160.00,
  "Quantity": 1.000,
  "Comment": "This is an insert of a manual price to a new row in the basket",
  "PriceListId": 1,
  "IsPriceManual": true
}

Then the returned basket item looks like this (shortened):


{
  "LineNo": 1,
  "PartNo": "TestPartNo",
  "PriceDisplay": 160.00,
  "Price": 0.00,
  "PriceOriginal": 160.00,
  "Quantity": 1.000,
  "PriceListId": 1,
  "IsPriceManual": true,
  "PriceDisplayIncVat": 200.00
}

Note that the field Price is 0 in the result, instead, the manual price is on PriceDisplay, just as with any normal price, to recognize this price as a manual price you must check the IsPriceManual field.

Lock the item to a price list

In some scenarios, you might want to lock the price to a specific price list. This will override any default "best price validations" that Norce normally do on the basket items. This makes it possible to override Norce's best price calculation and point to a specific price list that should be used.

Some use cases:

  1. The solution should use a price list (agreement) that has a higher price than the current campaign, but might give additional warranties or other prefered value to the customer.
  2. The solution should set the reservation to a specific warehouse/location. Lock the item to a price list, connected to this warehouse. Read about connected warehouses and reservation, for more info.

To lock the price to a price list, you must add PriceListLocked : true your the basket item in the InsertBasketItem or UpdateBasketItem.

Here is an example:


{
  "PartNo": "TestPartNo",
  "Quantity": 1.000,
  "Comment": "This is an insert of locked price list to a new row in the basket",
  "PriceListId": 15320,
  "PriceListLocked": true
}

Then the returned basket item looks like this (shortened):


{
  "LineNo": 1,
  "PartNo": "TestPartNo",
  "PriceDisplay": 6000.00,
  "Price": 0.00,
  "PriceOriginal": 6000.00,
  "Quantity": 1.000,
  "PriceListId": 15320,
  "PriceStandard": 5900.00,
  "PriceDisplayIncVat": 7500.00,
  "PriceListLocked": true
}

Note that the PriceStandard amount might be lower than the current PriceDisplay here, since this is a locked price.

PriceListLocked might return to false if

  • You call an update to the shoppingservice, or
  • The price list is no longer active on the product

Additional isEditable and isBuyable logic

Some clients wants to have more restrictions on what the basket than Norce provides, this could foe example be when a basket is buyable and not. This could be a validation on products that they should be in-stock for example. Or even more complex logic than that.


public bool Buyable(Basket basket)
{
    if (basket.isBuyable)
    {
        //Check my custom logic as well (for example, that all products are in stock)
        return true;
    } else
        return false;
}

Streamline basket processes

Event though Norce Commerce is flexible, some client solutions could benefit from a simplified view that is tailored to their needs. Examples:

  • Add item with RecommendedQuantity set
  • Add an already existing item as +1 to quantity
  • Handle certain flagged products differently
  • Handle overrides of prices as manual prices

Extend the basket model

Many cases the client has need of extending the basket model adding properties as info types in Norce Commerce Shopping Service. A common practice is to map these additional field to an extension to your basket model, so make it easier to use.

Promotions

Baskets applies promotions automatically if the requirements are valid. This means that prices or new items can suddenly be shown on a baskets depending of the effects. All applied promotions are are listed in the AppliedPromotions list on the basket and on the basket item as well.

Some promotions are applied using a code. Use UpdateBasket and set the DiscountCode property to enable these kind of promotions. If no such promotion exists or if it isnt valid, the basket will simply not show a discount code after update.

See a Postman example here.

Complex items

Norce Commerce allowes for more complex items to be added to the basket. By that we mean items containing other items. Use the ParentLineNo to display these items in an appropriate manner in the UI.

To simplify handling of these items there are some additional methods:

Examples of items that use this functionality is products of type ManagedStructure, ManagedErpPackage and ManagedErpPackageWithCalc and their Unmanaged counterparts.

Samples in Postman

We have some good samples on how to work with baskets here.

Suggested further reading