This is page 42 of 43. Use http://codebase.md/taurgis/sfcc-dev-mcp?page={x} to view the full context. # Directory Structure ``` ├── .DS_Store ├── .github │ ├── dependabot.yml │ ├── instructions │ │ ├── mcp-node-tests.instructions.md │ │ └── mcp-yml-tests.instructions.md │ ├── ISSUE_TEMPLATE │ │ ├── bug_report.yml │ │ ├── config.yml │ │ ├── documentation.yml │ │ ├── feature_request.yml │ │ └── question.yml │ ├── PULL_REQUEST_TEMPLATE │ │ ├── bug_fix.md │ │ ├── documentation.md │ │ └── new_tool.md │ ├── pull_request_template.md │ └── workflows │ ├── ci.yml │ ├── deploy-pages.yml │ ├── publish.yml │ └── update-docs.yml ├── .gitignore ├── .husky │ └── pre-commit ├── aegis.config.docs-only.json ├── aegis.config.json ├── aegis.config.with-dw.json ├── AGENTS.md ├── ai-instructions │ ├── claude-desktop │ │ └── claude_custom_instructions.md │ ├── cursor │ │ └── .cursor │ │ └── rules │ │ ├── debugging-workflows.mdc │ │ ├── hooks-development.mdc │ │ ├── isml-templates.mdc │ │ ├── job-framework.mdc │ │ ├── performance-optimization.mdc │ │ ├── scapi-endpoints.mdc │ │ ├── security-patterns.mdc │ │ ├── sfcc-development.mdc │ │ ├── sfra-controllers.mdc │ │ ├── sfra-models.mdc │ │ ├── system-objects.mdc │ │ └── testing-patterns.mdc │ └── github-copilot │ └── copilot-instructions.md ├── CHANGELOG.md ├── CONTRIBUTING.md ├── docs │ ├── best-practices │ │ ├── cartridge_creation.md │ │ ├── isml_templates.md │ │ ├── job_framework.md │ │ ├── localserviceregistry.md │ │ ├── ocapi_hooks.md │ │ ├── performance.md │ │ ├── scapi_custom_endpoint.md │ │ ├── scapi_hooks.md │ │ ├── security.md │ │ ├── sfra_client_side_js.md │ │ ├── sfra_controllers.md │ │ ├── sfra_models.md │ │ └── sfra_scss.md │ ├── dw_campaign │ │ ├── ABTest.md │ │ ├── ABTestMgr.md │ │ ├── ABTestSegment.md │ │ ├── AmountDiscount.md │ │ ├── ApproachingDiscount.md │ │ ├── BonusChoiceDiscount.md │ │ ├── BonusDiscount.md │ │ ├── Campaign.md │ │ ├── CampaignMgr.md │ │ ├── CampaignStatusCodes.md │ │ ├── Coupon.md │ │ ├── CouponMgr.md │ │ ├── CouponRedemption.md │ │ ├── CouponStatusCodes.md │ │ ├── Discount.md │ │ ├── DiscountPlan.md │ │ ├── FixedPriceDiscount.md │ │ ├── FixedPriceShippingDiscount.md │ │ ├── FreeDiscount.md │ │ ├── FreeShippingDiscount.md │ │ ├── PercentageDiscount.md │ │ ├── PercentageOptionDiscount.md │ │ ├── PriceBookPriceDiscount.md │ │ ├── Promotion.md │ │ ├── PromotionMgr.md │ │ ├── PromotionPlan.md │ │ ├── SlotContent.md │ │ ├── SourceCodeGroup.md │ │ ├── SourceCodeInfo.md │ │ ├── SourceCodeStatusCodes.md │ │ └── TotalFixedPriceDiscount.md │ ├── dw_catalog │ │ ├── Catalog.md │ │ ├── CatalogMgr.md │ │ ├── Category.md │ │ ├── CategoryAssignment.md │ │ ├── CategoryLink.md │ │ ├── PriceBook.md │ │ ├── PriceBookMgr.md │ │ ├── Product.md │ │ ├── ProductActiveData.md │ │ ├── ProductAttributeModel.md │ │ ├── ProductAvailabilityLevels.md │ │ ├── ProductAvailabilityModel.md │ │ ├── ProductInventoryList.md │ │ ├── ProductInventoryMgr.md │ │ ├── ProductInventoryRecord.md │ │ ├── ProductLink.md │ │ ├── ProductMgr.md │ │ ├── ProductOption.md │ │ ├── ProductOptionModel.md │ │ ├── ProductOptionValue.md │ │ ├── ProductPriceInfo.md │ │ ├── ProductPriceModel.md │ │ ├── ProductPriceTable.md │ │ ├── ProductSearchHit.md │ │ ├── ProductSearchModel.md │ │ ├── ProductSearchRefinementDefinition.md │ │ ├── ProductSearchRefinements.md │ │ ├── ProductSearchRefinementValue.md │ │ ├── ProductVariationAttribute.md │ │ ├── ProductVariationAttributeValue.md │ │ ├── ProductVariationModel.md │ │ ├── Recommendation.md │ │ ├── SearchModel.md │ │ ├── SearchRefinementDefinition.md │ │ ├── SearchRefinements.md │ │ ├── SearchRefinementValue.md │ │ ├── SortingOption.md │ │ ├── SortingRule.md │ │ ├── Store.md │ │ ├── StoreGroup.md │ │ ├── StoreInventoryFilter.md │ │ ├── StoreInventoryFilterValue.md │ │ ├── StoreMgr.md │ │ ├── Variant.md │ │ └── VariationGroup.md │ ├── dw_content │ │ ├── Content.md │ │ ├── ContentMgr.md │ │ ├── ContentSearchModel.md │ │ ├── ContentSearchRefinementDefinition.md │ │ ├── ContentSearchRefinements.md │ │ ├── ContentSearchRefinementValue.md │ │ ├── Folder.md │ │ ├── Library.md │ │ ├── MarkupText.md │ │ └── MediaFile.md │ ├── dw_crypto │ │ ├── CertificateRef.md │ │ ├── CertificateUtils.md │ │ ├── Cipher.md │ │ ├── Encoding.md │ │ ├── JWE.md │ │ ├── JWEHeader.md │ │ ├── JWS.md │ │ ├── JWSHeader.md │ │ ├── KeyRef.md │ │ ├── Mac.md │ │ ├── MessageDigest.md │ │ ├── SecureRandom.md │ │ ├── Signature.md │ │ ├── WeakCipher.md │ │ ├── WeakMac.md │ │ ├── WeakMessageDigest.md │ │ ├── WeakSignature.md │ │ └── X509Certificate.md │ ├── dw_customer │ │ ├── AddressBook.md │ │ ├── AgentUserMgr.md │ │ ├── AgentUserStatusCodes.md │ │ ├── AuthenticationStatus.md │ │ ├── Credentials.md │ │ ├── Customer.md │ │ ├── CustomerActiveData.md │ │ ├── CustomerAddress.md │ │ ├── CustomerCDPData.md │ │ ├── CustomerContextMgr.md │ │ ├── CustomerGroup.md │ │ ├── CustomerList.md │ │ ├── CustomerMgr.md │ │ ├── CustomerPasswordConstraints.md │ │ ├── CustomerPaymentInstrument.md │ │ ├── CustomerStatusCodes.md │ │ ├── EncryptedObject.md │ │ ├── ExternalProfile.md │ │ ├── OrderHistory.md │ │ ├── ProductList.md │ │ ├── ProductListItem.md │ │ ├── ProductListItemPurchase.md │ │ ├── ProductListMgr.md │ │ ├── ProductListRegistrant.md │ │ ├── Profile.md │ │ └── Wallet.md │ ├── dw_extensions.applepay │ │ ├── ApplePayHookResult.md │ │ └── ApplePayHooks.md │ ├── dw_extensions.facebook │ │ ├── FacebookFeedHooks.md │ │ └── FacebookProduct.md │ ├── dw_extensions.paymentrequest │ │ ├── PaymentRequestHookResult.md │ │ └── PaymentRequestHooks.md │ ├── dw_extensions.payments │ │ ├── SalesforceBancontactPaymentDetails.md │ │ ├── SalesforceCardPaymentDetails.md │ │ ├── SalesforceEpsPaymentDetails.md │ │ ├── SalesforceIdealPaymentDetails.md │ │ ├── SalesforceKlarnaPaymentDetails.md │ │ ├── SalesforcePaymentDetails.md │ │ ├── SalesforcePaymentIntent.md │ │ ├── SalesforcePaymentMethod.md │ │ ├── SalesforcePaymentRequest.md │ │ ├── SalesforcePaymentsHooks.md │ │ ├── SalesforcePaymentsMgr.md │ │ ├── SalesforcePaymentsSiteConfiguration.md │ │ ├── SalesforcePayPalOrder.md │ │ ├── SalesforcePayPalOrderAddress.md │ │ ├── SalesforcePayPalOrderPayer.md │ │ ├── SalesforcePayPalPaymentDetails.md │ │ ├── SalesforceSepaDebitPaymentDetails.md │ │ └── SalesforceVenmoPaymentDetails.md │ ├── dw_extensions.pinterest │ │ ├── PinterestAvailability.md │ │ ├── PinterestFeedHooks.md │ │ ├── PinterestOrder.md │ │ ├── PinterestOrderHooks.md │ │ └── PinterestProduct.md │ ├── dw_io │ │ ├── CSVStreamReader.md │ │ ├── CSVStreamWriter.md │ │ ├── File.md │ │ ├── FileReader.md │ │ ├── FileWriter.md │ │ ├── InputStream.md │ │ ├── OutputStream.md │ │ ├── PrintWriter.md │ │ ├── RandomAccessFileReader.md │ │ ├── Reader.md │ │ ├── StringWriter.md │ │ ├── Writer.md │ │ ├── XMLIndentingStreamWriter.md │ │ ├── XMLStreamConstants.md │ │ ├── XMLStreamReader.md │ │ └── XMLStreamWriter.md │ ├── dw_job │ │ ├── JobExecution.md │ │ └── JobStepExecution.md │ ├── dw_net │ │ ├── FTPClient.md │ │ ├── FTPFileInfo.md │ │ ├── HTTPClient.md │ │ ├── HTTPRequestPart.md │ │ ├── Mail.md │ │ ├── SFTPClient.md │ │ ├── SFTPFileInfo.md │ │ ├── WebDAVClient.md │ │ └── WebDAVFileInfo.md │ ├── dw_object │ │ ├── ActiveData.md │ │ ├── CustomAttributes.md │ │ ├── CustomObject.md │ │ ├── CustomObjectMgr.md │ │ ├── Extensible.md │ │ ├── ExtensibleObject.md │ │ ├── Note.md │ │ ├── ObjectAttributeDefinition.md │ │ ├── ObjectAttributeGroup.md │ │ ├── ObjectAttributeValueDefinition.md │ │ ├── ObjectTypeDefinition.md │ │ ├── PersistentObject.md │ │ ├── SimpleExtensible.md │ │ └── SystemObjectMgr.md │ ├── dw_order │ │ ├── AbstractItem.md │ │ ├── AbstractItemCtnr.md │ │ ├── Appeasement.md │ │ ├── AppeasementItem.md │ │ ├── Basket.md │ │ ├── BasketMgr.md │ │ ├── BonusDiscountLineItem.md │ │ ├── CouponLineItem.md │ │ ├── CreateAgentBasketLimitExceededException.md │ │ ├── CreateBasketFromOrderException.md │ │ ├── CreateCouponLineItemException.md │ │ ├── CreateOrderException.md │ │ ├── CreateTemporaryBasketLimitExceededException.md │ │ ├── GiftCertificate.md │ │ ├── GiftCertificateLineItem.md │ │ ├── GiftCertificateMgr.md │ │ ├── GiftCertificateStatusCodes.md │ │ ├── Invoice.md │ │ ├── InvoiceItem.md │ │ ├── LineItem.md │ │ ├── LineItemCtnr.md │ │ ├── Order.md │ │ ├── OrderAddress.md │ │ ├── OrderItem.md │ │ ├── OrderMgr.md │ │ ├── OrderPaymentInstrument.md │ │ ├── OrderProcessStatusCodes.md │ │ ├── PaymentCard.md │ │ ├── PaymentInstrument.md │ │ ├── PaymentMethod.md │ │ ├── PaymentMgr.md │ │ ├── PaymentProcessor.md │ │ ├── PaymentStatusCodes.md │ │ ├── PaymentTransaction.md │ │ ├── PriceAdjustment.md │ │ ├── PriceAdjustmentLimitTypes.md │ │ ├── ProductLineItem.md │ │ ├── ProductShippingCost.md │ │ ├── ProductShippingLineItem.md │ │ ├── ProductShippingModel.md │ │ ├── Return.md │ │ ├── ReturnCase.md │ │ ├── ReturnCaseItem.md │ │ ├── ReturnItem.md │ │ ├── Shipment.md │ │ ├── ShipmentShippingCost.md │ │ ├── ShipmentShippingModel.md │ │ ├── ShippingLineItem.md │ │ ├── ShippingLocation.md │ │ ├── ShippingMethod.md │ │ ├── ShippingMgr.md │ │ ├── ShippingOrder.md │ │ ├── ShippingOrderItem.md │ │ ├── SumItem.md │ │ ├── TaxGroup.md │ │ ├── TaxItem.md │ │ ├── TaxMgr.md │ │ ├── TrackingInfo.md │ │ └── TrackingRef.md │ ├── dw_order.hooks │ │ ├── CalculateHooks.md │ │ ├── OrderHooks.md │ │ ├── PaymentHooks.md │ │ ├── ReturnHooks.md │ │ └── ShippingOrderHooks.md │ ├── dw_rpc │ │ ├── SOAPUtil.md │ │ ├── Stub.md │ │ └── WebReference.md │ ├── dw_suggest │ │ ├── BrandSuggestions.md │ │ ├── CategorySuggestions.md │ │ ├── ContentSuggestions.md │ │ ├── CustomSuggestions.md │ │ ├── ProductSuggestions.md │ │ ├── SearchPhraseSuggestions.md │ │ ├── SuggestedCategory.md │ │ ├── SuggestedContent.md │ │ ├── SuggestedPhrase.md │ │ ├── SuggestedProduct.md │ │ ├── SuggestedTerm.md │ │ ├── SuggestedTerms.md │ │ ├── Suggestions.md │ │ └── SuggestModel.md │ ├── dw_svc │ │ ├── FTPService.md │ │ ├── FTPServiceDefinition.md │ │ ├── HTTPFormService.md │ │ ├── HTTPFormServiceDefinition.md │ │ ├── HTTPService.md │ │ ├── HTTPServiceDefinition.md │ │ ├── LocalServiceRegistry.md │ │ ├── Result.md │ │ ├── Service.md │ │ ├── ServiceCallback.md │ │ ├── ServiceConfig.md │ │ ├── ServiceCredential.md │ │ ├── ServiceDefinition.md │ │ ├── ServiceProfile.md │ │ ├── ServiceRegistry.md │ │ ├── SOAPService.md │ │ └── SOAPServiceDefinition.md │ ├── dw_system │ │ ├── AgentUserStatusCodes.md │ │ ├── Cache.md │ │ ├── CacheMgr.md │ │ ├── HookMgr.md │ │ ├── InternalObject.md │ │ ├── JobProcessMonitor.md │ │ ├── Log.md │ │ ├── Logger.md │ │ ├── LogNDC.md │ │ ├── OrganizationPreferences.md │ │ ├── Pipeline.md │ │ ├── PipelineDictionary.md │ │ ├── RemoteInclude.md │ │ ├── Request.md │ │ ├── RequestHooks.md │ │ ├── Response.md │ │ ├── RESTErrorResponse.md │ │ ├── RESTResponseMgr.md │ │ ├── RESTSuccessResponse.md │ │ ├── SearchStatus.md │ │ ├── Session.md │ │ ├── Site.md │ │ ├── SitePreferences.md │ │ ├── Status.md │ │ ├── StatusItem.md │ │ ├── System.md │ │ └── Transaction.md │ ├── dw_util │ │ ├── ArrayList.md │ │ ├── Assert.md │ │ ├── BigInteger.md │ │ ├── Bytes.md │ │ ├── Calendar.md │ │ ├── Collection.md │ │ ├── Currency.md │ │ ├── DateUtils.md │ │ ├── Decimal.md │ │ ├── FilteringCollection.md │ │ ├── Geolocation.md │ │ ├── HashMap.md │ │ ├── HashSet.md │ │ ├── Iterator.md │ │ ├── LinkedHashMap.md │ │ ├── LinkedHashSet.md │ │ ├── List.md │ │ ├── Locale.md │ │ ├── Map.md │ │ ├── MapEntry.md │ │ ├── MappingKey.md │ │ ├── MappingMgr.md │ │ ├── PropertyComparator.md │ │ ├── SecureEncoder.md │ │ ├── SecureFilter.md │ │ ├── SeekableIterator.md │ │ ├── Set.md │ │ ├── SortedMap.md │ │ ├── SortedSet.md │ │ ├── StringUtils.md │ │ ├── Template.md │ │ └── UUIDUtils.md │ ├── dw_value │ │ ├── EnumValue.md │ │ ├── MimeEncodedText.md │ │ ├── Money.md │ │ └── Quantity.md │ ├── dw_web │ │ ├── ClickStream.md │ │ ├── ClickStreamEntry.md │ │ ├── Cookie.md │ │ ├── Cookies.md │ │ ├── CSRFProtection.md │ │ ├── Form.md │ │ ├── FormAction.md │ │ ├── FormElement.md │ │ ├── FormElementValidationResult.md │ │ ├── FormField.md │ │ ├── FormFieldOption.md │ │ ├── FormFieldOptions.md │ │ ├── FormGroup.md │ │ ├── FormList.md │ │ ├── FormListItem.md │ │ ├── Forms.md │ │ ├── HttpParameter.md │ │ ├── HttpParameterMap.md │ │ ├── LoopIterator.md │ │ ├── PageMetaData.md │ │ ├── PageMetaTag.md │ │ ├── PagingModel.md │ │ ├── Resource.md │ │ ├── URL.md │ │ ├── URLAction.md │ │ ├── URLParameter.md │ │ ├── URLRedirect.md │ │ ├── URLRedirectMgr.md │ │ └── URLUtils.md │ ├── sfra │ │ ├── account.md │ │ ├── address.md │ │ ├── billing.md │ │ ├── cart.md │ │ ├── categories.md │ │ ├── content.md │ │ ├── locale.md │ │ ├── order.md │ │ ├── payment.md │ │ ├── price-default.md │ │ ├── price-range.md │ │ ├── price-tiered.md │ │ ├── product-bundle.md │ │ ├── product-full.md │ │ ├── product-line-items.md │ │ ├── product-search.md │ │ ├── product-tile.md │ │ ├── querystring.md │ │ ├── render.md │ │ ├── request.md │ │ ├── response.md │ │ ├── server.md │ │ ├── shipping.md │ │ ├── store.md │ │ ├── stores.md │ │ └── totals.md │ └── TopLevel │ ├── APIException.md │ ├── arguments.md │ ├── Array.md │ ├── ArrayBuffer.md │ ├── BigInt.md │ ├── Boolean.md │ ├── ConversionError.md │ ├── DataView.md │ ├── Date.md │ ├── Error.md │ ├── ES6Iterator.md │ ├── EvalError.md │ ├── Fault.md │ ├── Float32Array.md │ ├── Float64Array.md │ ├── Function.md │ ├── Generator.md │ ├── global.md │ ├── Int16Array.md │ ├── Int32Array.md │ ├── Int8Array.md │ ├── InternalError.md │ ├── IOError.md │ ├── Iterable.md │ ├── Iterator.md │ ├── JSON.md │ ├── Map.md │ ├── Math.md │ ├── Module.md │ ├── Namespace.md │ ├── Number.md │ ├── Object.md │ ├── QName.md │ ├── RangeError.md │ ├── ReferenceError.md │ ├── RegExp.md │ ├── Set.md │ ├── StopIteration.md │ ├── String.md │ ├── Symbol.md │ ├── SyntaxError.md │ ├── SystemError.md │ ├── TypeError.md │ ├── Uint16Array.md │ ├── Uint32Array.md │ ├── Uint8Array.md │ ├── Uint8ClampedArray.md │ ├── URIError.md │ ├── WeakMap.md │ ├── WeakSet.md │ ├── XML.md │ ├── XMLList.md │ └── XMLStreamError.md ├── docs-site │ ├── .gitignore │ ├── App.tsx │ ├── components │ │ ├── Badge.tsx │ │ ├── BreadcrumbSchema.tsx │ │ ├── CodeBlock.tsx │ │ ├── Collapsible.tsx │ │ ├── ConfigBuilder.tsx │ │ ├── ConfigHero.tsx │ │ ├── ConfigModeTabs.tsx │ │ ├── icons.tsx │ │ ├── Layout.tsx │ │ ├── LightCodeContainer.tsx │ │ ├── NewcomerCTA.tsx │ │ ├── NextStepsStrip.tsx │ │ ├── OnThisPage.tsx │ │ ├── Search.tsx │ │ ├── SEO.tsx │ │ ├── Sidebar.tsx │ │ ├── StructuredData.tsx │ │ ├── ToolCard.tsx │ │ ├── ToolFilters.tsx │ │ ├── Typography.tsx │ │ └── VersionBadge.tsx │ ├── constants.tsx │ ├── index.html │ ├── main.tsx │ ├── metadata.json │ ├── package-lock.json │ ├── package.json │ ├── pages │ │ ├── AIInterfacesPage.tsx │ │ ├── ConfigurationPage.tsx │ │ ├── DevelopmentPage.tsx │ │ ├── ExamplesPage.tsx │ │ ├── FeaturesPage.tsx │ │ ├── HomePage.tsx │ │ ├── SecurityPage.tsx │ │ ├── ToolsPage.tsx │ │ └── TroubleshootingPage.tsx │ ├── postcss.config.js │ ├── public │ │ ├── .well-known │ │ │ └── security.txt │ │ ├── 404.html │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── explain-product-pricing-methods-no-mcp.png │ │ ├── explain-product-pricing-methods.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── llms.txt │ │ ├── robots.txt │ │ ├── site.webmanifest │ │ └── sitemap.xml │ ├── README.md │ ├── scripts │ │ ├── generate-search-index.js │ │ ├── generate-sitemap.js │ │ └── search-dev.js │ ├── src │ │ └── styles │ │ ├── input.css │ │ └── prism-theme.css │ ├── tailwind.config.js │ ├── tsconfig.json │ ├── types.ts │ ├── utils │ │ ├── search.ts │ │ └── toolsData.ts │ └── vite.config.ts ├── eslint.config.js ├── jest.config.js ├── LICENSE ├── package-lock.json ├── package.json ├── README.md ├── scripts │ └── convert-docs.js ├── SECURITY.md ├── server.json ├── src │ ├── clients │ │ ├── base │ │ │ ├── http-client.ts │ │ │ ├── oauth-token.ts │ │ │ └── ocapi-auth-client.ts │ │ ├── best-practices-client.ts │ │ ├── cartridge-generation-client.ts │ │ ├── docs │ │ │ ├── class-content-parser.ts │ │ │ ├── class-name-resolver.ts │ │ │ ├── documentation-scanner.ts │ │ │ ├── index.ts │ │ │ └── referenced-types-extractor.ts │ │ ├── docs-client.ts │ │ ├── log-client.ts │ │ ├── logs │ │ │ ├── index.ts │ │ │ ├── log-analyzer.ts │ │ │ ├── log-client.ts │ │ │ ├── log-constants.ts │ │ │ ├── log-file-discovery.ts │ │ │ ├── log-file-reader.ts │ │ │ ├── log-formatter.ts │ │ │ ├── log-processor.ts │ │ │ ├── log-types.ts │ │ │ └── webdav-client-manager.ts │ │ ├── ocapi │ │ │ ├── code-versions-client.ts │ │ │ ├── site-preferences-client.ts │ │ │ └── system-objects-client.ts │ │ ├── ocapi-client.ts │ │ └── sfra-client.ts │ ├── config │ │ ├── configuration-factory.ts │ │ └── dw-json-loader.ts │ ├── core │ │ ├── handlers │ │ │ ├── abstract-log-tool-handler.ts │ │ │ ├── base-handler.ts │ │ │ ├── best-practices-handler.ts │ │ │ ├── cartridge-handler.ts │ │ │ ├── client-factory.ts │ │ │ ├── code-version-handler.ts │ │ │ ├── docs-handler.ts │ │ │ ├── job-log-handler.ts │ │ │ ├── job-log-tool-config.ts │ │ │ ├── log-handler.ts │ │ │ ├── log-tool-config.ts │ │ │ ├── sfra-handler.ts │ │ │ ├── system-object-handler.ts │ │ │ └── validation-helpers.ts │ │ ├── server.ts │ │ └── tool-definitions.ts │ ├── index.ts │ ├── main.ts │ ├── services │ │ ├── file-system-service.ts │ │ ├── index.ts │ │ └── path-service.ts │ ├── tool-configs │ │ ├── best-practices-tool-config.ts │ │ ├── cartridge-tool-config.ts │ │ ├── code-version-tool-config.ts │ │ ├── docs-tool-config.ts │ │ ├── job-log-tool-config.ts │ │ ├── log-tool-config.ts │ │ ├── sfra-tool-config.ts │ │ └── system-object-tool-config.ts │ ├── types │ │ └── types.ts │ └── utils │ ├── cache.ts │ ├── job-log-tool-config.ts │ ├── job-log-utils.ts │ ├── log-cache.ts │ ├── log-tool-config.ts │ ├── log-tool-constants.ts │ ├── log-tool-utils.ts │ ├── logger.ts │ ├── ocapi-url-builder.ts │ ├── path-resolver.ts │ ├── query-builder.ts │ ├── utils.ts │ └── validator.ts ├── tests │ ├── __mocks__ │ │ ├── docs-client.ts │ │ ├── src │ │ │ └── clients │ │ │ └── base │ │ │ └── http-client.js │ │ └── webdav.js │ ├── base-handler.test.ts │ ├── base-http-client.test.ts │ ├── best-practices-handler.test.ts │ ├── cache.test.ts │ ├── cartridge-handler.test.ts │ ├── class-content-parser.test.ts │ ├── class-name-resolver.test.ts │ ├── client-factory.test.ts │ ├── code-version-handler.test.ts │ ├── code-versions-client.test.ts │ ├── config.test.ts │ ├── configuration-factory.test.ts │ ├── docs-handler.test.ts │ ├── documentation-scanner.test.ts │ ├── file-system-service.test.ts │ ├── job-log-handler.test.ts │ ├── job-log-utils.test.ts │ ├── log-client.test.ts │ ├── log-handler.test.ts │ ├── log-processor.test.ts │ ├── logger.test.ts │ ├── mcp │ │ ├── AGENTS.md │ │ ├── node │ │ │ ├── activate-code-version-advanced.full-mode.programmatic.test.js │ │ │ ├── code-versions.full-mode.programmatic.test.js │ │ │ ├── generate-cartridge-structure.docs-only.programmatic.test.js │ │ │ ├── get-available-best-practice-guides.docs-only.programmatic.test.js │ │ │ ├── get-available-sfra-documents.programmatic.test.js │ │ │ ├── get-best-practice-guide.docs-only.programmatic.test.js │ │ │ ├── get-hook-reference.docs-only.programmatic.test.js │ │ │ ├── get-job-execution-summary.full-mode.programmatic.test.js │ │ │ ├── get-job-log-entries.full-mode.programmatic.test.js │ │ │ ├── get-latest-debug.full-mode.programmatic.test.js │ │ │ ├── get-latest-error.full-mode.programmatic.test.js │ │ │ ├── get-latest-info.full-mode.programmatic.test.js │ │ │ ├── get-latest-job-log-files.full-mode.programmatic.test.js │ │ │ ├── get-latest-warn.full-mode.programmatic.test.js │ │ │ ├── get-log-file-contents.full-mode.programmatic.test.js │ │ │ ├── get-sfcc-class-documentation.docs-only.programmatic.test.js │ │ │ ├── get-sfcc-class-info.docs-only.programmatic.test.js │ │ │ ├── get-sfra-categories.docs-only.programmatic.test.js │ │ │ ├── get-sfra-document.programmatic.test.js │ │ │ ├── get-sfra-documents-by-category.docs-only.programmatic.test.js │ │ │ ├── get-system-object-definition.full-mode.programmatic.test.js │ │ │ ├── get-system-object-definitions.docs-only.programmatic.test.js │ │ │ ├── get-system-object-definitions.full-mode.programmatic.test.js │ │ │ ├── list-log-files.full-mode.programmatic.test.js │ │ │ ├── list-sfcc-classes.docs-only.programmatic.test.js │ │ │ ├── search-best-practices.docs-only.programmatic.test.js │ │ │ ├── search-custom-object-attribute-definitions.full-mode.programmatic.test.js │ │ │ ├── search-job-logs-by-name.full-mode.programmatic.test.js │ │ │ ├── search-job-logs.full-mode.programmatic.test.js │ │ │ ├── search-logs.full-mode.programmatic.test.js │ │ │ ├── search-sfcc-classes.docs-only.programmatic.test.js │ │ │ ├── search-sfcc-methods.docs-only.programmatic.test.js │ │ │ ├── search-sfra-documentation.docs-only.programmatic.test.js │ │ │ ├── search-site-preferences.full-mode.programmatic.test.js │ │ │ ├── search-system-object-attribute-definitions.full-mode.programmatic.test.js │ │ │ ├── search-system-object-attribute-groups.full-mode.programmatic.test.js │ │ │ ├── summarize-logs.full-mode.programmatic.test.js │ │ │ ├── tools.docs-only.programmatic.test.js │ │ │ └── tools.full-mode.programmatic.test.js │ │ ├── README.md │ │ ├── test-fixtures │ │ │ └── dw.json │ │ └── yaml │ │ ├── activate-code-version.docs-only.test.mcp.yml │ │ ├── activate-code-version.full-mode.test.mcp.yml │ │ ├── get_latest_error.test.mcp.yml │ │ ├── get-available-best-practice-guides.docs-only.test.mcp.yml │ │ ├── get-available-best-practice-guides.full-mode.test.mcp.yml │ │ ├── get-available-sfra-documents.docs-only.test.mcp.yml │ │ ├── get-available-sfra-documents.full-mode.test.mcp.yml │ │ ├── get-best-practice-guide.docs-only.test.mcp.yml │ │ ├── get-best-practice-guide.full-mode.test.mcp.yml │ │ ├── get-code-versions.docs-only.test.mcp.yml │ │ ├── get-code-versions.full-mode.test.mcp.yml │ │ ├── get-hook-reference.docs-only.test.mcp.yml │ │ ├── get-hook-reference.full-mode.test.mcp.yml │ │ ├── get-job-execution-summary.full-mode.test.mcp.yml │ │ ├── get-job-log-entries.full-mode.test.mcp.yml │ │ ├── get-latest-debug.full-mode.test.mcp.yml │ │ ├── get-latest-error.full-mode.test.mcp.yml │ │ ├── get-latest-info.full-mode.test.mcp.yml │ │ ├── get-latest-job-log-files.full-mode.test.mcp.yml │ │ ├── get-latest-warn.full-mode.test.mcp.yml │ │ ├── get-log-file-contents.full-mode.test.mcp.yml │ │ ├── get-sfcc-class-documentation.docs-only.test.mcp.yml │ │ ├── get-sfcc-class-documentation.full-mode.test.mcp.yml │ │ ├── get-sfcc-class-info.docs-only.test.mcp.yml │ │ ├── get-sfcc-class-info.full-mode.test.mcp.yml │ │ ├── get-sfra-categories.docs-only.test.mcp.yml │ │ ├── get-sfra-categories.full-mode.test.mcp.yml │ │ ├── get-sfra-document.docs-only.test.mcp.yml │ │ ├── get-sfra-document.full-mode.test.mcp.yml │ │ ├── get-sfra-documents-by-category.docs-only.test.mcp.yml │ │ ├── get-sfra-documents-by-category.full-mode.test.mcp.yml │ │ ├── get-system-object-definition.docs-only.test.mcp.yml │ │ ├── get-system-object-definition.full-mode.test.mcp.yml │ │ ├── get-system-object-definitions.docs-only.test.mcp.yml │ │ ├── get-system-object-definitions.full-mode.test.mcp.yml │ │ ├── list-log-files.full-mode.test.mcp.yml │ │ ├── list-sfcc-classes.docs-only.test.mcp.yml │ │ ├── list-sfcc-classes.full-mode.test.mcp.yml │ │ ├── search-best-practices.docs-only.test.mcp.yml │ │ ├── search-best-practices.full-mode.test.mcp.yml │ │ ├── search-custom-object-attribute-definitions.docs-only.test.mcp.yml │ │ ├── search-custom-object-attribute-definitions.test.mcp.yml │ │ ├── search-job-logs-by-name.full-mode.test.mcp.yml │ │ ├── search-job-logs.full-mode.test.mcp.yml │ │ ├── search-logs.full-mode.test.mcp.yml │ │ ├── search-sfcc-classes.docs-only.test.mcp.yml │ │ ├── search-sfcc-classes.full-mode.test.mcp.yml │ │ ├── search-sfcc-methods.docs-only.test.mcp.yml │ │ ├── search-sfcc-methods.full-mode.test.mcp.yml │ │ ├── search-sfra-documentation.docs-only.test.mcp.yml │ │ ├── search-sfra-documentation.full-mode.test.mcp.yml │ │ ├── search-site-preferences.docs-only.test.mcp.yml │ │ ├── search-site-preferences.full-mode.test.mcp.yml │ │ ├── search-system-object-attribute-definitions.docs-only.test.mcp.yml │ │ ├── search-system-object-attribute-definitions.full-mode.test.mcp.yml │ │ ├── search-system-object-attribute-groups.docs-only.test.mcp.yml │ │ ├── search-system-object-attribute-groups.full-mode.test.mcp.yml │ │ ├── summarize-logs.full-mode.test.mcp.yml │ │ ├── tools.docs-only.test.mcp.yml │ │ └── tools.full-mode.test.mcp.yml │ ├── oauth-token.test.ts │ ├── ocapi-auth-client.test.ts │ ├── ocapi-client.test.ts │ ├── path-service.test.ts │ ├── query-builder.test.ts │ ├── referenced-types-extractor.test.ts │ ├── servers │ │ ├── sfcc-mock-server │ │ │ ├── mock-data │ │ │ │ └── ocapi │ │ │ │ ├── code-versions.json │ │ │ │ ├── custom-object-attributes-customapi.json │ │ │ │ ├── custom-object-attributes-globalsettings.json │ │ │ │ ├── custom-object-attributes-versionhistory.json │ │ │ │ ├── site-preferences-ccv.json │ │ │ │ ├── site-preferences-fastforward.json │ │ │ │ ├── site-preferences-sfra.json │ │ │ │ ├── site-preferences-storefront.json │ │ │ │ ├── site-preferences-system.json │ │ │ │ ├── system-object-attribute-groups-campaign.json │ │ │ │ ├── system-object-attribute-groups-category.json │ │ │ │ ├── system-object-attribute-groups-order.json │ │ │ │ ├── system-object-attribute-groups-product.json │ │ │ │ ├── system-object-attribute-groups-sitepreferences.json │ │ │ │ ├── system-object-attributes-customeraddress.json │ │ │ │ ├── system-object-attributes-product-expanded.json │ │ │ │ ├── system-object-attributes-product.json │ │ │ │ ├── system-object-definition-category.json │ │ │ │ ├── system-object-definition-customer.json │ │ │ │ ├── system-object-definition-customeraddress.json │ │ │ │ ├── system-object-definition-order.json │ │ │ │ ├── system-object-definition-product.json │ │ │ │ ├── system-object-definitions-old.json │ │ │ │ └── system-object-definitions.json │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── README.md │ │ │ ├── scripts │ │ │ │ └── setup-logs.js │ │ │ ├── server.js │ │ │ └── src │ │ │ ├── app.js │ │ │ ├── config │ │ │ │ └── server-config.js │ │ │ ├── middleware │ │ │ │ ├── auth.js │ │ │ │ ├── cors.js │ │ │ │ └── logging.js │ │ │ ├── routes │ │ │ │ ├── ocapi │ │ │ │ │ ├── code-versions-handler.js │ │ │ │ │ ├── oauth-handler.js │ │ │ │ │ ├── ocapi-error-utils.js │ │ │ │ │ ├── ocapi-utils.js │ │ │ │ │ ├── site-preferences-handler.js │ │ │ │ │ └── system-objects-handler.js │ │ │ │ ├── ocapi.js │ │ │ │ └── webdav.js │ │ │ └── utils │ │ │ ├── mock-data-loader.js │ │ │ └── webdav-xml.js │ │ └── sfcc-mock-server-manager.ts │ ├── sfcc-mock-server.test.ts │ ├── site-preferences-client.test.ts │ ├── system-objects-client.test.ts │ ├── utils.test.ts │ ├── validation-helpers.test.ts │ └── validator.test.ts ├── tsconfig.json └── tsconfig.test.json ``` # Files -------------------------------------------------------------------------------- /docs/best-practices/isml_templates.md: -------------------------------------------------------------------------------- ```markdown # Salesforce B2C Commerce ISML Templates: Best Practices & Development Guide This guide provides comprehensive best practices for developing ISML (Internet Store Markup Language) templates within the Salesforce B2C Commerce Storefront Reference Architecture (SFRA). Master these principles to build secure, maintainable, and high-performing storefront experiences. **IMPORTANT**: Before developing ISML templates, consult the **Performance and Stability Best Practices** and **SFRA Controllers** guides from this MCP server. Understanding the MVC separation and controller patterns is essential for proper ISML development. ## Core Principles ### The Golden Rule: Logic-Free Templates **NEVER use `<isscript>` for business logic in ISML templates.** This is the most critical rule in SFRA development. ISML templates are presentation-only layers that should receive all data from controllers via the `pdict` object. Any business logic, data manipulation, or API calls belong in controllers or models. #### ❌ Anti-Pattern: Logic in Templates ```html <isscript> var ProductMgr = require('dw/catalog/ProductMgr'); var product = ProductMgr.getProduct(pdict.pid); var price = product.getPriceModel().getPrice(); </isscript> <div class="price">${price}</div> ``` #### ✅ Correct Pattern: Data from Controller ```javascript // Controller server.get('Show', function (req, res, next) { var product = ProductFactory.get({ pid: req.querystring.pid }); res.render('product/productDetails', { product: product }); next(); }); ``` ```html <!-- ISML Template --> <div class="price">${pdict.product.price.sales.formatted}</div> ``` ### Exception: Asset Management Only The **only** acceptable use of `<isscript>` is for managing static assets: ```html <isscript> var assets = require('*/cartridge/scripts/assets.js'); assets.addCss('/css/product.css'); assets.addJs('/js/product.js'); </isscript> ``` ## Security Best Practices ### XSS Prevention with Proper Encoding **Always rely on default encoding.** The `<isprint>` tag automatically HTML-encodes output to prevent XSS attacks. #### ✅ Secure (Default Behavior) ```html <div class="search-term"> You searched for: <isprint value="${pdict.searchPhrase}" /> </div> ``` #### ❌ Vulnerable ```html <div class="search-term"> You searched for: <isprint value="${pdict.searchPhrase}" encoding="off" /> </div> ``` ### Context-Specific Encoding For non-HTML contexts, use `dw.util.SecureEncoder`: ```html <isscript> var SecureEncoder = require('dw/util/SecureEncoder'); </isscript> <!-- For JavaScript context --> <script> var searchTerm = "${SecureEncoder.forJavaScript(pdict.searchPhrase)}"; </script> <!-- For HTML attributes --> <input type="hidden" value="${SecureEncoder.forHTMLAttribute(pdict.token)}" /> ``` ## Template Architecture Patterns ### 1. Layout Decorators Use decorators for consistent page structure: #### SFRA Default Decorator Templates **IMPORTANT**: SFRA provides only **two default decorator templates** out of the box: 1. **`common/layout/page`** - Standard storefront pages (homepage, PDP, search, account, etc.) 2. **`common/layout/checkout`** - Secure checkout process pages If you need additional layout patterns (modal dialogs, email templates, mobile-specific layouts, etc.), you must **create custom decorator templates** in your cartridge's `templates/default/common/layout/` directory. #### Common Custom Decorators You May Need to Create: ```html <!-- Custom Modal Layout --> common/layout/modal.isml <!-- Email Template Layout --> common/layout/email.isml <!-- Popup/Lightbox Layout --> common/layout/popup.isml <!-- Print-Friendly Layout --> common/layout/print.isml <!-- Mobile App Layout --> common/layout/mobile.isml ``` #### Default Template Usage Examples: **Using the Standard Page Layout**: ```html <!-- ✅ Standard storefront pages --> <isdecorate template="common/layout/page"> <div class="product-details"> <h1><isprint value="${pdict.product.productName}" /></h1> <!-- Content goes here --> </div> </isdecorate> ``` **Using the Checkout Layout**: ```html <!-- ✅ Secure checkout pages --> <isdecorate template="common/layout/checkout"> <div class="checkout-content"> <h1>Checkout</h1> <!-- Checkout form content --> </div> </isdecorate> ``` #### Creating Custom Decorator Templates: If you need a custom layout, create it in your cartridge at `templates/default/common/layout/[name].isml`: **Example Custom Modal Layout** (`common/layout/modal.isml`): ```html <!doctype html> <html lang="${require('dw/util/Locale').getLocale(request.locale).getLanguage()}"> <head> <isinclude template="common/htmlHead" /> </head> <body class="modal-body"> <div class="modal-container"> <header class="modal-header"> <button type="button" class="close" data-dismiss="modal"> <span>×</span> </button> </header> <main class="modal-content"> <isreplace/> </main> </div> </body> </html> ``` **Using Your Custom Layout**: ```html <!-- ✅ Using custom decorator template --> <isdecorate template="common/layout/modal"> <div class="modal-body-content"> <h2>Modal Title</h2> <p>Modal content goes here</p> </div> </isdecorate> ``` ### 2. Component Modularity Break complex templates into reusable components: **Product Tile Component** (`product/components/productTile.isml`): ```html <div class="product-tile" data-pid="${pdict.product.id}"> <div class="tile-image"> <isinclude template="product/components/productTileImage" /> </div> <div class="tile-body"> <div class="pdp-link"> <a class="link" href="${pdict.product.url}"> <isprint value="${pdict.product.productName}" /> </a> </div> <isinclude template="product/components/pricing/main" /> <isinclude template="product/components/productTileActions" /> </div> </div> ``` **Usage in Grid**: ```html <div class="row product-grid"> <isloop items="${pdict.productSearch.productHits}" var="productHit"> <div class="col-6 col-sm-4"> <isinclude template="product/components/productTile" /> <isset name="product" value="${productHit.product}" scope="page" /> </div> </isloop> </div> ``` ### 3. Remote Includes vs Local Includes (Advanced Fragment Architecture) Remote includes are NOT just an alternative syntax – they change request boundaries, data scoping, caching strategy, security posture, and performance characteristics. Choose them only when a fragment truly needs an independent cache policy or isolation. | Attribute | Local Include `<isinclude template="...">` | Remote Include `<isinclude url="...">` | |-----------|---------------------------------------------|-------------------------------------------| | Processing | Single request on Application Server | Parent request + secondary request orchestrated by Web Adapter | | Data Scope | Full access to parent `pdict` & variables | Isolated – only URL query params available | | Cache Policy | Inherits parent (lowest TTL wins) | Independent TTL per fragment | | Typical Use | Reusable markup, product tile partials | Mini-cart, personalized promo slot, dynamic inventory widget | | Overhead | Minimal | Extra HTTP round trip per include | | Security | Inherits parent auth state | New unauthenticated request – must add explicit protection | | Failure Mode | Template error breaks page render | Fragment timeout can delay full page assembly | #### 3.1 When to Use Which Use a local include unless ALL are true: 1. Fragment volatility differs meaningfully from page shell 2. Output can be parameterized via simple query params 3. Performance gain from separate caching outweighs added request 4. Security implications are understood and mitigated #### 3.2 Implementing a Remote Include Template example (mini-cart header icon kept uncached while page shell cached hours): ```html <div class="header-cart" data-component="mini-cart"> <isinclude url="${URLUtils.url('Cart-MiniCart')}" /> <!-- Controller route name MUST match exactly --> </div> ``` Controller (excerpt): ```javascript var server = require('server'); var cache = require('*/cartridge/scripts/middleware/cache'); server.get('MiniCart', server.middleware.include, // Gatekeeper: only valid inside remote include flow cache.applyShortPromotionSensitiveCache, // Or cache.disableCaching() equivalent for uncached function (req, res, next) { // Build isolated model – no parent pdict access res.render('components/header/miniCart'); next(); } ); module.exports = server.exports(); ``` #### 3.3 Passing Data All context must be URL params: ```html <isinclude url="${URLUtils.url('Page-Include', 'cid', 'footer-content-asset')}" /> ``` Avoid over-parameterization – each unique full URL becomes a distinct cache entry (cache fragmentation risk). #### 3.4 Caching Strategy Patterns | Scenario | Page Shell TTL | Remote Include TTL | Rationale | |----------|----------------|--------------------|-----------| | Marketing landing + live inventory badge | 12h | 5m | Keep inventory fresh without invalidating hero layout | | Category grid + personalized banner | 4h | 15m | Personalized offers rotate more often than navigation | | PDP + mini-cart | 2h | 0 (uncached) | Basket state must reflect current session | Keep total remote includes per page conservative (<20 recommended) to avoid waterfall latency. #### 3.5 Performance Anti-Patterns | Anti-Pattern | Why It’s Harmful | Better Alternative | |--------------|------------------|--------------------| | One remote include per product tile in a grid | N extra HTTP requests, destroys cache efficiency | Single parent render with local includes | | Adding position/index params that change per render | Creates unique cache keys, low hit ratio | Omit non-functional varying params | | Deep nesting (include inside include chain) | Hard to debug, compounding latency | Flatten architecture – coalesce related fragments | #### 3.6 Security Criticals Remote include endpoints are effectively public unless you add authentication middleware (e.g., `userLoggedIn.validateLoggedIn`). NEVER expose PII or account state in an unprotected include. Always start chain with: ```javascript server.get('SensitiveFragment', server.middleware.include, userLoggedIn.validateLoggedIn, // if user-specific function (req, res, next) { ... } ); ``` #### 3.7 Observability & Debugging Use extended request IDs in logs: `reqId-depth-index` (e.g., `AbC123-1-02`). Search logs to isolate slow fragment origins. #### 3.8 Checklist ```text [ ] Justified different cache TTL [ ] URL params minimal & non-sensitive [ ] server.middleware.include first [ ] Additional auth middleware if user data [ ] Explicit cache middleware (or disabled) [ ] Fragment count on page < 20 [ ] No nested chains beyond depth 2 ``` If you cannot satisfy most checklist items, prefer a local include. #### 3.9 When NOT to Use Remote Includes - Pure presentational partials (icons, button groups) - Iterative children of a paginated list - Form bodies that rely on parent controller’s validation context - Anything requiring access to parent `pdict` objects without trivial serialization --- ## Utility Helpers Available in Templates SFRA templates run inside the B2C Commerce template processor, which autowires a set of utility objects and classes so you can call them without additional imports. Knowing what is available keeps templates lean and avoids unnecessary `<isscript>` blocks. ### Top-Level Variables The template scope automatically exposes: - `pdict` - `out` - `request` - `session` Each object gives you direct access to storefront context data and helper APIs. ### `dw.system.Request` Because `request` is a top-level variable, you can call methods directly without `require` statements. | Method | Description | | --- | --- | | `getHttpCookies()` → `Cookies` | Returns the `Cookies` object so you can inspect or manipulate client-side cookies. | | `getHttpHeaders()` → `Map` | Returns a map of HTTP header values on the current request. | | `isHttpSecure()` → `Boolean` | Indicates whether the request is secure (`HTTPS`). | | `isSCAPI()` → `Boolean` | Distinguishes between OCAPI and SCAPI requests in extension points (hooks). | **Example** ```html <td class="price merchandizetotal"> <isprint value="${request.custom.Container.adjustedMerchandiseTotalNetPrice}" /> </td> ``` ### `dw.system.Session` The `session` top-level variable exposes the current storefront or Business Manager session (Business Manager sessions return `null` for customer lookups). | Method | Description | | --- | --- | | `getCustomer()` → `Customer` | Returns the current customer associated with the storefront session; `null` in Business Manager. | | `isCustomerAuthenticated()` → `Boolean` | Indicates whether the customer for this session is authenticated (equivalent to `customer.isAuthenticated()`). | **Example** ```html <isprint value="${session.getCustomer().firstname}" /> ``` ### `dw.util.StringUtils` `StringUtils` is pre-imported, letting you call static helpers by their simple name to format and sanitize output. | Method | Description | | --- | --- | | `formatDate(date)` → `String` | Formats a `Date` with the current site’s default date format. | | `formatInteger(number)` → `String` | Formats a number using the site’s default integer format; floats are coerced to integers. | | `formatNumber(number)` → `String` | Formats a number using the site’s default number format. | | `garble(str, replaceChar, suffixLength)` → `String` | Masks a string, leaving the last `suffixLength` characters intact. | | `pad(str, width)` → `String` | Pads a string to a target width (useful for alignment in tables). | | `stringToHtml(str)` → `String` | Converts a string to an HTML-safe representation. | | `stringToWml(str)` → `String` | Converts a string to a WML-safe representation. | | `stringToXml(str)` → `String` | Converts a string to an XML-safe representation. | | `trim(str)` → `String` | Removes leading and trailing whitespace. | | `truncate(str, maxLength, mode, suffix)` → `String` | Truncates text using the provided mode and optional suffix. | **Example** ```html <isprint value="${StringUtils.pad('abc', 5)}" /> ``` ### `dw.web.URLUtils` `URLUtils` is also pre-imported. Use it for URL generation instead of manual string concatenation. | Method | Description | | --- | --- | | `abs(action, ...namesAndParams)` → `URL` | Generates an absolute URL using protocol and host from the calling request. | | `http(action, ...namesAndParams)` → `URL` | Generates an absolute HTTP URL using site preferences when available. | | `https(action, ...namesAndParams)` → `URL` | Generates an absolute HTTPS URL; respects secure host preferences. | | `httpsWebRoot()` → `URL` | Returns an absolute HTTPS web root URL for static asset references. | | `httpWebRoot()` → `URL` | Returns an absolute HTTP web root URL for static asset references. | | `url(action, ...namesAndParams)` → `URL` | Generates a relative URL. | | `webRoot()` → `URL` | Returns a relative web root URL for referencing static media. | **Example** ```html <form action="${URLUtils.httpsContinue()}" method="post" id="${pdict.CurrentForms.login.login.htmlName}" > </form> ``` --- ## ISML Expressions ISML expressions let templates embed storefront logic and data access inline, using syntax that mirrors JavaScript expressions. They are the primary way to render data from the Pipeline Dictionary (`pdict`) without resorting to `<isscript>` blocks. ### Expression Basics - **Syntax**: `${ ... }` where `${` begins the expression and `}` ends it. - **Scope**: Expressions evaluate in the context of template variables (`pdict`, `request`, `session`, etc.). - **Usage**: Place expressions directly in markup or inside tag attributes. Always ensure the data you reference has been added to `pdict` (by the controller, decorator, or include). #### Common Pattern ```html ${pdict.<KeyAttributeName>} ``` ### Expression Examples ```html <!-- Attribute value --> <isprint value="${pdict.Product.name}" /> <!-- Method call on a pdict object --> "${pdict.Product.getLongDescription() != null}" <!-- Using URL helper within an attribute --> <form action="${URLUtils.continueURL()}" method="post" id="${pdict.CurrentForms.cart.htmlName}" > </form> ``` ### Additional Quick References | Expression | Description | | --- | --- | | `${pdict.Product}` | References the current product object. | | `${pdict.Content.template}` | Accesses the content asset template attribute. | | `${pdict.ProductPrices}` | Outputs the product prices data structure placed in `pdict`. | | `${pdict.Order.orderNo}` | Outputs the current order number. | ### Protected `</body>` Tag The literal string `</body>` is reserved by the ISML parser. Do **not** include it in comments or inline scripts. If you need to emit the closing body tag from JavaScript, obfuscate it: ```javascript var endBodyIndex = markup.indexOf('</bo' + 'dy>'); ``` --- ### 4. Essential ISML Tags & Usage Renumbered after expanded section. ### Conditional Logic ```html <isif condition="${pdict.product.available}"> <span class="in-stock">In Stock</span> <iselseif condition="${pdict.product.preorderAvailable}"> <span class="preorder">Available for Pre-order</span> <iselse> <span class="out-of-stock">Out of Stock</span> </isif> ``` ### Loops with Status ```html <isloop items="${pdict.productSearch.productHits}" var="productHit" status="loopstate"> <div class="product-item ${loopstate.first ? 'first' : ''} ${loopstate.last ? 'last' : ''}"> <!-- Product content --> </div> <isif condition="${loopstate.count % 3 === 0 && !loopstate.last}"> </div><div class="row"> <!-- Start new row every 3 items --> </isif> </isloop> ``` ### Variable Setting Use `<isset>` sparingly and only for simple template variables: ```html <isset name="showRatings" value="${pdict.product.ratingsEnabled && pdict.product.reviews.count > 0}" scope="page" /> <isif condition="${showRatings}"> <isinclude template="product/components/reviews/reviewsSection" /> </isif> ``` ## Performance Optimization ### Caching Strategy **Controller-based caching** (preferred): ```javascript // In controller server.get('Show', cache.applyDefaultCache, function (req, res, next) { // Controller logic }); ``` **Template-based caching** (for personalized content, also preferred in the controller): ```html <iscache type="relative" hour="1" varyby="price_promotion" /> ``` ### Efficient Asset Loading ```html <isscript> var assets = require('*/cartridge/scripts/assets.js'); assets.addCss('/css/product.css'); assets.addJs('/js/product.js'); </isscript> ``` ## Localization Best Practices ### Simple Text Resources ```html <!-- Properties file: checkout.properties --> <!-- label.billing.address=Billing Address --> <label class="form-control-label"> ${Resource.msg('label.billing.address', 'checkout', 'Billing Address')} </label> ``` ### Parameterized Messages ```html <!-- Properties file: cart.properties --> <!-- items.in.cart=You have {0} items totaling {1} --> <div class="cart-summary"> ${Resource.msgf('items.in.cart', 'cart', null, pdict.basket.numItems, pdict.basket.subTotal)} </div> ``` ## Common Patterns & Examples ### 1. Form Rendering with Validation ```html <form action="${URLUtils.url('Account-SubmitRegistration')}" method="post"> <input type="hidden" name="${pdict.csrf.tokenName}" value="${pdict.csrf.token}"/> <div class="form-group ${pdict.forms.profile.customer.firstname.invalid ? 'is-invalid' : ''}"> <label for="registration-form-fname"> ${Resource.msg('field.customer.firstname', 'registration', null)} </label> <input type="text" class="form-control" id="registration-form-fname" name="${pdict.forms.profile.customer.firstname.htmlName}" value="${pdict.forms.profile.customer.firstname.htmlValue}" <isprint value="${pdict.forms.profile.customer.firstname.attributes}" encoding="off" />> <isif condition="${pdict.forms.profile.customer.firstname.invalid}"> <div class="invalid-feedback"> <isprint value="${pdict.forms.profile.customer.firstname.error}" /> </div> </isif> </div> </form> ``` ### 2. Product Grid with Pagination ```html <div class="search-results"> <div class="row product-grid"> <isloop items="${pdict.productSearch.productHits}" var="productHit"> <div class="col-6 col-sm-4 col-lg-3"> <isset name="product" value="${productHit.product}" scope="page" /> <isinclude template="product/components/productTile" /> </div> </isloop> </div> <isif condition="${pdict.productSearch.count > pdict.productSearch.pageSize}"> <isinclude template="search/components/pagination" /> </isif> </div> ``` ### 3. Responsive Image Handling ```html <picture class="product-image"> <source media="(max-width: 544px)" srcset="${pdict.product.images.small[0].url}"> <source media="(max-width: 768px)" srcset="${pdict.product.images.medium[0].url}"> <img src="${pdict.product.images.large[0].url}" alt="${pdict.product.images.large[0].alt}" title="${pdict.product.images.large[0].title}" class="img-fluid"> </picture> ``` ## Error Handling in Templates ### Defensive Programming ```html <isif condition="${pdict.product && pdict.product.available}"> <div class="product-availability"> <isif condition="${pdict.product.availabilityModel.availability > 0}"> <span class="in-stock"> ${Resource.msgf('label.quantity.in.stock', 'product', null, pdict.product.availabilityModel.availability)} </span> <iselse> <span class="limited-stock"> ${Resource.msg('label.limited.availability', 'product', null)} </span> </isif> </div> </isif> ``` ### Graceful Degradation ```html <div class="product-reviews"> <isif condition="${pdict.product.reviews && pdict.product.reviews.count > 0}"> <div class="reviews-summary"> <span class="review-count">${pdict.product.reviews.count}</span> <isinclude template="product/components/reviewStars" /> </div> <iselse> <div class="no-reviews"> ${Resource.msg('label.no.reviews', 'product', 'No reviews yet')} </div> </isif> </div> ``` ## Testing & Debugging ### Template Comments for Development ```html <iscomment> TODO: Implement wishlist functionality Controller needs to pass wishlist status in product model </iscomment> <iscomment> Debug: Product ID = ${pdict.product.id} Available = ${pdict.product.available} Price = ${pdict.product.price.sales.value} </iscomment> ``` ### Conditional Debug Output ```html <isif condition="${dw.system.System.getInstanceType() === dw.system.System.DEVELOPMENT_SYSTEM}"> <div class="debug-info" style="background: yellow; padding: 10px;"> <strong>Debug Info:</strong><br> Product ID: ${pdict.product.id}<br> Template: product/productDetails.isml<br> Timestamp: ${new Date()} </div> </isif> ``` ## Template Decoration and Layout ### The `<isreplace>` Element The `<isreplace>` element is a crucial component of SFCC's template decoration system. It identifies where the decorated content should be included within a decorator template. #### Syntax ```html <isreplace/> ``` #### Purpose and Behavior The decorator template uses `<isreplace/>` to specify the insertion point for decorated content. Understanding its behavior is essential for proper template architecture: - **Single `<isreplace/>` (typical)**: The decorated content is inserted at the location of the tag - **Multiple `<isreplace/>` tags**: The decorated content is duplicated at each tag location - **Zero `<isreplace/>` tags**: The decorated content is effectively omitted from the output #### Example 1: Basic Template Decoration **Rendering Template (uses decorator):** ```html <isset name="DecoratorTemplate" value="common/layout/page" scope="page"/> <isdecorate template="${DecoratorTemplate}"> <div class="product-details"> <h1>${pdict.product.displayName}</h1> <div class="price">${pdict.product.price.sales.formatted}</div> </div> </isdecorate> ``` **Decorator Template (`common/layout/page.isml`):** ```html <!DOCTYPE html> <html> <head> <title>${pdict.pageTitle}</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <div id="page-container"> <isinclude template="components/header" /> <main id="main-content"> <div class="content-wrapper"> <isreplace/> </div> </main> <isinclude template="components/footer" /> </div> </body> </html> ``` #### Example 2: Multiple `<isreplace/>` Tags **Decorator Template with Sidebar:** ```html <div class="layout-two-column"> <aside class="sidebar"> <div class="sidebar-content"> <isreplace/> </div> </aside> <main class="main-content"> <div class="content-area"> <isreplace/> </div> </main> </div> ``` *In this example, the decorated content appears in both the sidebar and main content areas.* #### Example 3: Conditional Content Placement **Advanced Decorator Pattern:** ```html <div class="page-layout"> <isinclude template="components/breadcrumb" /> <isif condition="${pdict.showInSidebar}"> <div class="with-sidebar"> <main class="content"> <isreplace/> </main> <aside class="sidebar"> <isinclude template="components/relatedProducts" /> </aside> </div> <iselse> <main class="full-width"> <isreplace/> </main> </isif> </div> ``` #### Best Practices for `<isreplace>` 1. **Single Replacement Point**: Use one `<isreplace/>` per decorator for clarity and maintainability 2. **Semantic Placement**: Position `<isreplace/>` within semantic HTML elements (`<main>`, `<section>`, etc.) 3. **CSS Class Structure**: Wrap `<isreplace/>` in containers with appropriate CSS classes for styling 4. **Documentation**: Comment complex decorator patterns to explain the layout structure #### Common Patterns **Standard Page Layout:** ```html <isdecorate template="common/layout/page"> <!-- Page-specific content goes here --> </isdecorate> ``` **Modal/Dialog Layout:** ```html <isdecorate template="common/layout/modal"> <!-- Modal content goes here --> </isdecorate> ``` **Email Template Layout:** ```html <isdecorate template="common/layout/email"> <!-- Email content goes here --> </isdecorate> ``` ## SFRA Base Templates Architecture Understanding SFRA's base template structure is crucial for effective storefront development. SFRA provides a well-organized hierarchy of layout templates, page-specific templates, and reusable components that work together to create consistent user experiences. **IMPORTANT**: SFRA uses **Bootstrap 4** as its foundational CSS framework, providing responsive grid systems, utility classes, and component styling throughout all templates. Understanding Bootstrap classes and responsive breakpoints is essential for effective SFRA development. ### Core Layout Templates SFRA uses a **three-tier layout system** with base layouts that define the overall page structure: #### 1. Main Page Layout (`common/layout/page.isml`) The primary layout for most storefront pages including homepage, product details, search results, and category pages: ```html <iscontent type="text/html" charset="UTF-8" compact="true"/> <isinclude template="/components/modules" sf-toolkit="off" /> <!DOCTYPE html> <html lang="${require('dw/util/Locale').getLocale(request.getLocale()).getLanguage()}"> <head> <!--[if gt IE 9]><!--> <isinclude sf-toolkit="off" template="/common/scripts" /> <!--<![endif]--> <isinclude template="/common/htmlHead" /> <isif condition="${pdict.canonicalUrl}" > <link rel="canonical" href="${pdict.canonicalUrl}"/> </isif> <isactivedatahead/> <isinclude template="/components/schema" /> </head> <body> ${dw.system.HookMgr.callHook('app.template.beforeHeader', 'beforeHeader', pdict) || ''} <div class="page" data-action="${pdict.action}" data-querystring="${pdict.queryString}" > <isinclude template="/components/header/pageHeader" /> <div role="main" id="maincontent"> <isreplace/> </div> <isinclude template="/components/footer/pageFooter" /> </div> <div class="error-messaging"></div> <div class="modal-background"></div> <iscontentasset aid="cookie_hint" /> <!--[if lt IE 10]> <isinclude sf-toolkit="off" template="/common/scripts" /> <![endif]--> <iscomment> hook for Marketing Cloud connector & other integration which need to inject logic at the page end IMPORTANT: Note that this hook will be called to cached as well as uncached pages which means you need to put privacy information into another remote include </iscomment> ${dw.system.HookMgr.callHook('app.template.afterFooter', 'afterFooter', pdict) || ''} <isinclude url="${URLUtils.url('ConsentTracking-Check')}"/> </body> </html> ``` **Key Features:** - **Full navigation header**: Includes main menu, search, and account links via `pageHeader` - **Hook integration**: `beforeHeader` and `afterFooter` hooks for customization - **SEO elements**: Canonical URLs, structured data, meta tags - **Accessibility**: Proper ARIA roles and semantic HTML - **Analytics support**: ActiveData integration - **Error handling**: Error messaging and modal background containers #### 2. Checkout Layout (`common/layout/checkout.isml`) Complete layout for checkout process with minimal navigation header: ```html <iscontent type="text/html" charset="UTF-8" compact="true"/> <isinclude template="/components/modules" sf-toolkit="off" /> <!DOCTYPE html> <html lang="${require('dw/util/Locale').getLocale(request.getLocale()).getLanguage()}"> <head> <!--[if gt IE 9]><!--> <isinclude sf-toolkit="off" template="/common/scripts" /> <!--<![endif]--> <isinclude template="/common/htmlHead" /> <isactivedatahead/> </head> <body> ${dw.system.HookMgr.callHook('app.template.beforeHeader', 'beforeHeader', pdict) || ''} <div class="page"> <isinclude template="/components/header/pageHeaderNomenu" /> <div role="main" id="maincontent"> <isreplace/> </div> <isinclude template="/components/footer/pageFooter" /> </div> <!--[if lt IE 10]> <isinclude sf-toolkit="off" template="/common/scripts" /> <![endif]--> <iscomment> hook for Marketing Cloud connector & other integration which need to inject logic at the page end IMPORTANT: Note that this hook will be called to cached as well as uncached pages which means you need to put privacy information into another remote include </iscomment> ${dw.system.HookMgr.callHook('app.template.afterFooter', 'afterFooter', pdict) || ''} <isinclude url="${URLUtils.url('ConsentTracking-Check')}"/> </body> </html> ``` **Key Features:** - **Simplified header**: `pageHeaderNomenu` without main navigation menu - **Secure context**: HTTPS enforcement and minimal external dependencies - **Same structure as main layout**: Maintains consistency while removing distractions - **Hook support**: Full hook integration for customization - **Accessibility**: Maintains ARIA roles and semantic structure #### 3. Page Designer Store Layout (`common/layout/pdStorePage.isml`) Specialized layout for Page Designer store pages with campaign banner support: ```html <iscontent type="text/html" charset="UTF-8" compact="true"/> <isinclude template="/components/modules" sf-toolkit="off" /> <!-- Include Page Designer Campaign Banner JavaScript and Styles only once here rather than at component level. --> <!-- There should only be one Campagin Banner added on a PD page. Multiple Banners is unsupported at the moment. --> <isif condition="${pdict.resetEditPDMode}"> <script> var resetCampaignBannerSessionToken = true; </script> </isif> <isscript> var assets = require('*/cartridge/scripts/assets.js'); assets.addCss('/css/experience/components/commerceAssets/campaignBanner.css'); assets.addJs('/js/campaignBanner.js'); </isscript> <!DOCTYPE html> <html lang="${require('dw/util/Locale').getLocale(request.getLocale()).getLanguage()}"> <head> <!--[if gt IE 9]><!--> <isinclude sf-toolkit="off" template="/common/scripts" /> <!--<![endif]--> <isinclude template="/common/htmlHead" /> <isif condition="${pdict.canonicalUrl}" > <link rel="canonical" href="${pdict.canonicalUrl}"/> </isif> <isactivedatahead/> <isinclude template="/components/schema" /> </head> <body> ${dw.system.HookMgr.callHook('app.template.beforeHeader', 'beforeHeader', pdict) || ''} <div class="page" data-action="${pdict.action}" data-querystring="${pdict.queryString}" > <isinclude template="/components/header/pdStorePageHeader" /> <div role="main" id="maincontent"> <isreplace/> </div> <isinclude template="/components/footer/pageFooter" /> </div> <div class="error-messaging"></div> <div class="modal-background"></div> <iscontentasset aid="cookie_hint" /> <!--[if lt IE 10]> <isinclude sf-toolkit="off" template="/common/scripts" /> <![endif]--> <iscomment> hook for Marketing Cloud connector & other integration which need to inject logic at the page end IMPORTANT: Note that this hook will be called to cached as well as uncached pages which means you need to put privacy information into another remote include </iscomment> ${dw.system.HookMgr.callHook('app.template.afterFooter', 'afterFooter', pdict) || ''} <isinclude url="${URLUtils.url('ConsentTracking-Check')}"/> </body> </html> ``` **Key Features:** - **Page Designer header**: Uses `pdStorePageHeader` for Page Designer-specific navigation - **Campaign banner support**: Includes campaign banner CSS and JavaScript assets - **Edit mode support**: Handles Page Designer edit mode with session token reset - **Same core structure**: Maintains consistency with main layout - **SEO and analytics**: Full SEO and analytics support ### SFRA Page Template Patterns #### Homepage Template Structure ```html <isdecorate template="common/layout/page"> <isscript> var assets = require('*/cartridge/scripts/assets.js'); assets.addJs('/js/productTile.js'); assets.addCss('/css/homePage.css'); </isscript> <div class="home-main homepage"> <isslot id="home-main-m" description="Main home page slot." context="global" /> </div> <div class="container home-categories homepage"> <div class="row home-main-categories no-gutters"> <isslot id="home-categories-m" description="Categories slots on the home page." context="global" /> </div> </div> <div class="container home-product-tiles homepage"> <div class="hp-product-grid" itemtype="http://schema.org/SomeProducts" itemid="#product"> <isslot id="home-products-m" description="Product tiles on the home page." context="global" /> </div> </div> </isdecorate> ``` **Pattern Highlights:** - **Content slots**: Uses Business Manager-configurable content slots - **Asset management**: Page-specific CSS and JavaScript loading - **SEO structure**: Schema.org markup for products - **Responsive design**: Bootstrap grid system integration #### Product Detail Page Structure ```html <isdecorate template="common/layout/page"> <isscript> var assets = require('*/cartridge/scripts/assets'); assets.addJs('/js/productDetail.js'); assets.addCss('/css/product/detail.css'); </isscript> <isset name="product" value="${pdict.product}" scope="page" /> <isset name="isQuickView" value="${false}" scope="page" /> <isset name="isProductSet" value="${pdict.product.productType === 'set'}" scope="page" /> <isobject object="${product.raw}" view="detail"> <div class="container product-detail product-wrapper" data-pid="${product.id}"> <div class="row"> <div class="col-12"> <div class="product-breadcrumb d-md-none"> <isinclude template="components/breadcrumbs/pageBreadcrumbs"/> </div> <div class="row"> <div class="d-md-none col-sm-12"> <h1 class="product-name">${product.productName}</h1> </div> </div> </div> </div> <!-- Product images, details, add to cart, etc. --> </div> </isobject> </isdecorate> ``` **Pattern Highlights:** - **Product context**: `<isobject>` tag for product data binding - **Variable scoping**: Page-scoped variables for template logic - **Mobile-first design**: Responsive breakpoint handling - **SEO optimization**: Structured product data and breadcrumbs #### Cart Page Structure ```html <isdecorate template="common/layout/page"> <isscript> var assets = require('*/cartridge/scripts/assets.js'); assets.addCss('/css/cart.css'); </isscript> <isif condition="${pdict.reportingURLs && pdict.reportingURLs.length}"> <isinclude template="reporting/reportingUrls" /> </isif> <div class="cart-error-messaging cart-error"> <isif condition="${pdict.valid.error && pdict.items.length !== 0}"> <div class="alert alert-danger alert-dismissible valid-cart-error fade show" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="Close"> <span aria-hidden="true">×</span> </button> ${pdict.valid.message} </div> </isif> </div> <div class="container"> <h1 class="page-title">${Resource.msg('title.cart','cart',null)}</h1> <div class="row cart-header"> <div class="col-sm-4 hidden-xs-down"> <a class="continue-shopping-link" href="${URLUtils.url('Home-Show')}" title="${Resource.msg('link.continue.shopping','cart',null)}"> ${Resource.msg('link.continue.shopping','cart',null)} </a> </div> <div class="col-sm-3 text-center"> <h2 class="number-of-items">${Resource.msgf('label.number.items.in.cart','cart', null, pdict.numItems)}</h2> </div> <div class="col-sm-5 text-right hidden-xs-down"> <div> <span>${Resource.msg('info.need.help','cart',null)}</span> <span><a class="help-phone-number" href="tel:${Resource.msg('info.phone.number','common',null)}">${Resource.msg('info.phone.number','common',null)}</a></span> </div> </div> </div> <hr class="no-margin-top"> </div> <isif condition="${pdict.items.length === 0}"> <div class="container cart-empty"> <div class="row"> <div class="col-12 text-center"> <h1>${Resource.msg('info.cart.empty.msg','cart',null)}</h1> </div> </div> </div> <iselse/> <div class="container cart cart-page"> <div class="row"> <!---product cards---> <div class="col-sm-7 col-md-8"> <isloop items="${pdict.items}" var="lineItem"> <isif condition="${lineItem.productType === 'bundle'}"> <isinclude template="cart/productCard/cartBundleCard" /> <iselse/> <isif condition="${lineItem.noProduct === true}"> <isinclude template="cart/productCard/uncategorizedCartProductCard" /> <iselse/> <isinclude template="cart/productCard/cartProductCard" /> </isif> </isif> </isloop> <isinclude template="cart/cartApproachingDiscount" /> </div> <!---totals, and checkout actions---> <div class="col-sm-5 col-md-4 totals"> <isinclude template="cart/cartPromoCode" /> <div class="coupons-and-promos"> <isinclude template="cart/cartCouponDisplay" /> </div> <div class="row"> <isinclude template="cart/cartShippingMethodSelection" /> </div> <isinclude template="cart/cartTotals" /> <div class="row"> <div class="col-12 checkout-continue"> <isinclude template="cart/checkoutButtons" /> </div> </div> </div> </div> <isinclude template="cart/cartRemoveProductModal"/> </div> <isinclude template="cart/cartRemoveCouponModal"/> </isif> <div class="container"> <isslot id="cart-recommendations-m" description="Recommended products" context="global" /> </div> </isdecorate> ``` **Pattern Highlights:** - **Error handling**: Comprehensive validation error display with dismissible alerts - **Analytics integration**: Reporting URL includes for tracking - **User feedback**: Alert system for cart validation messages - **Empty cart state**: Dedicated empty cart display with clear messaging - **Product cards**: Dynamic product card rendering based on product type (bundle, regular, uncategorized) - **Responsive layout**: Bootstrap grid system for desktop and mobile layouts - **Promotional features**: Coupon display, promo codes, and approaching discount messaging - **Checkout integration**: Seamless transition to checkout with proper button placement - **Recommendations**: Content slot for product recommendations - **Modal support**: Product removal and coupon removal modals #### Account Page Structure ```html <isdecorate template="common/layout/page"> <isscript> var assets = require('*/cartridge/scripts/assets.js'); assets.addJs('/js/account.js'); assets.addCss('/css/account.css'); </isscript> <div class="hero slant-down account-hero"> <div class="container"> <h1 class="page-title">${Resource.msg('page.heading.myaccount','account',null)}</h1> </div> </div> <div class="container"> <div class="row justify-content-center"> <div class="col"> <div class="myaccount-row"> <!-- Account Navigation --> <div class="col-sm-3"> <div class="account-nav"> <isinclude template="account/accountNav" /> </div> </div> <!-- Account Content --> <div class="col-sm-9"> <div class="card"> <div class="card-header"> <h2 class="pull-left">${pdict.pageTitle}</h2> </div> <div class="card-body card-body-positioning"> <!-- Page-specific content will be inserted here --> <isif condition="${pdict.addressBook}"> <isinclude template="account/addressBook" /> <iselseif condition="${pdict.orderHistory}"> <isinclude template="account/orderHistory" /> <iselseif condition="${pdict.profile}"> <isinclude template="account/profile" /> <iselseif condition="${pdict.paymentInstruments}"> <isinclude template="account/payment/paymentMethods" /> <iselse> <isinclude template="account/dashboard" /> </isif> </div> </div> </div> </div> </div> </div> </div> </isdecorate> ``` **Pattern Highlights:** - **Account navigation**: Consistent sidebar navigation across all account pages - **Card-based layout**: Professional UI with card components - **Conditional content**: Dynamic content loading based on page type - **Responsive design**: Mobile-friendly account management interface #### Search Results Page Structure ```html <isdecorate template="common/layout/page"> <isscript> var assets = require('*/cartridge/scripts/assets.js'); assets.addJs('/js/search.js'); assets.addCss('/css/search.css'); </isscript> <div class="search-results-header"> <div class="container"> <div class="row"> <div class="col-sm-12"> <h1 class="header page-title"> <isif condition="${pdict.productSearch.isCategorySearch}"> ${pdict.productSearch.category.name} <iselse> ${Resource.msgf('heading.search.results', 'search', null, pdict.productSearch.searchKeywords)} </isif> </h1> <!-- Search Result Count --> <div class="result-count pull-left"> <isinclude template="search/searchResultsCount"/> </div> </div> </div> </div> </div> <div class="container search-results"> <div class="row search-nav"> <div class="tab-content col-12"> <div class="tab-pane container active" id="product-search-results"> <div class="row grid-header"> <div class="result-count col-6 col-md-9 order-2 order-md-1"> <isinclude template="search/searchResultsCount"/> </div> <div class="col-6 col-md-3 order-1 order-md-2"> <isinclude template="search/sortOrderMenu"/> </div> </div> <!-- Refinements and Product Grid --> <div class="row"> <!-- Refinements Sidebar --> <div class="refinement-bar col-md-3"> <isinclude template="search/refinements"/> </div> <!-- Product Grid --> <div class="col-sm-12 col-md-9"> <div class="container"> <isif condition="${pdict.productSearch.productHits.length > 0}"> <!-- Product Grid --> <div class="row product-grid" itemtype="http://schema.org/SomeProducts" itemid="#product"> <isloop items="${pdict.productSearch.productHits}" var="productHit"> <div class="col-6 col-sm-4 product-tile-wrapper"> <isset name="product" value="${productHit.product}" scope="page" /> <div class="product-tile" data-pid="${product.id}" data-gtm-product='${JSON.stringify(product.gtm)}'> <isinclude template="product/productTile"/> </div> </div> </isloop> </div> <!-- Pagination --> <div class="row"> <isinclude template="search/searchResultsPagination"/> </div> <!-- Show More Products --> <div class="row"> <div class="col-12 text-center"> <div class="show-more btn btn-outline-primary" data-url="${pdict.productSearch.showMoreUrl}"> ${Resource.msg('button.search.showmore', 'search', null)} </div> </div> </div> <iselse> <!-- No Results --> <div class="row justify-content-center"> <div class="col"> <div class="no-results-message"> <h3>${Resource.msg('heading.no.results', 'search', null)}</h3> <p>${Resource.msg('msg.no.results', 'search', null)}</p> <!-- Search Suggestions --> <isif condition="${pdict.productSearch.searchSuggestions && pdict.productSearch.searchSuggestions.length > 0}"> <div class="search-suggestions"> <p>${Resource.msg('label.search.suggestions', 'search', null)}</p> <ul class="suggestions-list"> <isloop items="${pdict.productSearch.searchSuggestions}" var="suggestion"> <li><a href="${suggestion.url}">${suggestion.value}</a></li> </isloop> </ul> </div> </isif> </div> </div> </div> </isif> </div> </div> </div> </div> </div> </div> </div> <!-- Recently Viewed --> <div class="container"> <isinclude template="search/components/recentlyViewed"/> </div> </isdecorate> ``` **Pattern Highlights:** - **Dual search support**: Category browsing and keyword search functionality - **Advanced filtering**: Refinement sidebar with faceted search - **Responsive grid**: Product tiles with mobile-optimized layout - **Pagination system**: Multiple pagination patterns including "show more" - **No results handling**: Graceful degradation with search suggestions #### Category Landing Page Structure ```html <isdecorate template="common/layout/page"> <isscript> var assets = require('*/cartridge/scripts/assets.js'); assets.addJs('/js/categoryLanding.js'); assets.addCss('/css/categoryLanding.css'); </isscript> <!-- Category Hero Section --> <div class="hero category-hero" <isif condition="${pdict.category.image}">style="background-image: url('${pdict.category.image}')"</isif>> <div class="container"> <div class="row"> <div class="col-12 text-center"> <h1 class="category-title">${pdict.category.displayName}</h1> <isif condition="${pdict.category.description}"> <p class="category-description">${pdict.category.description}</p> </isif> </div> </div> </div> </div> <!-- Breadcrumbs --> <div class="container"> <div class="row"> <div class="col-12"> <isinclude template="components/breadcrumbs/pageBreadcrumbs"/> </div> </div> </div> <!-- Category Content Slots --> <isif condition="${pdict.category.template && pdict.category.template !== ''}"> <!-- Custom Category Template --> <isinclude template="${pdict.category.template}"/> <iselse> <!-- Default Category Content --> <div class="container category-content"> <!-- Category Slots --> <div class="category-slots"> <isslot id="category-banner" description="Category banner content" context="category" context-object="${pdict.category.raw}" /> </div> <!-- Sub-categories --> <isif condition="${pdict.category.subCategories && pdict.category.subCategories.length > 0}"> <div class="sub-categories"> <div class="row"> <div class="col-12"> <h2 class="sub-categories-title">${Resource.msg('heading.browse.categories', 'search', null)}</h2> </div> </div> <div class="row"> <isloop items="${pdict.category.subCategories}" var="subCategory"> <div class="col-6 col-md-4 col-lg-3"> <div class="category-tile"> <a href="${subCategory.url}" class="category-link"> <isif condition="${subCategory.image}"> <div class="category-image"> <img src="${subCategory.image}" alt="${subCategory.displayName}" class="img-fluid"> </div> </isif> <div class="category-info"> <h3 class="category-name">${subCategory.displayName}</h3> <isif condition="${subCategory.productCount}"> <span class="product-count"> ${Resource.msgf('label.category.product.count', 'search', null, subCategory.productCount)} </span> </isif> </div> </a> </div> </div> </isloop> </div> </div> </isif> <!-- Featured Products --> <isif condition="${pdict.productSearch && pdict.productSearch.productHits.length > 0}"> <div class="featured-products"> <div class="row"> <div class="col-12"> <h2 class="featured-title">${Resource.msg('heading.featured.products', 'search', null)}</h2> </div> </div> <div class="row product-grid"> <isloop items="${pdict.productSearch.productHits}" var="productHit" begin="0" end="7"> <div class="col-6 col-md-4 col-lg-3"> <isset name="product" value="${productHit.product}" scope="page" /> <isinclude template="product/productTile"/> </div> </isloop> </div> <div class="row"> <div class="col-12 text-center"> <a href="${pdict.category.url}?showAll=true" class="btn btn-primary"> ${Resource.msg('button.view.all.products', 'search', null)} </a> </div> </div> </div> </isif> <!-- Category Content Slots --> <div class="category-content-slots"> <isslot id="category-content" description="Category content area" context="category" context-object="${pdict.category.raw}" /> </div> </div> </isif> </isdecorate> ``` **Pattern Highlights:** - **Hero section**: Visual category introduction with background imagery - **Content slots**: Business Manager-configurable category content - **Sub-category navigation**: Hierarchical category browsing - **Featured products**: Limited product showcase with view-all option - **Flexible templating**: Support for custom category templates #### Login/Registration Page Structure ```html <isdecorate template="common/layout/page"> <isscript> var assets = require('*/cartridge/scripts/assets.js'); assets.addJs('/js/login.js'); assets.addCss('/css/login.css'); </isscript> <div class="hero slant-down login-banner"> <h1 class="page-title">${Resource.msg('title.login.page', 'login', null)}</h1> </div> <div class="container login-page"> <div class="row justify-content-center"> <!-- Login Form --> <div class="col-md-6"> <div class="card login-form-nav"> <div class="card-header"> <h2>${Resource.msg('heading.returning.customers', 'login', null)}</h2> </div> <div class="card-body"> <form action="${URLUtils.url('Account-Login')}" class="login" method="post" name="login-form"> <input type="hidden" name="${pdict.csrf.tokenName}" value="${pdict.csrf.token}"/> <!-- Email Field --> <div class="form-group <isif condition="${pdict.loginForm.username.invalid}">is-invalid</isif>"> <label class="form-control-label" for="login-form-email"> <isprint value="${pdict.loginForm.username.label}" encoding="htmlcontent" /> </label> <input type="email" required class="form-control" id="login-form-email" name="${pdict.loginForm.username.htmlName}" value="${pdict.loginForm.username.value}" autocomplete="email"> <isif condition="${pdict.loginForm.username.invalid}"> <div class="invalid-feedback"> <isprint value="${pdict.loginForm.username.error}" /> </div> </isif> </div> <!-- Password Field --> <div class="form-group <isif condition="${pdict.loginForm.password.invalid}">is-invalid</isif>"> <label class="form-control-label" for="login-form-password"> <isprint value="${pdict.loginForm.password.label}" encoding="htmlcontent" /> </label> <input type="password" required class="form-control" id="login-form-password" name="${pdict.loginForm.password.htmlName}" autocomplete="current-password"> <isif condition="${pdict.loginForm.password.invalid}"> <div class="invalid-feedback"> <isprint value="${pdict.loginForm.password.error}" /> </div> </isif> </div> <!-- Remember Me --> <div class="form-group custom-control custom-checkbox"> <input type="checkbox" class="custom-control-input" id="rememberMe" name="${pdict.loginForm.rememberMe.htmlName}" value="true" <isif condition="${pdict.loginForm.rememberMe.checked}">checked</isif>> <label class="custom-control-label" for="rememberMe"> ${Resource.msg('field.login.remember.me', 'login', null)} </label> </div> <!-- Login Button --> <button type="submit" class="btn btn-primary btn-block login-btn"> ${Resource.msg('button.text.loginform', 'login', null)} </button> <!-- Forgot Password --> <div class="forgot-password text-center"> <a href="${URLUtils.url('Account-PasswordReset')}" title="${Resource.msg('link.login.forgotpassword', 'login', null)}"> ${Resource.msg('link.login.forgotpassword', 'login', null)} </a> </div> </form> </div> </div> </div> <!-- Registration Form --> <div class="col-md-6"> <div class="card registration-form-nav"> <div class="card-header"> <h2>${Resource.msg('heading.new.customers', 'login', null)}</h2> </div> <div class="card-body"> <p>${Resource.msg('msg.create.account', 'login', null)}</p> <form action="${URLUtils.url('Account-SubmitRegistration')}" class="registration" method="post" name="registration-form"> <input type="hidden" name="${pdict.csrf.tokenName}" value="${pdict.csrf.token}"/> <!-- First Name --> <div class="form-group <isif condition="${pdict.registrationForm.customer.firstname.invalid}">is-invalid</isif>"> <label class="form-control-label" for="registration-form-fname"> <isprint value="${pdict.registrationForm.customer.firstname.label}" encoding="htmlcontent" /> </label> <input type="text" required class="form-control" id="registration-form-fname" name="${pdict.registrationForm.customer.firstname.htmlName}" value="${pdict.registrationForm.customer.firstname.value}" autocomplete="given-name"> <isif condition="${pdict.registrationForm.customer.firstname.invalid}"> <div class="invalid-feedback"> <isprint value="${pdict.registrationForm.customer.firstname.error}" /> </div> </isif> </div> <!-- Last Name --> <div class="form-group <isif condition="${pdict.registrationForm.customer.lastname.invalid}">is-invalid</isif>"> <label class="form-control-label" for="registration-form-lname"> <isprint value="${pdict.registrationForm.customer.lastname.label}" encoding="htmlcontent" /> </label> <input type="text" required class="form-control" id="registration-form-lname" name="${pdict.registrationForm.customer.lastname.htmlName}" value="${pdict.registrationForm.customer.lastname.value}" autocomplete="family-name"> <isif condition="${pdict.registrationForm.customer.lastname.invalid}"> <div class="invalid-feedback"> <isprint value="${pdict.registrationForm.customer.lastname.error}" /> </div> </isif> </div> <!-- Email --> <div class="form-group <isif condition="${pdict.registrationForm.customer.email.invalid}">is-invalid</isif>"> <label class="form-control-label" for="registration-form-email"> <isprint value="${pdict.registrationForm.customer.email.label}" encoding="htmlcontent" /> </label> <input type="email" required class="form-control" id="registration-form-email" name="${pdict.registrationForm.customer.email.htmlName}" value="${pdict.registrationForm.customer.email.value}" autocomplete="email"> <isif condition="${pdict.registrationForm.customer.email.invalid}"> <div class="invalid-feedback"> <isprint value="${pdict.registrationForm.customer.email.error}" /> </div> </isif> </div> <!-- Password --> <div class="form-group <isif condition="${pdict.registrationForm.newPasswords.newpassword.invalid}">is-invalid</isif>"> <label class="form-control-label" for="registration-form-password"> <isprint value="${pdict.registrationForm.newPasswords.newpassword.label}" encoding="htmlcontent" /> </label> <input type="password" required class="form-control" id="registration-form-password" name="${pdict.registrationForm.newPasswords.newpassword.htmlName}" autocomplete="new-password"> <isif condition="${pdict.registrationForm.newPasswords.newpassword.invalid}"> <div class="invalid-feedback"> <isprint value="${pdict.registrationForm.newPasswords.newpassword.error}" /> </div> </isif> </div> <!-- Confirm Password --> <div class="form-group <isif condition="${pdict.registrationForm.newPasswords.newpasswordconfirm.invalid}">is-invalid</isif>"> <label class="form-control-label" for="registration-form-password-confirm"> <isprint value="${pdict.registrationForm.newPasswords.newpasswordconfirm.label}" encoding="htmlcontent" /> </label> <input type="password" required class="form-control" id="registration-form-password-confirm" name="${pdict.registrationForm.newPasswords.newpasswordconfirm.htmlName}" autocomplete="new-password"> <isif condition="${pdict.registrationForm.newPasswords.newpasswordconfirm.invalid}"> <div class="invalid-feedback"> <isprint value="${pdict.registrationForm.newPasswords.newpasswordconfirm.error}" /> </div> </isif> </div> <!-- Privacy Policy --> <div class="form-group custom-control custom-checkbox"> <input type="checkbox" required class="custom-control-input" id="add-to-email-list" name="${pdict.registrationForm.customer.addtoemaillist.htmlName}" value="true"> <label class="custom-control-label" for="add-to-email-list"> ${Resource.msg('label.registration.email.subscribe', 'login', null)} </label> </div> <!-- Create Account Button --> <button type="submit" class="btn btn-primary btn-block create-account-btn"> ${Resource.msg('button.createaccount.registration', 'login', null)} </button> </form> </div> </div> </div> </div> </div> </isdecorate> ``` **Pattern Highlights:** - **Dual-form layout**: Login and registration side-by-side - **Form validation**: Client and server-side validation with error display - **Accessibility features**: Proper form labels, autocomplete attributes - **Security elements**: CSRF protection and password requirements - **Mobile responsiveness**: Stacked layout on smaller screens ## Common Components Architecture SFRA organizes reusable components in the `/components/` directory: #### HTML Head Component (`common/htmlHead.isml`) ```html <meta charset=UTF-8> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <isif condition="${dw.system.System.getInstanceType() != dw.system.System.PRODUCTION_SYSTEM}"> <title>${pdict.CurrentPageMetaData.title} | ${Resource.msg('global.site.name', 'version', null)} | ${Resource.msg('global.version.number', 'version', null)}</title> <iselse/> <title><isprint value="${pdict.CurrentPageMetaData.title}" encoding="htmlcontent" /></title> </isif> <meta name="description" content="${pdict.CurrentPageMetaData.description ? pdict.CurrentPageMetaData.description : Resource.msg('global.storename','common',null)}"/> <meta name="keywords" content="${pdict.CurrentPageMetaData.keywords ? pdict.CurrentPageMetaData.keywords : Resource.msg('global.storename','common',null)}"/> <!-- Rule-based page meta tags --> <isloop items="${pdict.CurrentPageMetaData.pageMetaTags}" var="pageMetaTag"> <isif condition="${pageMetaTag.name}"> <meta name="<isprint value="${pageMetaTag.ID}">" content="<isprint value="${pageMetaTag.content}">"> <iselseif condition="${pageMetaTag.property}"> <meta property="<isprint value="${pageMetaTag.ID}">" content="<isprint value="${pageMetaTag.content}">"> </isif> </isloop> <!-- Favicons --> <link rel="icon" type="image/png" href="${URLUtils.staticURL('/images/favicons/favicon-196x196.png')}" sizes="196x196" /> <!-- Additional favicon sizes... --> ``` **Component Features:** - **Environment awareness**: Different titles for non-production environments - **SEO management**: Dynamic meta tags from Page Designer or manual configuration - **Multi-device support**: Comprehensive favicon set - **Content security**: Proper encoding for meta content ### SFRA Template Directory Structure ``` templates/default/ ├── common/ # Shared layout and utility templates │ ├── layout/ │ │ ├── page.isml # Main page layout │ │ ├── checkout.isml # Checkout layout │ │ └── pdStorePage.isml # Page Designer layout │ ├── htmlHead.isml # HTML head component │ ├── scripts.isml # JavaScript includes │ └── consent.isml # Cookie consent ├── components/ # Reusable UI components │ ├── header/ # Header variations │ ├── footer/ # Footer components │ ├── breadcrumbs/ # Navigation breadcrumbs │ ├── modules.isml # Module registration │ └── schema.isml # Structured data ├── home/ # Homepage templates │ └── homePage.isml # Main homepage ├── product/ # Product-related templates │ ├── productD etails.isml # PDP template │ ├── productTile.isml # Product tile component │ └── quickView.isml # Quick view modal ├── cart/ # Shopping cart templates │ └── cart.isml # Cart page ├── checkout/ # Checkout process templates │ └── checkout.isml # Main checkout ├── account/ # Customer account templates │ ├── login.isml # Login page │ ├── profile.isml # Account profile │ └── orderHistory.isml # Order history ├── search/ # Search and category templates │ └── searchResults.isml # Search results page └── error/ # Error page templates ├── error.isml # Generic error page └── notFound.isml # 404 page ``` ### Best Practices for SFRA Template Development #### 1. Follow the Layout Hierarchy ```html <!-- ✅ Use appropriate base layout --> <isdecorate template="common/layout/page"> <!-- Standard page content --> </isdecorate> <!-- ✅ Use checkout layout for secure pages --> <isdecorate template="common/layout/checkout"> <!-- Checkout/payment content --> </isdecorate> ``` #### 2. Leverage Component Reusability ```html <!-- ✅ Include reusable components --> <isinclude template="components/breadcrumbs/pageBreadcrumbs" /> <isinclude template="components/product/productTile" /> ``` #### 3. Implement Proper Asset Management ```html <!-- ✅ Page-specific assets --> <isscript> var assets = require('*/cartridge/scripts/assets.js'); assets.addCss('/css/product/detail.css'); assets.addJs('/js/productDetail.js'); </isscript> ``` #### 4. Use Semantic HTML Structure ```html <!-- ✅ Semantic and accessible markup --> <main id="maincontent" role="main"> <article class="product-detail"> <header class="product-header"> <h1 class="product-name">${product.productName}</h1> </header> <section class="product-images"> <!-- Product imagery --> </section> </article> </main> ``` #### 5. Implement Responsive Design Patterns ```html <!-- ✅ Mobile-first responsive structure --> <div class="row"> <div class="col-12 col-md-6 col-lg-4"> <!-- Mobile: full width, tablet: half, desktop: one-third --> </div> </div> <!-- ✅ Progressive disclosure --> <div class="product-breadcrumb d-md-none"> <!-- Only show on mobile --> </div> <div class="d-none d-md-block"> <!-- Only show on tablet and up --> </div> ``` This SFRA base template architecture provides a solid foundation for building consistent, maintainable, and scalable storefronts while following Commerce Cloud best practices for performance, security, and user experience ## Quick Reference Tables ### Essential ISML Tags | Tag | Purpose | Example | |-----|---------|---------| | `<isprint>` | Output data safely | `<isprint value="${pdict.product.name}" />` | | `<isif>` | Conditional logic | `<isif condition="${product.available}">` | | `<isloop>` | Iterate collections | `<isloop items="${products}" var="product">` | | `<isinclude>` | Include templates | `<isinclude template="components/header" />` | | `<isdecorate>` | Apply layout | `<isdecorate template="common/layout/page">` | | `<isset>` | Set variables | `<isset name="showPrice" value="${true}" scope="page" />` | ### URL Generation Functions | Function | Purpose | Example | |----------|---------|---------| | `URLUtils.url()` | Relative URLs | `URLUtils.url('Product-Show', 'pid', product.id)` | | `URLUtils.https()` | Secure URLs | `URLUtils.https('Account-Login')` | | `URLUtils.staticURL()` | Static assets | `URLUtils.staticURL('/images/logo.png')` | Remember: **Keep business logic in controllers, use ISML only for presentation, and always encode output for security.** ``` -------------------------------------------------------------------------------- /docs/dw_order/LineItemCtnr.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.order # Class LineItemCtnr ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.object.ExtensibleObject - dw.order.LineItemCtnr ## Description A container for line items, such as ProductLineItems, CouponLineItems, GiftCertificateLineItems. This container also provides access to shipments, shipping adjustments (promotions), and payment instruments (credit cards). LineItemCtnr also contains a set of methods for creating line items and adjustments, and for accessing various price values. There are three types of price-related methods: Net-based methods represent the amount of a category before tax has been calculated. For example, the getMerchandizeTotalNetPrice() returns the price of all merchandise in the container whereas getShippingTotalNetPrice() returns the price of all shipments in the container. Tax-based methods return the amount of tax on a category. For example, the getMerchandizeTotalTax() returns the total tax for all merchandise and the getShippingTotalTax() returns the tax applied to all shipments. Gross-based methods represent the amount of a category after tax has been calculated. For example, the getMerchandizeTotalGrossPrice() returns the price of all merchandise in the container, including tax on the merchandise, whereas getShippingTotalGrossPrice() returns the price of all shipments in the container, including tax on the shipments in the container. There are also a set of methods that provide access to 'adjusted' values. The adjusted-based methods return values where promotions have been applied. For example, the getAdjustedMerchandizeTotalNetPrice() method returns the net price of all merchandise after product-level and order-level promotions have been applied. Whereas the getAdjustedMerchandizeTotalGrossPrice() method returns the price of all merchandise after product-level and order-level promotions have been applied and includes the amount of merchandise-related tax. Finally, there are a set of methods that return the aggregate values representing the line items in the container. These are the total-based methods getTotalNetPrice(), getTotalTax() and getTotalGrossPrice(). These methods return the totals of all items in the container and include any order-level promotions. Note that all merchandise-related methods do not include 'gift certificates' values in the values they return. Gift certificates are not considered merchandise as they do not represent a product. ## Constants ### BUSINESS_TYPE_B2B **Type:** Number = 2 constant for Business Type B2B ### BUSINESS_TYPE_B2C **Type:** Number = 1 constant for Business Type B2C ### CHANNEL_TYPE_CALLCENTER **Type:** Number = 2 constant for Channel Type CallCenter ### CHANNEL_TYPE_CUSTOMERSERVICECENTER **Type:** Number = 11 constant for Channel Type Customer Service Center ### CHANNEL_TYPE_DSS **Type:** Number = 4 constant for Channel Type DSS ### CHANNEL_TYPE_FACEBOOKADS **Type:** Number = 8 constant for Channel Type Facebook Ads ### CHANNEL_TYPE_GOOGLE **Type:** Number = 13 constant for Channel Type Google ### CHANNEL_TYPE_INSTAGRAMCOMMERCE **Type:** Number = 12 constant for Channel Type Instagram Commerce ### CHANNEL_TYPE_MARKETPLACE **Type:** Number = 3 constant for Channel Type Marketplace ### CHANNEL_TYPE_ONLINERESERVATION **Type:** Number = 10 constant for Channel Type Online Reservation ### CHANNEL_TYPE_PINTEREST **Type:** Number = 6 constant for Channel Type Pinterest ### CHANNEL_TYPE_SNAPCHAT **Type:** Number = 15 constant for Channel Type Snapchat ### CHANNEL_TYPE_STORE **Type:** Number = 5 constant for Channel Type Store ### CHANNEL_TYPE_STOREFRONT **Type:** Number = 1 constant for Channel Type Storefront ### CHANNEL_TYPE_SUBSCRIPTIONS **Type:** Number = 9 constant for Channel Type Subscriptions ### CHANNEL_TYPE_TIKTOK **Type:** Number = 14 constant for Channel Type TikTok ### CHANNEL_TYPE_TWITTER **Type:** Number = 7 constant for Channel Type Twitter ### CHANNEL_TYPE_WHATSAPP **Type:** Number = 16 constant for Channel Type WhatsApp ### CHANNEL_TYPE_YOUTUBE **Type:** Number = 17 constant for Channel Type YouTube ## Properties ### adjustedMerchandizeTotalGrossPrice **Type:** Money (Read Only) The adjusted total gross price (including tax) in purchase currency. Adjusted merchandize prices represent the sum of product prices before services such as shipping, but after product-level and order-level adjustments. ### adjustedMerchandizeTotalNetPrice **Type:** Money (Read Only) The total net price (excluding tax) in purchase currency. Adjusted merchandize prices represent the sum of product prices before services such as shipping, but after product-level and order-level adjustments. ### adjustedMerchandizeTotalPrice **Type:** Money (Read Only) The adjusted merchandize total price including product-level and order-level adjustments. If the line item container is based on net pricing the adjusted merchandize total net price is returned. If the line item container is based on gross pricing the adjusted merchandize total gross price is returned. ### adjustedMerchandizeTotalTax **Type:** Money (Read Only) The subtotal tax in purchase currency. Adjusted merchandize prices represent the sum of product prices before services such as shipping have been added, but after adjustment from promotions have been added. ### adjustedShippingTotalGrossPrice **Type:** Money (Read Only) The adjusted sum of all shipping line items of the line item container, including tax after shipping adjustments have been applied. ### adjustedShippingTotalNetPrice **Type:** Money (Read Only) The sum of all shipping line items of the line item container, excluding tax after shipping adjustments have been applied. ### adjustedShippingTotalPrice **Type:** Money (Read Only) The adjusted shipping total price. If the line item container is based on net pricing the adjusted shipping total net price is returned. If the line item container is based on gross pricing the adjusted shipping total gross price is returned. ### adjustedShippingTotalTax **Type:** Money (Read Only) The tax of all shipping line items of the line item container after shipping adjustments have been applied. ### allGiftCertificateLineItems **Type:** Collection (Read Only) All gift certificate line items of the container. ### allLineItems **Type:** Collection (Read Only) All product, shipping, price adjustment, and gift certificate line items of the line item container. ### allProductLineItems **Type:** Collection (Read Only) All product line items of the container, no matter if they are dependent or independent. This includes option, bundled and bonus line items. ### allProductQuantities **Type:** HashMap (Read Only) A hash mapping all products in the line item container to their total quantities. The total product quantity is used chiefly to validate the availability of the items in the cart. This method is not appropriate to look up prices because it returns products such as bundled line items which are included in the price of their parent and therefore have no corresponding price. The method counts all direct product line items, plus dependent product line items that are not option line items. It also excludes product line items that are not associated to any catalog product. ### allShippingPriceAdjustments **Type:** Collection (Read Only) The collection of all shipping price adjustments applied somewhere in the container. This can be adjustments applied to individual shipments or to the container itself. Note that the promotions engine only applies shipping price adjustments to the the default shipping line item of shipments, and never to the container. ### billingAddress **Type:** OrderAddress (Read Only) The billing address defined for the container. Returns null if no billing address has been created yet. ### bonusDiscountLineItems **Type:** Collection (Read Only) An unsorted collection of the the bonus discount line items associated with this container. ### bonusLineItems **Type:** Collection (Read Only) The collection of product line items that are bonus items (where ProductLineItem.isBonusProductLineItem() is true). ### businessType **Type:** EnumValue (Read Only) The type of the business this order has been placed in. Possible values are BUSINESS_TYPE_B2C or BUSINESS_TYPE_B2B. ### channelType **Type:** EnumValue (Read Only) The channel type defines in which sales channel this order has been created. This can be used to distinguish order placed through Storefront, Call Center or Marketplace. Possible values are CHANNEL_TYPE_STOREFRONT, CHANNEL_TYPE_CALLCENTER, CHANNEL_TYPE_MARKETPLACE, CHANNEL_TYPE_DSS, CHANNEL_TYPE_STORE, CHANNEL_TYPE_PINTEREST, CHANNEL_TYPE_TWITTER, CHANNEL_TYPE_FACEBOOKADS, CHANNEL_TYPE_SUBSCRIPTIONS, CHANNEL_TYPE_ONLINERESERVATION, CHANNEL_TYPE_CUSTOMERSERVICECENTER, CHANNEL_TYPE_INSTAGRAMCOMMERCE, CHANNEL_TYPE_GOOGLE, CHANNEL_TYPE_YOUTUBE, CHANNEL_TYPE_TIKTOK, CHANNEL_TYPE_SNAPCHAT, CHANNEL_TYPE_WHATSAPP ### couponLineItems **Type:** Collection (Read Only) A sorted collection of the coupon line items in the container. The coupon line items are returned in the order they were added to container. ### currencyCode **Type:** String (Read Only) The currency code for this line item container. The currency code is a 3-character currency mnemonic such as 'USD' or 'EUR'. The currency code represents the currency in which the calculation is made, and in which the buyer sees all prices in the store front. ### customer **Type:** Customer (Read Only) The customer associated with this container. ### customerEmail **Type:** String The email of the customer associated with this container. ### customerName **Type:** String The name of the customer associated with this container. ### customerNo **Type:** String (Read Only) The customer number of the customer associated with this container. ### defaultShipment **Type:** Shipment (Read Only) The default shipment of the line item container. Every basket and order has a default shipment with the id "me". If you call a process that accesses a shipment, and you don't specify the shipment, then the process uses the default shipment. You can't remove a default shipment. Calling removeShipment(Shipment) on it throws an exception. ### etag **Type:** String (Read Only) The Etag of the line item container. The Etag is a hash that represents the overall container state including any associated objects like line items. ### externallyTaxed **Type:** boolean (Read Only) Use this method to check whether the LineItemCtnr is calculated based on external tax tables. Note: a basket can only be created in EXTERNAL tax mode using SCAPI. ### giftCertificateLineItems **Type:** Collection (Read Only) All gift certificate line items of the container. ### giftCertificatePaymentInstruments **Type:** Collection (Read Only) An unsorted collection of the PaymentInstrument instances that represent GiftCertificates in this container. ### giftCertificateTotalGrossPrice **Type:** Money (Read Only) The total gross price of all gift certificates in the cart. Should usually be equal to total net price. ### giftCertificateTotalNetPrice **Type:** Money (Read Only) The total net price (excluding tax) of all gift certificates in the cart. Should usually be equal to total gross price. ### giftCertificateTotalPrice **Type:** Money (Read Only) The gift certificate total price. If the line item container is based on net pricing the gift certificate total net price is returned. If the line item container is based on gross pricing the gift certificate total gross price is returned. ### giftCertificateTotalTax **Type:** Money (Read Only) The total tax of all gift certificates in the cart. Should usually be 0.0. ### merchandizeTotalGrossPrice **Type:** Money (Read Only) The total gross price (including tax) in purchase currency. Merchandize total prices represent the sum of product prices before services such as shipping or adjustment from promotions have been added. ### merchandizeTotalNetPrice **Type:** Money (Read Only) The total net price (excluding tax) in purchase currency. Merchandize total prices represent the sum of product prices before services such as shipping or adjustment from promotion have been added. ### merchandizeTotalPrice **Type:** Money (Read Only) The merchandize total price. If the line item container is based on net pricing the merchandize total net price is returned. If the line item container is based on gross pricing the merchandize total gross price is returned. ### merchandizeTotalTax **Type:** Money (Read Only) The total tax in purchase currency. Merchandize total prices represent the sum of product prices before services such as shipping or adjustment from promotions have been added. ### notes **Type:** List (Read Only) The list of notes for this object, ordered by creation time from oldest to newest. ### paymentInstrument **Type:** OrderPaymentInstrument (Read Only) The payment instrument of the line item container or null. This method is deprecated. You should use getPaymentInstruments() or getGiftCertificatePaymentInstruments() instead. ### paymentInstruments **Type:** Collection (Read Only) An unsorted collection of the payment instruments in this container. ### priceAdjustments **Type:** Collection (Read Only) The collection of price adjustments that have been applied to the totals such as promotion on the purchase value (i.e. $10 Off or 10% Off). The price adjustments are sorted by the order in which they were applied to the order by the promotions engine. ### productLineItems **Type:** Collection (Read Only) The product line items of the container that are not dependent on other product line items. This includes line items representing bonus products in the container but excludes option, bundled, and bonus line items. The returned collection is sorted by the position attribute of the product line items. ### productQuantities **Type:** HashMap (Read Only) A hash map of all products in the line item container and their total quantities. The total product quantity is for example used to lookup the product price. The method counts all direct product line items, plus dependent product line items that are not bundled line items and no option line items. It also excludes product line items that are not associated to any catalog product, and bonus product line items. ### productQuantityTotal **Type:** Number (Read Only) The total quantity of all product line items. Not included are bundled line items and option line items. ### shipments **Type:** Collection (Read Only) All shipments of the line item container. The first shipment in the returned collection is the default shipment (shipment ID always set to "me"). All other shipments are sorted ascending by shipment ID. ### shippingPriceAdjustments **Type:** Collection (Read Only) The of shipping price adjustments applied to the shipping total of the container. Note that the promotions engine only applies shipping price adjustments to the the default shipping line item of shipments, and never to the container. ### shippingTotalGrossPrice **Type:** Money (Read Only) The sum of all shipping line items of the line item container, including tax before shipping adjustments have been applied. ### shippingTotalNetPrice **Type:** Money (Read Only) The sum of all shipping line items of the line item container, excluding tax before shipping adjustments have been applied. ### shippingTotalPrice **Type:** Money (Read Only) The shipping total price. If the line item container is based on net pricing the shipping total net price is returned. If the line item container is based on gross pricing the shipping total gross price is returned. ### shippingTotalTax **Type:** Money (Read Only) The tax of all shipping line items of the line item container before shipping adjustments have been applied. ### taxRoundedAtGroup **Type:** boolean (Read Only) Use this method to check if the LineItemCtnr was calculated with grouped taxation calculation. If the tax is rounded on group level, the tax is applied to the summed-up tax basis for each tax rate. ### taxTotalsPerTaxRate **Type:** SortedMap (Read Only) This method returns a SortedMap in which the keys are Decimal tax rates and the values are Money total tax for the tax rate. The map is unmodifiable. ### totalGrossPrice **Type:** Money (Read Only) The grand total price gross of tax for LineItemCtnr, in purchase currency. Total prices represent the sum of product prices, services prices and adjustments. ### totalNetPrice **Type:** Money (Read Only) The grand total price for LineItemCtnr net of tax, in purchase currency. Total prices represent the sum of product prices, services prices and adjustments. ### totalTax **Type:** Money (Read Only) The grand total tax for LineItemCtnr, in purchase currency. Total prices represent the sum of product prices, services prices and adjustments. ## Constructor Summary ## Method Summary ### addNote **Signature:** `addNote(subject : String, text : String) : Note` Adds a note to the object. ### createBillingAddress **Signature:** `createBillingAddress() : OrderAddress` Create a billing address for the LineItemCtnr. ### createBonusProductLineItem **Signature:** `createBonusProductLineItem(bonusDiscountLineItem : BonusDiscountLineItem, product : Product, optionModel : ProductOptionModel, shipment : Shipment) : ProductLineItem` Creates a product line item in the container based on the passed Product and BonusDiscountLineItem. ### createCouponLineItem **Signature:** `createCouponLineItem(couponCode : String, campaignBased : boolean) : CouponLineItem` Creates a new CouponLineItem for this container based on the supplied coupon code. ### createCouponLineItem **Signature:** `createCouponLineItem(couponCode : String) : CouponLineItem` Creates a coupon line item that is not based on the B2C Commerce campaign system and associates it with the specified coupon code. ### createGiftCertificateLineItem **Signature:** `createGiftCertificateLineItem(amount : Number, recipientEmail : String) : GiftCertificateLineItem` Creates a gift certificate line item. ### createGiftCertificatePaymentInstrument **Signature:** `createGiftCertificatePaymentInstrument(giftCertificateCode : String, amount : Money) : OrderPaymentInstrument` Creates an OrderPaymentInstrument representing a Gift Certificate. ### createPaymentInstrument **Signature:** `createPaymentInstrument(paymentMethodId : String, amount : Money) : OrderPaymentInstrument` Creates a payment instrument using the specified payment method id and amount. ### createPaymentInstrumentFromWallet **Signature:** `createPaymentInstrumentFromWallet(walletPaymentInstrument : CustomerPaymentInstrument, amount : Money) : OrderPaymentInstrument` Creates a payment instrument using the specified wallet payment instrument and amount. ### createPriceAdjustment **Signature:** `createPriceAdjustment(promotionID : String) : PriceAdjustment` Creates an order price adjustment. The promotion id is mandatory and must not be the ID of any actual promotion defined in B2C Commerce; otherwise an exception is thrown. ### createPriceAdjustment **Signature:** `createPriceAdjustment(promotionID : String, discount : Discount) : PriceAdjustment` Creates an order level price adjustment for a specific discount. The promotion id is mandatory and must not be the ID of any actual promotion defined in B2C Commerce; otherwise an exception is thrown. ### createProductLineItem **Signature:** `createProductLineItem(productID : String, quantity : Quantity, shipment : Shipment) : ProductLineItem` Creates a new product line item in the container and assigns it to the specified shipment. ### createProductLineItem **Signature:** `createProductLineItem(productID : String, shipment : Shipment) : ProductLineItem` Creates a new product line item in the container and assigns it to the specified shipment. ### createProductLineItem **Signature:** `createProductLineItem(productListItem : ProductListItem, shipment : Shipment) : ProductLineItem` Creates a new product line item in the basket and assigns it to the specified shipment. ### createProductLineItem **Signature:** `createProductLineItem(product : Product, optionModel : ProductOptionModel, shipment : Shipment) : ProductLineItem` Creates a new product line item in the container and assigns it to the specified shipment. ### createShipment **Signature:** `createShipment(id : String) : Shipment` Creates a standard shipment for the line item container. ### createShippingPriceAdjustment **Signature:** `createShippingPriceAdjustment(promotionID : String) : PriceAdjustment` Creates a shipping price adjustment to be applied to the container. ### getAdjustedMerchandizeTotalGrossPrice **Signature:** `getAdjustedMerchandizeTotalGrossPrice() : Money` Returns the adjusted total gross price (including tax) in purchase currency. ### getAdjustedMerchandizeTotalNetPrice **Signature:** `getAdjustedMerchandizeTotalNetPrice() : Money` Returns the total net price (excluding tax) in purchase currency. ### getAdjustedMerchandizeTotalPrice **Signature:** `getAdjustedMerchandizeTotalPrice() : Money` Returns the adjusted merchandize total price including product-level and order-level adjustments. ### getAdjustedMerchandizeTotalPrice **Signature:** `getAdjustedMerchandizeTotalPrice(applyOrderLevelAdjustments : boolean) : Money` Returns the adjusted merchandize total price including order-level adjustments if requested. ### getAdjustedMerchandizeTotalTax **Signature:** `getAdjustedMerchandizeTotalTax() : Money` Returns the subtotal tax in purchase currency. ### getAdjustedShippingTotalGrossPrice **Signature:** `getAdjustedShippingTotalGrossPrice() : Money` Returns the adjusted sum of all shipping line items of the line item container, including tax after shipping adjustments have been applied. ### getAdjustedShippingTotalNetPrice **Signature:** `getAdjustedShippingTotalNetPrice() : Money` Returns the sum of all shipping line items of the line item container, excluding tax after shipping adjustments have been applied. ### getAdjustedShippingTotalPrice **Signature:** `getAdjustedShippingTotalPrice() : Money` Returns the adjusted shipping total price. ### getAdjustedShippingTotalTax **Signature:** `getAdjustedShippingTotalTax() : Money` Returns the tax of all shipping line items of the line item container after shipping adjustments have been applied. ### getAllGiftCertificateLineItems **Signature:** `getAllGiftCertificateLineItems() : Collection` Returns all gift certificate line items of the container. ### getAllLineItems **Signature:** `getAllLineItems() : Collection` Returns all product, shipping, price adjustment, and gift certificate line items of the line item container. ### getAllProductLineItems **Signature:** `getAllProductLineItems() : Collection` Returns all product line items of the container, no matter if they are dependent or independent. ### getAllProductLineItems **Signature:** `getAllProductLineItems(productID : String) : Collection` Returns all product line items of the container that have a product ID equal to the specified product ID, no matter if they are dependent or independent. ### getAllProductQuantities **Signature:** `getAllProductQuantities() : HashMap` Returns a hash mapping all products in the line item container to their total quantities. ### getAllShippingPriceAdjustments **Signature:** `getAllShippingPriceAdjustments() : Collection` Returns the collection of all shipping price adjustments applied somewhere in the container. ### getBillingAddress **Signature:** `getBillingAddress() : OrderAddress` Returns the billing address defined for the container. ### getBonusDiscountLineItems **Signature:** `getBonusDiscountLineItems() : Collection` Returns an unsorted collection of the the bonus discount line items associated with this container. ### getBonusLineItems **Signature:** `getBonusLineItems() : Collection` Returns the collection of product line items that are bonus items (where ProductLineItem.isBonusProductLineItem() is true). ### getBusinessType **Signature:** `getBusinessType() : EnumValue` Returns the type of the business this order has been placed in. Possible values are BUSINESS_TYPE_B2C or BUSINESS_TYPE_B2B. ### getChannelType **Signature:** `getChannelType() : EnumValue` The channel type defines in which sales channel this order has been created. ### getCouponLineItem **Signature:** `getCouponLineItem(couponCode : String) : CouponLineItem` Returns the coupon line item representing the specified coupon code. ### getCouponLineItems **Signature:** `getCouponLineItems() : Collection` Returns a sorted collection of the coupon line items in the container. ### getCurrencyCode **Signature:** `getCurrencyCode() : String` Returns the currency code for this line item container. ### getCustomer **Signature:** `getCustomer() : Customer` Returns the customer associated with this container. ### getCustomerEmail **Signature:** `getCustomerEmail() : String` Returns the email of the customer associated with this container. ### getCustomerName **Signature:** `getCustomerName() : String` Returns the name of the customer associated with this container. ### getCustomerNo **Signature:** `getCustomerNo() : String` Returns the customer number of the customer associated with this container. ### getDefaultShipment **Signature:** `getDefaultShipment() : Shipment` Returns the default shipment of the line item container. ### getEtag **Signature:** `getEtag() : String` Returns the Etag of the line item container. ### getGiftCertificateLineItems **Signature:** `getGiftCertificateLineItems() : Collection` Returns all gift certificate line items of the container. ### getGiftCertificateLineItems **Signature:** `getGiftCertificateLineItems(giftCertificateId : String) : Collection` Returns all gift certificate line items of the container, no matter if they are dependent or independent. ### getGiftCertificatePaymentInstruments **Signature:** `getGiftCertificatePaymentInstruments() : Collection` Returns an unsorted collection of the PaymentInstrument instances that represent GiftCertificates in this container. ### getGiftCertificatePaymentInstruments **Signature:** `getGiftCertificatePaymentInstruments(giftCertificateCode : String) : Collection` Returns an unsorted collection containing all PaymentInstruments of type PaymentInstrument.METHOD_GIFT_CERTIFICATE where the specified code is the same code on the payment instrument. ### getGiftCertificateTotalGrossPrice **Signature:** `getGiftCertificateTotalGrossPrice() : Money` Returns the total gross price of all gift certificates in the cart. ### getGiftCertificateTotalNetPrice **Signature:** `getGiftCertificateTotalNetPrice() : Money` Returns the total net price (excluding tax) of all gift certificates in the cart. ### getGiftCertificateTotalPrice **Signature:** `getGiftCertificateTotalPrice() : Money` Returns the gift certificate total price. ### getGiftCertificateTotalTax **Signature:** `getGiftCertificateTotalTax() : Money` Returns the total tax of all gift certificates in the cart. ### getMerchandizeTotalGrossPrice **Signature:** `getMerchandizeTotalGrossPrice() : Money` Returns the total gross price (including tax) in purchase currency. ### getMerchandizeTotalNetPrice **Signature:** `getMerchandizeTotalNetPrice() : Money` Returns the total net price (excluding tax) in purchase currency. ### getMerchandizeTotalPrice **Signature:** `getMerchandizeTotalPrice() : Money` Returns the merchandize total price. ### getMerchandizeTotalTax **Signature:** `getMerchandizeTotalTax() : Money` Returns the total tax in purchase currency. ### getNotes **Signature:** `getNotes() : List` Returns the list of notes for this object, ordered by creation time from oldest to newest. ### getPaymentInstrument **Signature:** `getPaymentInstrument() : OrderPaymentInstrument` Returns the payment instrument of the line item container or null. ### getPaymentInstruments **Signature:** `getPaymentInstruments() : Collection` Returns an unsorted collection of the payment instruments in this container. ### getPaymentInstruments **Signature:** `getPaymentInstruments(paymentMethodID : String) : Collection` Returns an unsorted collection of PaymentInstrument instances based on the specified payment method ID. ### getPriceAdjustmentByPromotionID **Signature:** `getPriceAdjustmentByPromotionID(promotionID : String) : PriceAdjustment` Returns the price adjustment associated to the specified promotion ID. ### getPriceAdjustments **Signature:** `getPriceAdjustments() : Collection` Returns the collection of price adjustments that have been applied to the totals such as promotion on the purchase value (i.e. ### getProductLineItems **Signature:** `getProductLineItems() : Collection` Returns the product line items of the container that are not dependent on other product line items. ### getProductLineItems **Signature:** `getProductLineItems(productID : String) : Collection` Returns the product line items of the container that have a product ID equal to the specified product ID and that are not dependent on other product line items. ### getProductQuantities **Signature:** `getProductQuantities() : HashMap` Returns a hash map of all products in the line item container and their total quantities. ### getProductQuantities **Signature:** `getProductQuantities(includeBonusProducts : boolean) : HashMap` Returns a hash map of all products in the line item container and their total quantities. ### getProductQuantityTotal **Signature:** `getProductQuantityTotal() : Number` Returns the total quantity of all product line items. ### getShipment **Signature:** `getShipment(id : String) : Shipment` Returns the shipment for the specified ID or null if no shipment with this ID exists in the line item container. ### getShipments **Signature:** `getShipments() : Collection` Returns all shipments of the line item container. The first shipment in the returned collection is the default shipment (shipment ID always set to "me"). ### getShippingPriceAdjustmentByPromotionID **Signature:** `getShippingPriceAdjustmentByPromotionID(promotionID : String) : PriceAdjustment` Returns the shipping price adjustment associated with the specified promotion ID. ### getShippingPriceAdjustments **Signature:** `getShippingPriceAdjustments() : Collection` Returns the of shipping price adjustments applied to the shipping total of the container. ### getShippingTotalGrossPrice **Signature:** `getShippingTotalGrossPrice() : Money` Returns the sum of all shipping line items of the line item container, including tax before shipping adjustments have been applied. ### getShippingTotalNetPrice **Signature:** `getShippingTotalNetPrice() : Money` Returns the sum of all shipping line items of the line item container, excluding tax before shipping adjustments have been applied. ### getShippingTotalPrice **Signature:** `getShippingTotalPrice() : Money` Returns the shipping total price. ### getShippingTotalTax **Signature:** `getShippingTotalTax() : Money` Returns the tax of all shipping line items of the line item container before shipping adjustments have been applied. ### getTaxTotalsPerTaxRate **Signature:** `getTaxTotalsPerTaxRate() : SortedMap` This method returns a SortedMap in which the keys are Decimal tax rates and the values are Money total tax for the tax rate. ### getTotalGrossPrice **Signature:** `getTotalGrossPrice() : Money` Returns the grand total price gross of tax for LineItemCtnr, in purchase currency. ### getTotalNetPrice **Signature:** `getTotalNetPrice() : Money` Returns the grand total price for LineItemCtnr net of tax, in purchase currency. ### getTotalTax **Signature:** `getTotalTax() : Money` Returns the grand total tax for LineItemCtnr, in purchase currency. ### isExternallyTaxed **Signature:** `isExternallyTaxed() : boolean` Use this method to check whether the LineItemCtnr is calculated based on external tax tables. ### isTaxRoundedAtGroup **Signature:** `isTaxRoundedAtGroup() : boolean` Use this method to check if the LineItemCtnr was calculated with grouped taxation calculation. ### removeAllPaymentInstruments **Signature:** `removeAllPaymentInstruments() : void` Removes the all Payment Instruments from this container and deletes the Payment Instruments. ### removeBonusDiscountLineItem **Signature:** `removeBonusDiscountLineItem(bonusDiscountLineItem : BonusDiscountLineItem) : void` Removes the specified bonus discount line item from the line item container. ### removeCouponLineItem **Signature:** `removeCouponLineItem(couponLineItem : CouponLineItem) : void` Removes the specified coupon line item from the line item container. ### removeGiftCertificateLineItem **Signature:** `removeGiftCertificateLineItem(giftCertificateLineItem : GiftCertificateLineItem) : void` Removes the specified gift certificate line item from the line item container. ### removeNote **Signature:** `removeNote(note : Note) : void` Removes a note from this line item container and deletes it. ### removePaymentInstrument **Signature:** `removePaymentInstrument(pi : PaymentInstrument) : void` Removes the specified Payment Instrument from this container and deletes the Payment Instrument. ### removePriceAdjustment **Signature:** `removePriceAdjustment(priceAdjustment : PriceAdjustment) : void` Removes the specified price adjustment line item from the line item container. ### removeProductLineItem **Signature:** `removeProductLineItem(productLineItem : ProductLineItem) : void` Removes the specified product line item from the line item container. ### removeShipment **Signature:** `removeShipment(shipment : Shipment) : void` Removes the specified shipment and all associated product, gift certificate, shipping and price adjustment line items from the line item container. ### removeShippingPriceAdjustment **Signature:** `removeShippingPriceAdjustment(priceAdjustment : PriceAdjustment) : void` Removes the specified shipping price adjustment line item from the line item container. ### setCustomerEmail **Signature:** `setCustomerEmail(aValue : String) : void` Sets the email address of the customer associated with this container. ### setCustomerName **Signature:** `setCustomerName(aValue : String) : void` Sets the name of the customer associated with this container. ### updateOrderLevelPriceAdjustmentTax **Signature:** `updateOrderLevelPriceAdjustmentTax() : void` Calculates the tax for all shipping and order-level merchandise price adjustments in this LineItemCtnr. ### updateTotals **Signature:** `updateTotals() : void` Recalculates the totals of the line item container. ### verifyPriceAdjustmentLimits **Signature:** `verifyPriceAdjustmentLimits() : Status` Verifies whether the manual price adjustments made for the line item container exceed the corresponding limits for the current user and the current site. ## Method Detail ## Method Details ### addNote **Signature:** `addNote(subject : String, text : String) : Note` **Description:** Adds a note to the object. **Parameters:** - `subject`: The subject of the note. - `text`: The text of the note. Must be no more than 4000 characters or an exception is thrown. **Returns:** the added note. --- ### createBillingAddress **Signature:** `createBillingAddress() : OrderAddress` **Description:** Create a billing address for the LineItemCtnr. A LineItemCtnr (e.g. basket) initially has no billing address. This method creates a billing address for the LineItemCtnr and replaces an existing billing address. **Returns:** The new billing address of the LineItemCtnr. --- ### createBonusProductLineItem **Signature:** `createBonusProductLineItem(bonusDiscountLineItem : BonusDiscountLineItem, product : Product, optionModel : ProductOptionModel, shipment : Shipment) : ProductLineItem` **Description:** Creates a product line item in the container based on the passed Product and BonusDiscountLineItem. The product must be assigned to the current site catalog and must also be a bonus product of the specified BonusDiscountLineItem or an exception is thrown. The line item is always created in the default shipment. If successful, the operation always creates a new ProductLineItem and never simply increments the quantity of an existing ProductLineItem. An option model can optionally be specified. **Parameters:** - `bonusDiscountLineItem`: Line item representing an applied BonusChoiceDiscount in the LineItemCtnr, must not be null. - `product`: Product The product to add to the LineItemCtnr. Must not be null and must be a bonus product of bonusDiscountLineItem. - `optionModel`: ProductOptionModel or null. - `shipment`: The shipment to add the bonus product to. If null, the product is added to the default shipment. --- ### createCouponLineItem **Signature:** `createCouponLineItem(couponCode : String, campaignBased : boolean) : CouponLineItem` **Description:** Creates a new CouponLineItem for this container based on the supplied coupon code. The created coupon line item is based on the B2C Commerce campaign system if campaignBased parameter is true. In that case, if the supplied coupon code is not valid, APIException with type 'CreateCouponLineItemException' is thrown. If you want to create a custom coupon line item, you must call this method with campaignBased = false or to use createCouponLineItem(String). Example: try { var cli : CouponLineItem = basket.createCouponLineItem(couponCode, true); } catch (e if e instanceof APIException && e.type === 'CreateCouponLineItemException') if (e.errorCode == CouponStatusCodes.COUPON_CODE_ALREADY_IN_BASKET) { ... } } An dw.order.CreateCouponLineItemException is thrown in case of campaignBased = true only. Indicates that the provided coupon code is not a valid coupon code to create a coupon line item based on the B2C Commerce campaign system. The error code property (CreateCouponLineItemException.errorCode) will be set to one of the following values: CouponStatusCodes.COUPON_CODE_ALREADY_IN_BASKET = Indicates that coupon code has already been added to basket. CouponStatusCodes.COUPON_ALREADY_IN_BASKET = Indicates that another code of the same MultiCode/System coupon has already been added to basket. CouponStatusCodes.COUPON_CODE_ALREADY_REDEEMED = Indicates that code of MultiCode/System coupon has already been redeemed. CouponStatusCodes.COUPON_CODE_UNKNOWN = Indicates that coupon not found for given coupon code or that the code itself was not found. CouponStatusCodes.COUPON_DISABLED = Indicates that coupon is not enabled. CouponStatusCodes.REDEMPTION_LIMIT_EXCEEDED = Indicates that number of redemptions per code exceeded. CouponStatusCodes.CUSTOMER_REDEMPTION_LIMIT_EXCEEDED = Indicates that number of redemptions per code and customer exceeded. CouponStatusCodes.TIMEFRAME_REDEMPTION_LIMIT_EXCEEDED = Indicates that number of redemptions per code, customer and time exceeded. CouponStatusCodes.NO_ACTIVE_PROMOTION = Indicates that coupon is not assigned to an active promotion. **Parameters:** - `couponCode`: the coupon code to be represented by the coupon line item - `campaignBased`: the flag if the created coupon line item should be based on the B2C Commerce campaign system **Returns:** the created coupon line item --- ### createCouponLineItem **Signature:** `createCouponLineItem(couponCode : String) : CouponLineItem` **Description:** Creates a coupon line item that is not based on the B2C Commerce campaign system and associates it with the specified coupon code. There may not be any other coupon line item in the container with the specific coupon code, otherwise an exception is thrown. If you want to create a coupon line item based on the B2C Commerce campaign system, you must use createCouponLineItem(String, Boolean) with campaignBased = true. **Parameters:** - `couponCode`: couponCode represented by the coupon line item. **Returns:** New coupon line item. --- ### createGiftCertificateLineItem **Signature:** `createGiftCertificateLineItem(amount : Number, recipientEmail : String) : GiftCertificateLineItem` **Description:** Creates a gift certificate line item. **Parameters:** - `amount`: the amount of the gift certificate - mandatory - `recipientEmail`: the recipient's email address - mandatory **Returns:** The new gift certificate line item --- ### createGiftCertificatePaymentInstrument **Signature:** `createGiftCertificatePaymentInstrument(giftCertificateCode : String, amount : Money) : OrderPaymentInstrument` **Description:** Creates an OrderPaymentInstrument representing a Gift Certificate. The amount is set on a PaymentTransaction that is accessible via the OrderPaymentInstrument. By default, the status of the PaymentTransaction is set to CREATE. The PaymentTransaction must be processed at a later time. **Parameters:** - `giftCertificateCode`: the redemption code of the Gift Certificate. - `amount`: the amount to set on the PaymentTransaction. If the OrderPaymentInstrument is actually redeemed, this is the amount that will be deducted from the Gift Certificate. **Returns:** the OrderPaymentInstrument. --- ### createPaymentInstrument **Signature:** `createPaymentInstrument(paymentMethodId : String, amount : Money) : OrderPaymentInstrument` **Description:** Creates a payment instrument using the specified payment method id and amount. The amount is set on the PaymentTransaction that is attached to the payment instrument. **Parameters:** - `paymentMethodId`: The payment method id. See the PaymentInstrument class for payment method types - `amount`: The payment amount or null **Returns:** The new payment instrument --- ### createPaymentInstrumentFromWallet **Signature:** `createPaymentInstrumentFromWallet(walletPaymentInstrument : CustomerPaymentInstrument, amount : Money) : OrderPaymentInstrument` **Description:** Creates a payment instrument using the specified wallet payment instrument and amount. The amount is set on the PaymentTransaction that is attached to the payment instrument. All data from the wallet payment instrument will be copied over to the created payment instrument. **Parameters:** - `walletPaymentInstrument`: The payment instrument from the customer's walled. - `amount`: The payment amount or null **Returns:** The new payment instrument --- ### createPriceAdjustment **Signature:** `createPriceAdjustment(promotionID : String) : PriceAdjustment` **Description:** Creates an order price adjustment. The promotion id is mandatory and must not be the ID of any actual promotion defined in B2C Commerce; otherwise an exception is thrown. **Parameters:** - `promotionID`: Promotion ID **Returns:** The new price adjustment --- ### createPriceAdjustment **Signature:** `createPriceAdjustment(promotionID : String, discount : Discount) : PriceAdjustment` **Description:** Creates an order level price adjustment for a specific discount. The promotion id is mandatory and must not be the ID of any actual promotion defined in B2C Commerce; otherwise an exception is thrown. The possible discount types are supported: PercentageDiscount and AmountDiscount. Examples: var myOrder : dw.order.Order; // assume known var paTenPercent : dw.order.PriceAdjustment = myOrder.createPriceAdjustment("myPromotionID1", new dw.campaign.PercentageDiscount(10)); var paReduceBy20 : dw.order.PriceAdjustment = myOrder.createPriceAdjustment("myPromotionID2", new dw.campaign.AmountDiscount(20); **Parameters:** - `promotionID`: Promotion ID - `discount`: The discount **Returns:** The new price adjustment --- ### createProductLineItem **Signature:** `createProductLineItem(productID : String, quantity : Quantity, shipment : Shipment) : ProductLineItem` **Description:** Creates a new product line item in the container and assigns it to the specified shipment. If the specified productID represents a product in the site catalog, the method will associate the product line item with that catalog product and will copy all order-relevant information, like the quantity unit, from the catalog product. If the specified productID does not represent a product of the site catalog, the method creates a new product line item and initializes it with the specified product ID and quantity. If the passed in quantity value is not a positive integer, it will be rounded to the nearest positive integer. The minimum order quantity and step quantity will be set to 1.0. For catalog products, the method follows the configured 'Add2Basket' strategy to either increment the quantity of an existing product line item or create a new product line item for the same product. For non-catalog products, the method creates a new product line item no matter if the same product is already in the line item container. If a negative quantity is specified, it is automatically changed to 1.0. **Deprecated:** Use createProductLineItem(String, Shipment) or ProductLineItem.updateQuantity(Number) instead. **Parameters:** - `productID`: The product ID. - `quantity`: The quantity of the product. - `shipment`: Shipment **Returns:** the product line item --- ### createProductLineItem **Signature:** `createProductLineItem(productID : String, shipment : Shipment) : ProductLineItem` **Description:** Creates a new product line item in the container and assigns it to the specified shipment. If the specified productID represents a product in the site catalog, the method will associate the product line item with that catalog product and will copy all order-relevant information, like the quantity unit, from the catalog product. The quantity of the product line item is initialized with 1.0 or - if defined - the minimum order quantity of the product. If the product represents a product in the site catalog and is an option product, the product is added with it's default option values. If the specified productID does not represent a product of the site catalog, the method creates a new product line item and initializes it with the specified product ID and with a quantity, minimum order quantity, and step quantity value of 1.0. If the provided SKU references a product that is not available as described in method ProductLineItem.isCatalogProduct(), the new product line item is considered a non-catalog product line item without a connection to a product. Such product line items are not included in reservation requests in either OCI-based inventory or eCom-based inventory when calling Basket.reserveInventory() or OrderMgr.createOrder(Basket). **Parameters:** - `productID`: The product ID. - `shipment`: Shipment **Returns:** The new product line item --- ### createProductLineItem **Signature:** `createProductLineItem(productListItem : ProductListItem, shipment : Shipment) : ProductLineItem` **Description:** Creates a new product line item in the basket and assigns it to the specified shipment. If the product list item references a product in the site catalog, the method will associate the product line item with that catalog product and will copy all order-relevant information, like the quantity unit, from the catalog product. The quantity of the product line item is initialized with 1.0 or - if defined - the minimum order quantity of the product. If the product list item references an option product, the option values are copied from the product list item. If the product list item is associated with an existing product line item, and the BasketAddProductBehaviour setting is MergeQuantities, then the product line item quantity is increased by 1.0 or, if defined, the minimum order quantity of the product. An exception is thrown if the line item container is no basket. the type of the product list item is not PRODUCT. the product list item references a product which is not assigned to the site catalog. **Parameters:** - `productListItem`: the product list item - `shipment`: the shipment the created product line item will be assigned to **Returns:** The new product line item --- ### createProductLineItem **Signature:** `createProductLineItem(product : Product, optionModel : ProductOptionModel, shipment : Shipment) : ProductLineItem` **Description:** Creates a new product line item in the container and assigns it to the specified shipment. An option model can be specified. Please note that the product must be assigned to the current site catalog. **Parameters:** - `product`: Product - `optionModel`: ProductOptionModel or null - `shipment`: Shipment --- ### createShipment **Signature:** `createShipment(id : String) : Shipment` **Description:** Creates a standard shipment for the line item container. The specified ID must not yet be in use for another shipment of this line item container. **Parameters:** - `id`: ID of the shipment. --- ### createShippingPriceAdjustment **Signature:** `createShippingPriceAdjustment(promotionID : String) : PriceAdjustment` **Description:** Creates a shipping price adjustment to be applied to the container. The promotion ID is mandatory and must not be the ID of any actual promotion defined in B2C Commerce; otherwise the method will throw an exception. If there already exists a shipping price adjustment referring to the specified promotion ID, an exception is thrown. **Parameters:** - `promotionID`: Promotion ID **Returns:** The new price adjustment --- ### getAdjustedMerchandizeTotalGrossPrice **Signature:** `getAdjustedMerchandizeTotalGrossPrice() : Money` **Description:** Returns the adjusted total gross price (including tax) in purchase currency. Adjusted merchandize prices represent the sum of product prices before services such as shipping, but after product-level and order-level adjustments. **Returns:** the adjusted total gross price (including tax) in purchase currency. --- ### getAdjustedMerchandizeTotalNetPrice **Signature:** `getAdjustedMerchandizeTotalNetPrice() : Money` **Description:** Returns the total net price (excluding tax) in purchase currency. Adjusted merchandize prices represent the sum of product prices before services such as shipping, but after product-level and order-level adjustments. **Returns:** the total net price (excluding tax) in purchase currency. --- ### getAdjustedMerchandizeTotalPrice **Signature:** `getAdjustedMerchandizeTotalPrice() : Money` **Description:** Returns the adjusted merchandize total price including product-level and order-level adjustments. If the line item container is based on net pricing the adjusted merchandize total net price is returned. If the line item container is based on gross pricing the adjusted merchandize total gross price is returned. **Returns:** either the adjusted merchandize total net or gross price --- ### getAdjustedMerchandizeTotalPrice **Signature:** `getAdjustedMerchandizeTotalPrice(applyOrderLevelAdjustments : boolean) : Money` **Description:** Returns the adjusted merchandize total price including order-level adjustments if requested. If the line item container is based on net pricing the adjusted merchandize total net price is returned. If the line item container is based on gross pricing the adjusted merchandize total gross price is returned. **Parameters:** - `applyOrderLevelAdjustments`: controls if order-level price adjustements are applied. If true, the price that is returned includes order-level price adjustments. If false, only product-level price adjustments are applied. **Returns:** a price representing the adjusted merchandize total controlled by the applyOrderLevelAdjustments parameter. --- ### getAdjustedMerchandizeTotalTax **Signature:** `getAdjustedMerchandizeTotalTax() : Money` **Description:** Returns the subtotal tax in purchase currency. Adjusted merchandize prices represent the sum of product prices before services such as shipping have been added, but after adjustment from promotions have been added. **Returns:** the subtotal tax in purchase currency. --- ### getAdjustedShippingTotalGrossPrice **Signature:** `getAdjustedShippingTotalGrossPrice() : Money` **Description:** Returns the adjusted sum of all shipping line items of the line item container, including tax after shipping adjustments have been applied. **Returns:** the adjusted sum of all shipping line items of the line item container, including tax after shipping adjustments have been applied. --- ### getAdjustedShippingTotalNetPrice **Signature:** `getAdjustedShippingTotalNetPrice() : Money` **Description:** Returns the sum of all shipping line items of the line item container, excluding tax after shipping adjustments have been applied. **Returns:** the sum of all shipping line items of the line item container, excluding tax after shipping adjustments have been applied. --- ### getAdjustedShippingTotalPrice **Signature:** `getAdjustedShippingTotalPrice() : Money` **Description:** Returns the adjusted shipping total price. If the line item container is based on net pricing the adjusted shipping total net price is returned. If the line item container is based on gross pricing the adjusted shipping total gross price is returned. **Returns:** either the adjusted shipping total net or gross price --- ### getAdjustedShippingTotalTax **Signature:** `getAdjustedShippingTotalTax() : Money` **Description:** Returns the tax of all shipping line items of the line item container after shipping adjustments have been applied. **Returns:** the tax of all shipping line items of the line item container after shipping adjustments have been applied. --- ### getAllGiftCertificateLineItems **Signature:** `getAllGiftCertificateLineItems() : Collection` **Description:** Returns all gift certificate line items of the container. **Deprecated:** Use getGiftCertificateLineItems() to get the collection instead. **Returns:** A collection of all GiftCertificateLineItems of the container. --- ### getAllLineItems **Signature:** `getAllLineItems() : Collection` **Description:** Returns all product, shipping, price adjustment, and gift certificate line items of the line item container. **Returns:** A collection of all product, shipping, price adjustment, and gift certificate line items of the container, in that order. --- ### getAllProductLineItems **Signature:** `getAllProductLineItems() : Collection` **Description:** Returns all product line items of the container, no matter if they are dependent or independent. This includes option, bundled and bonus line items. **Returns:** An unsorted collection of all ProductLineItem instances of the container. --- ### getAllProductLineItems **Signature:** `getAllProductLineItems(productID : String) : Collection` **Description:** Returns all product line items of the container that have a product ID equal to the specified product ID, no matter if they are dependent or independent. This includes option, bundled and bonus line items. **Parameters:** - `productID`: The product ID used to filter the product line items. **Returns:** An unsorted collection of all ProductLineItem instances which have the specified product ID. --- ### getAllProductQuantities **Signature:** `getAllProductQuantities() : HashMap` **Description:** Returns a hash mapping all products in the line item container to their total quantities. The total product quantity is used chiefly to validate the availability of the items in the cart. This method is not appropriate to look up prices because it returns products such as bundled line items which are included in the price of their parent and therefore have no corresponding price. The method counts all direct product line items, plus dependent product line items that are not option line items. It also excludes product line items that are not associated to any catalog product. **Returns:** A map of products and their total quantities. --- ### getAllShippingPriceAdjustments **Signature:** `getAllShippingPriceAdjustments() : Collection` **Description:** Returns the collection of all shipping price adjustments applied somewhere in the container. This can be adjustments applied to individual shipments or to the container itself. Note that the promotions engine only applies shipping price adjustments to the the default shipping line item of shipments, and never to the container. **Returns:** an unsorted collection of the shipping PriceAdjustment instances associated with this container. **See Also:** getShippingPriceAdjustments() --- ### getBillingAddress **Signature:** `getBillingAddress() : OrderAddress` **Description:** Returns the billing address defined for the container. Returns null if no billing address has been created yet. **Returns:** the billing address or null. --- ### getBonusDiscountLineItems **Signature:** `getBonusDiscountLineItems() : Collection` **Description:** Returns an unsorted collection of the the bonus discount line items associated with this container. **Returns:** An unsorted collection of BonusDiscountLine instances in the container. --- ### getBonusLineItems **Signature:** `getBonusLineItems() : Collection` **Description:** Returns the collection of product line items that are bonus items (where ProductLineItem.isBonusProductLineItem() is true). **Returns:** the collection of product line items that are bonus items. --- ### getBusinessType **Signature:** `getBusinessType() : EnumValue` **Description:** Returns the type of the business this order has been placed in. Possible values are BUSINESS_TYPE_B2C or BUSINESS_TYPE_B2B. **Returns:** the type of the business this order has been placed in. or null, if the business type is not set --- ### getChannelType **Signature:** `getChannelType() : EnumValue` **Description:** The channel type defines in which sales channel this order has been created. This can be used to distinguish order placed through Storefront, Call Center or Marketplace. Possible values are CHANNEL_TYPE_STOREFRONT, CHANNEL_TYPE_CALLCENTER, CHANNEL_TYPE_MARKETPLACE, CHANNEL_TYPE_DSS, CHANNEL_TYPE_STORE, CHANNEL_TYPE_PINTEREST, CHANNEL_TYPE_TWITTER, CHANNEL_TYPE_FACEBOOKADS, CHANNEL_TYPE_SUBSCRIPTIONS, CHANNEL_TYPE_ONLINERESERVATION, CHANNEL_TYPE_CUSTOMERSERVICECENTER, CHANNEL_TYPE_INSTAGRAMCOMMERCE, CHANNEL_TYPE_GOOGLE, CHANNEL_TYPE_YOUTUBE, CHANNEL_TYPE_TIKTOK, CHANNEL_TYPE_SNAPCHAT, CHANNEL_TYPE_WHATSAPP **Returns:** the sales channel this order has been placed in or null, if the order channel is not set --- ### getCouponLineItem **Signature:** `getCouponLineItem(couponCode : String) : CouponLineItem` **Description:** Returns the coupon line item representing the specified coupon code. **Parameters:** - `couponCode`: the coupon code. **Returns:** coupon line item or null. --- ### getCouponLineItems **Signature:** `getCouponLineItems() : Collection` **Description:** Returns a sorted collection of the coupon line items in the container. The coupon line items are returned in the order they were added to container. **Returns:** A sorted list of the CouponLineItem instances in the container. --- ### getCurrencyCode **Signature:** `getCurrencyCode() : String` **Description:** Returns the currency code for this line item container. The currency code is a 3-character currency mnemonic such as 'USD' or 'EUR'. The currency code represents the currency in which the calculation is made, and in which the buyer sees all prices in the store front. **Returns:** the currency code for this line item container. --- ### getCustomer **Signature:** `getCustomer() : Customer` **Description:** Returns the customer associated with this container. **Returns:** the customer associated with this container. --- ### getCustomerEmail **Signature:** `getCustomerEmail() : String` **Description:** Returns the email of the customer associated with this container. **Returns:** the email of the customer associated with this container. --- ### getCustomerName **Signature:** `getCustomerName() : String` **Description:** Returns the name of the customer associated with this container. **Returns:** the name of the customer associated with this container. --- ### getCustomerNo **Signature:** `getCustomerNo() : String` **Description:** Returns the customer number of the customer associated with this container. **Returns:** the customer number of the customer associated with this container. --- ### getDefaultShipment **Signature:** `getDefaultShipment() : Shipment` **Description:** Returns the default shipment of the line item container. Every basket and order has a default shipment with the id "me". If you call a process that accesses a shipment, and you don't specify the shipment, then the process uses the default shipment. You can't remove a default shipment. Calling removeShipment(Shipment) on it throws an exception. **Returns:** the default shipment of the container --- ### getEtag **Signature:** `getEtag() : String` **Description:** Returns the Etag of the line item container. The Etag is a hash that represents the overall container state including any associated objects like line items. **Returns:** the Etag value --- ### getGiftCertificateLineItems **Signature:** `getGiftCertificateLineItems() : Collection` **Description:** Returns all gift certificate line items of the container. **Returns:** A collection of all GiftCertificateLineItems of the container. --- ### getGiftCertificateLineItems **Signature:** `getGiftCertificateLineItems(giftCertificateId : String) : Collection` **Description:** Returns all gift certificate line items of the container, no matter if they are dependent or independent. **Parameters:** - `giftCertificateId`: the gift certificate identifier. **Returns:** A collection of all GiftCertificateLineItems of the container. --- ### getGiftCertificatePaymentInstruments **Signature:** `getGiftCertificatePaymentInstruments() : Collection` **Description:** Returns an unsorted collection of the PaymentInstrument instances that represent GiftCertificates in this container. **Returns:** an unsorted collection containing the set of PaymentInstrument instances that represent GiftCertificates. --- ### getGiftCertificatePaymentInstruments **Signature:** `getGiftCertificatePaymentInstruments(giftCertificateCode : String) : Collection` **Description:** Returns an unsorted collection containing all PaymentInstruments of type PaymentInstrument.METHOD_GIFT_CERTIFICATE where the specified code is the same code on the payment instrument. **Parameters:** - `giftCertificateCode`: the gift certificate code. **Returns:** an unsorted collection containing all PaymentInstruments of type PaymentInstrument.METHOD_GIFT_CERTIFICATE where the specified code is the same code on the payment instrument. --- ### getGiftCertificateTotalGrossPrice **Signature:** `getGiftCertificateTotalGrossPrice() : Money` **Description:** Returns the total gross price of all gift certificates in the cart. Should usually be equal to total net price. **Returns:** the total gross price of all gift certificate line items --- ### getGiftCertificateTotalNetPrice **Signature:** `getGiftCertificateTotalNetPrice() : Money` **Description:** Returns the total net price (excluding tax) of all gift certificates in the cart. Should usually be equal to total gross price. **Returns:** the total net price of all gift certificate line items --- ### getGiftCertificateTotalPrice **Signature:** `getGiftCertificateTotalPrice() : Money` **Description:** Returns the gift certificate total price. If the line item container is based on net pricing the gift certificate total net price is returned. If the line item container is based on gross pricing the gift certificate total gross price is returned. **Returns:** either the gift certificate total net or gross price --- ### getGiftCertificateTotalTax **Signature:** `getGiftCertificateTotalTax() : Money` **Description:** Returns the total tax of all gift certificates in the cart. Should usually be 0.0. **Returns:** the total tax of all gift certificate line items --- ### getMerchandizeTotalGrossPrice **Signature:** `getMerchandizeTotalGrossPrice() : Money` **Description:** Returns the total gross price (including tax) in purchase currency. Merchandize total prices represent the sum of product prices before services such as shipping or adjustment from promotions have been added. **Returns:** the total gross price (including tax) in purchase currency. --- ### getMerchandizeTotalNetPrice **Signature:** `getMerchandizeTotalNetPrice() : Money` **Description:** Returns the total net price (excluding tax) in purchase currency. Merchandize total prices represent the sum of product prices before services such as shipping or adjustment from promotion have been added. **Returns:** the total net price (excluding tax) in purchase currency. --- ### getMerchandizeTotalPrice **Signature:** `getMerchandizeTotalPrice() : Money` **Description:** Returns the merchandize total price. If the line item container is based on net pricing the merchandize total net price is returned. If the line item container is based on gross pricing the merchandize total gross price is returned. **Returns:** either the merchandize total net or gross price --- ### getMerchandizeTotalTax **Signature:** `getMerchandizeTotalTax() : Money` **Description:** Returns the total tax in purchase currency. Merchandize total prices represent the sum of product prices before services such as shipping or adjustment from promotions have been added. **Returns:** the total tax in purchase currency. --- ### getNotes **Signature:** `getNotes() : List` **Description:** Returns the list of notes for this object, ordered by creation time from oldest to newest. **Returns:** the list of notes for this object, ordered by creation time from oldest to newest. --- ### getPaymentInstrument **Signature:** `getPaymentInstrument() : OrderPaymentInstrument` **Description:** Returns the payment instrument of the line item container or null. This method is deprecated. You should use getPaymentInstruments() or getGiftCertificatePaymentInstruments() instead. **Deprecated:** Use getPaymentInstruments() or getGiftCertificatePaymentInstruments() to get the set of payment instruments. **Returns:** the order payment instrument of the line item container or null. --- ### getPaymentInstruments **Signature:** `getPaymentInstruments() : Collection` **Description:** Returns an unsorted collection of the payment instruments in this container. **Returns:** an unsorted collection containing the set of PaymentInstrument instances associated with this container. --- ### getPaymentInstruments **Signature:** `getPaymentInstruments(paymentMethodID : String) : Collection` **Description:** Returns an unsorted collection of PaymentInstrument instances based on the specified payment method ID. **Parameters:** - `paymentMethodID`: the ID of the payment method used. **Returns:** an unsorted collection of OrderPaymentInstrument instances based on the payment method. --- ### getPriceAdjustmentByPromotionID **Signature:** `getPriceAdjustmentByPromotionID(promotionID : String) : PriceAdjustment` **Description:** Returns the price adjustment associated to the specified promotion ID. **Parameters:** - `promotionID`: Promotion id **Returns:** The price adjustment associated with the specified promotion ID or null if none was found. --- ### getPriceAdjustments **Signature:** `getPriceAdjustments() : Collection` **Description:** Returns the collection of price adjustments that have been applied to the totals such as promotion on the purchase value (i.e. $10 Off or 10% Off). The price adjustments are sorted by the order in which they were applied to the order by the promotions engine. **Returns:** the sorted collection of PriceAdjustment instances. --- ### getProductLineItems **Signature:** `getProductLineItems() : Collection` **Description:** Returns the product line items of the container that are not dependent on other product line items. This includes line items representing bonus products in the container but excludes option, bundled, and bonus line items. The returned collection is sorted by the position attribute of the product line items. **Returns:** A sorted collection of ProductLineItem instances which are not dependent on other product line items. --- ### getProductLineItems **Signature:** `getProductLineItems(productID : String) : Collection` **Description:** Returns the product line items of the container that have a product ID equal to the specified product ID and that are not dependent on other product line items. This includes line items representing bonus products in the container, but excludes option, bundled and bonus line items. The returned collection is sorted by the position attribute of the product line items. **Parameters:** - `productID`: The Product ID used to filter the product line items. **Returns:** A sorted collection of ProductLineItem instances which have the specified product ID and are not dependent on other product line items. --- ### getProductQuantities **Signature:** `getProductQuantities() : HashMap` **Description:** Returns a hash map of all products in the line item container and their total quantities. The total product quantity is for example used to lookup the product price. The method counts all direct product line items, plus dependent product line items that are not bundled line items and no option line items. It also excludes product line items that are not associated to any catalog product, and bonus product line items. **Returns:** a map of products and their total quantities. **See Also:** getProductQuantities(Boolean) --- ### getProductQuantities **Signature:** `getProductQuantities(includeBonusProducts : boolean) : HashMap` **Description:** Returns a hash map of all products in the line item container and their total quantities. The total product quantity is for example used to lookup the product price in the cart. The method counts all direct product line items, plus dependent product line items that are not bundled line items and no option line items. It also excludes product line items that are not associated to any catalog product. If the parameter 'includeBonusProducts' is set to true, the method also counts bonus product line items. **Parameters:** - `includeBonusProducts`: if true also bonus product line item are counted **Returns:** A map of products and their total quantities. --- ### getProductQuantityTotal **Signature:** `getProductQuantityTotal() : Number` **Description:** Returns the total quantity of all product line items. Not included are bundled line items and option line items. **Returns:** The total quantity of all line items of the container. --- ### getShipment **Signature:** `getShipment(id : String) : Shipment` **Description:** Returns the shipment for the specified ID or null if no shipment with this ID exists in the line item container. Using "me" always returns the default shipment. **Parameters:** - `id`: the shipment identifier **Returns:** the shipment or null --- ### getShipments **Signature:** `getShipments() : Collection` **Description:** Returns all shipments of the line item container. The first shipment in the returned collection is the default shipment (shipment ID always set to "me"). All other shipments are sorted ascending by shipment ID. **Returns:** all shipments of the line item container --- ### getShippingPriceAdjustmentByPromotionID **Signature:** `getShippingPriceAdjustmentByPromotionID(promotionID : String) : PriceAdjustment` **Description:** Returns the shipping price adjustment associated with the specified promotion ID. **Parameters:** - `promotionID`: Promotion id **Returns:** The price adjustment associated with the specified promotion ID or null if none was found. --- ### getShippingPriceAdjustments **Signature:** `getShippingPriceAdjustments() : Collection` **Description:** Returns the of shipping price adjustments applied to the shipping total of the container. Note that the promotions engine only applies shipping price adjustments to the the default shipping line item of shipments, and never to the container. **Returns:** a collection of shipping price adjustments. **See Also:** getAllShippingPriceAdjustments() --- ### getShippingTotalGrossPrice **Signature:** `getShippingTotalGrossPrice() : Money` **Description:** Returns the sum of all shipping line items of the line item container, including tax before shipping adjustments have been applied. **Returns:** the sum of all shipping line items of the line item container, including tax before shipping adjustments have been applied. --- ### getShippingTotalNetPrice **Signature:** `getShippingTotalNetPrice() : Money` **Description:** Returns the sum of all shipping line items of the line item container, excluding tax before shipping adjustments have been applied. **Returns:** the sum of all shipping line items of the line item container, excluding tax before shipping adjustments have been applied. --- ### getShippingTotalPrice **Signature:** `getShippingTotalPrice() : Money` **Description:** Returns the shipping total price. If the line item container is based on net pricing the shipping total net price is returned. If the line item container is based on gross pricing the shipping total gross price is returned. **Returns:** either the shipping total net or gross price --- ### getShippingTotalTax **Signature:** `getShippingTotalTax() : Money` **Description:** Returns the tax of all shipping line items of the line item container before shipping adjustments have been applied. **Returns:** the tax of all shipping line items of the line item container before shipping adjustments have been applied. --- ### getTaxTotalsPerTaxRate **Signature:** `getTaxTotalsPerTaxRate() : SortedMap` **Description:** This method returns a SortedMap in which the keys are Decimal tax rates and the values are Money total tax for the tax rate. The map is unmodifiable. **Returns:** sorted map of tax rate against total tax --- ### getTotalGrossPrice **Signature:** `getTotalGrossPrice() : Money` **Description:** Returns the grand total price gross of tax for LineItemCtnr, in purchase currency. Total prices represent the sum of product prices, services prices and adjustments. **Returns:** the grand total price. --- ### getTotalNetPrice **Signature:** `getTotalNetPrice() : Money` **Description:** Returns the grand total price for LineItemCtnr net of tax, in purchase currency. Total prices represent the sum of product prices, services prices and adjustments. **Returns:** the grand total price. --- ### getTotalTax **Signature:** `getTotalTax() : Money` **Description:** Returns the grand total tax for LineItemCtnr, in purchase currency. Total prices represent the sum of product prices, services prices and adjustments. **Returns:** the grand total tax. --- ### isExternallyTaxed **Signature:** `isExternallyTaxed() : boolean` **Description:** Use this method to check whether the LineItemCtnr is calculated based on external tax tables. Note: a basket can only be created in EXTERNAL tax mode using SCAPI. **Returns:** true if the LineItemCtnr was calculated based on external tax tables. --- ### isTaxRoundedAtGroup **Signature:** `isTaxRoundedAtGroup() : boolean` **Description:** Use this method to check if the LineItemCtnr was calculated with grouped taxation calculation. If the tax is rounded on group level, the tax is applied to the summed-up tax basis for each tax rate. **Returns:** true if the LineItemCtnr was calculated with grouped taxation --- ### removeAllPaymentInstruments **Signature:** `removeAllPaymentInstruments() : void` **Description:** Removes the all Payment Instruments from this container and deletes the Payment Instruments. --- ### removeBonusDiscountLineItem **Signature:** `removeBonusDiscountLineItem(bonusDiscountLineItem : BonusDiscountLineItem) : void` **Description:** Removes the specified bonus discount line item from the line item container. **Parameters:** - `bonusDiscountLineItem`: The bonus discount line item to remove, must not be null. --- ### removeCouponLineItem **Signature:** `removeCouponLineItem(couponLineItem : CouponLineItem) : void` **Description:** Removes the specified coupon line item from the line item container. **Parameters:** - `couponLineItem`: The coupon line item to remove --- ### removeGiftCertificateLineItem **Signature:** `removeGiftCertificateLineItem(giftCertificateLineItem : GiftCertificateLineItem) : void` **Description:** Removes the specified gift certificate line item from the line item container. **Parameters:** - `giftCertificateLineItem`: The gift certificate line item to remove --- ### removeNote **Signature:** `removeNote(note : Note) : void` **Description:** Removes a note from this line item container and deletes it. **Parameters:** - `note`: The note to remove. Must not be null. Must belong to this line item container. --- ### removePaymentInstrument **Signature:** `removePaymentInstrument(pi : PaymentInstrument) : void` **Description:** Removes the specified Payment Instrument from this container and deletes the Payment Instrument. **Parameters:** - `pi`: the Payment Instrument to remove. --- ### removePriceAdjustment **Signature:** `removePriceAdjustment(priceAdjustment : PriceAdjustment) : void` **Description:** Removes the specified price adjustment line item from the line item container. **Parameters:** - `priceAdjustment`: The price adjustment line item to remove, must not be null. --- ### removeProductLineItem **Signature:** `removeProductLineItem(productLineItem : ProductLineItem) : void` **Description:** Removes the specified product line item from the line item container. **Parameters:** - `productLineItem`: The product line item to remove, must not be null. --- ### removeShipment **Signature:** `removeShipment(shipment : Shipment) : void` **Description:** Removes the specified shipment and all associated product, gift certificate, shipping and price adjustment line items from the line item container. It is not permissible to remove the default shipment. **Parameters:** - `shipment`: Shipment to be removed, must not be null. --- ### removeShippingPriceAdjustment **Signature:** `removeShippingPriceAdjustment(priceAdjustment : PriceAdjustment) : void` **Description:** Removes the specified shipping price adjustment line item from the line item container. **Parameters:** - `priceAdjustment`: The price adjustment line item to remove, must not be null. --- ### setCustomerEmail **Signature:** `setCustomerEmail(aValue : String) : void` **Description:** Sets the email address of the customer associated with this container. **Parameters:** - `aValue`: the email address of the customer associated with this container. --- ### setCustomerName **Signature:** `setCustomerName(aValue : String) : void` **Description:** Sets the name of the customer associated with this container. **Parameters:** - `aValue`: the name of the customer associated with this container. --- ### updateOrderLevelPriceAdjustmentTax **Signature:** `updateOrderLevelPriceAdjustmentTax() : void` **Description:** Calculates the tax for all shipping and order-level merchandise price adjustments in this LineItemCtnr. The tax on each adjustment is calculated from the taxes of the line items the adjustment applies across. This method must be invoked at the end of tax calculation of a basket or an order. --- ### updateTotals **Signature:** `updateTotals() : void` **Description:** Recalculates the totals of the line item container. It is necessary to call this method after any type of modification to the basket. --- ### verifyPriceAdjustmentLimits **Signature:** `verifyPriceAdjustmentLimits() : Status` **Description:** Verifies whether the manual price adjustments made for the line item container exceed the corresponding limits for the current user and the current site. The results of this method are based on the current values held in the LineItemCtnr, such as the base price of manual price adjustments. It is important the method is only called after the calculation process has completed. Status.OK is returned if NONE of the manual price adjustments exceed the correspondent limits. Status.ERROR is returned if ANY of the manual price adjustments exceed the correspondent limits. If this case Status.getItems() returns all price adjustment limit violations. The code of each StatusItem represents the violated price adjustment type (see PriceAdjustmentLimitTypes). StatusItem.getDetails() returns a Map with the max amount and (where relevant) the item to which the violation applies. Usage: var order : Order; // known var status : Status = order.verifyPriceAdjustmentLimits(); if (status.status == Status.ERROR) { for each (var statusItem : StatusItem in status.items) { var statusDetail : MapEntry = statusItem.details.entrySet().iterator().next(); var maxAllowedLimit : Number = (Number) (statusDetail.key); if (statusItem.code == PriceAdjustmentLimitTypes.TYPE_ORDER) { // fix order price adjustment considering maxAllowedLimit } else if (statusItem.code == PriceAdjustmentLimitTypes.TYPE_ITEM) { var pli : ProductLineItem = (ProductLineItem) (statusDetail.value); // fix pli price adjustment considering maxAllowedLimit } else if (statusItem.code == PriceAdjustmentLimitTypes.TYPE_SHIPPING) { if (statusDetail.value == null) { // fix order level shipping price adjustment considering maxAllowedLimit } else { var sli : ShippingLineItem = (ShippingLineItem) (statusDetail.value); // fix sli price adjustment considering maxAllowedLimit } } } } **Returns:** a Status instance with - Status.OK if all manual price adjustments do not exceed the correspondent limits, otherwise Status.ERROR --- ```