#
tokens: 44058/50000 3/825 files (page 38/43)
lines: off (toggle) GitHub
raw markdown copy
This is page 38 of 43. Use http://codebase.md/taurgis/sfcc-dev-mcp?lines=false&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/dw_order/PaymentInstrument.md:
--------------------------------------------------------------------------------

```markdown
## Package: dw.order

# Class PaymentInstrument

## Inheritance Hierarchy

- Object
  - dw.object.PersistentObject
  - dw.object.ExtensibleObject
    - dw.customer.EncryptedObject
      - dw.order.PaymentInstrument

## Description

Base class for payment instrument either stored in the customers profile or related to an order. A payment instrument can be credit card or bank transfer. The object defines standard methods for credit card payment, and can be extended by attributes appropriate for other payment methods. Note: this class handles sensitive financial and card holder data. Pay special attention to PCI DSS v3. requirements 1, 3, 7, and 9.

## Constants

### ENCRYPTION_ALGORITHM_RSA

**Type:** String = "RSA"

The outdated encryption algorithm "RSA/ECB/PKCS1Padding". Please do not use anymore!

### ENCRYPTION_ALGORITHM_RSA_ECB_OAEPWITHSHA_256ANDMGF1PADDING

**Type:** String = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding"

The encryption algorithm "RSA/ECB/OAEPWithSHA-256AndMGF1Padding".

### METHOD_BANK_TRANSFER

**Type:** String = "BANK_TRANSFER"

Represents a bank transfer type of payment.

### METHOD_BML

**Type:** String = "BML"

Represents a 'bill me later' type of payment.

### METHOD_CREDIT_CARD

**Type:** String = "CREDIT_CARD"

Represents a credit card type of payment.

### METHOD_DW_ANDROID_PAY

**Type:** String = "DW_ANDROID_PAY"

Represents an Android Pay payment.

### METHOD_DW_APPLE_PAY

**Type:** String = "DW_APPLE_PAY"

Represents an Apple Pay payment.

### METHOD_GIFT_CERTIFICATE

**Type:** String = "GIFT_CERTIFICATE"

Represents a gift certificate.

## Properties

### bankAccountDriversLicense

**Type:** String

The driver's license number associated with the bank account if the
 calling context meets the following criteria: 
 
 
 If the instance is a CustomerPaymentInstrument, and
 we are in the context of a storefront request, and the current customer
 is registered and authenticated, and the payment instrument is associated
 to the profile of the current customer, and the current protocol is HTTPS
 
 
 If the instance is a OrderPaymentInstrumentInfo, and we are in
 the context of a storefront request, and the current customer is identical
 to the customer related to the basket, and the current protocol is HTTPS
 
 
 If the instance is a OrderPaymentInstrumentInfo, and we are in
 the context of a business manager request, and the current user has the
 permission MANAGE_ORDERS
 
 
 If the instance is a OrderPaymentInstrumentInfo, and the account information
 has not been masked as a result of the data retention security policy
 for the site
 
 
 
 Otherwise, the method returns the masked driver's license number. If a basket is reopened with
 OrderMgr.failOrder(Order, Boolean), it always masks sensitive information
 because during order creation, basket payment information is permanently masked.

### bankAccountDriversLicenseLastDigits

**Type:** String (Read Only)

The last 4 characters of the decrypted driver's license number of
 the bank account associated with this PaymentInstrument.

 If the number is empty or null
 it will be returned without an exception.

### bankAccountDriversLicenseStateCode

**Type:** String

The driver's license state code associated with a bank account payment instrument.
 Returns null for other payment methods.

### bankAccountHolder

**Type:** String

The full name of the holder of a bank account payment instrument.
 Returns null for other payment methods.

### bankAccountNumber

**Type:** String

The bank account number if the calling context meets
 the following criteria: 
 
 
 If the instance is a CustomerPaymentInstrument, and
 we are in the context of a storefront request, and the current customer
 is registered and authenticated, and the payment instrument is associated
 to the profile of the current customer, and the current protocol is HTTPS
 
 
 If the instance is a OrderPaymentInstrumentInfo, and we are in
 the context of a storefront request, and the current customer is identical
 to the customer related to the basket, and the current protocol is HTTPS
 
 
 If the instance is a OrderPaymentInstrumentInfo, and we are in
 the context of a business manager request, and the current user has the
 permission MANAGE_ORDERS
 
 
 If the instance is a OrderPaymentInstrumentInfo, and the account information
 has not been masked as a result of the data retention security policy
 for the site
 
 
 
 Otherwise, the method returns the masked bank account number. If a basket is reopened with
 OrderMgr.failOrder(Order, Boolean), it always masks sensitive information
 because during order creation, basket payment information is permanently masked.

### bankAccountNumberLastDigits

**Type:** String (Read Only)

The last 4 characters of the decrypted bank account number.

 If the number is empty or null,
 it will be returned without an exception.

### bankRoutingNumber

**Type:** String

The bank routing number of a bank account payment instrument.
 Returns null for other payment methods.

 If account information has been masked due to the data retention security
 policy for the site, the return value is fully masked.

### creditCardExpirationMonth

**Type:** Number

The month of the year in which the credit card
 expires (1-12).

### creditCardExpirationYear

**Type:** Number

The year in which the credit card
 expires, such as '2004'.

### creditCardExpired

**Type:** boolean (Read Only)

Returns true if this payment instrument represents an expired credit
 card. This check is only logical if the credit card expiration month and
 year are set. If either of these attributes are not set, then this method
 always returns false.

### creditCardHolder

**Type:** String

The name of the credit card owner.

### creditCardIssueNumber

**Type:** String

The credit card issue number.  This attribute is only used by
 specific credit/debit card processors such as Solo and Switch in the UK.

### creditCardNumber

**Type:** String

The decrypted credit card number if the calling context meets
 the following criteria: 
 
 
 If the instance is a CustomerPaymentInstrument, and
 we are in the context of a storefront request, and the current customer
 is registered and authenticated, and the payment instrument is associated
 to the profile of the current customer, and the current protocol is HTTPS
 
 
 If the instance is a OrderPaymentInstrument in the context of a storefront request, and
 the current authenticated customer is referenced by the basket or order, and
 the current protocol is HTTPS.
 
 
 If the customer is anonymous, and the customer is referenced by the order, and the protocol is secure and
 the order status is CREATED.
 
 
 If the instance is a OrderPaymentInstrument, and we are in
 the context of a business manager request, and the current user has the
 permission MANAGE_ORDERS
 
 
 If the instance is a OrderPaymentInstrument, and the account information
 has not been masked as a result of the data retention security policy
 for the site
 
 
 
 Otherwise, the method returns the masked credit card number. If a basket is reopened with
 OrderMgr.failOrder(Order, Boolean), it always masks sensitive information
 because during order creation, basket payment information is permanently masked.

### creditCardNumberLastDigits

**Type:** String (Read Only)

The last 4 characters of the decrypted credit card number.

 If the number is empty or null
 it will be returned without an exception.

### creditCardToken

**Type:** String

Secure credit card data can be replaced by a token by utilizing a
 tokenization provider, which securely stores the credit card data using
 the token as a key. The stored data can later reused by including the
 token in a request. In this way credit card processes such as
 authorization and capture can be implemented without being responsible
 for persisting the credit card data.

### creditCardType

**Type:** String

The type of the credit card.

### creditCardValidFromMonth

**Type:** Number

The month of the year in which the credit card became
 valid (1-12).  This attribute is not used by all credit card types.

### creditCardValidFromYear

**Type:** Number

The year in which the credit card became valid, such as '2001'.
 This attribute is not used by all credit card types.

### giftCertificateCode

**Type:** String

The Gift Certificate code for this Payment Instrument.

### giftCertificateID

**Type:** String

The Gift Certificate ID for this Payment Instrument.

### maskedBankAccountDriversLicense

**Type:** String (Read Only)

The decrypted driver's license number of the bank account with
 all but the last 4 characters replaced with a '*' character.

 If the driver's license number is empty,
 it will be returned without an exception.

### maskedBankAccountNumber

**Type:** String (Read Only)

The decrypted bank account number with
 all but the last 4 characters replaced with a '*' character.

 If the number is empty (i.e. "" or null),
 it will be returned without an exception.

### maskedCreditCardNumber

**Type:** String (Read Only)

The decrypted credit card number with
 all but the last 4 characters replaced with a '*' character.

 If the number is empty,
 it will be returned without an exception.

### maskedGiftCertificateCode

**Type:** String (Read Only)

The masked gift certificate code with
 all but the last 4 characters replaced with a '*' character.

### paymentMethod

**Type:** String (Read Only)

The identifier of the payment method represented by this
 payment instrument.

### permanentlyMasked

**Type:** boolean (Read Only)

Returns true if the account information for this Payment Instrument
 has been permanently masked as a result of the data retention security policy
 for the site or a creditcard tokenization, and false otherwise.

 When account information is masked only the last 4 digits of the credit card
 or bank account number are recoverable.  The bank account driver's license number
 and bank routing number are completely masked.

## Constructor Summary

## Method Summary

### getBankAccountDriversLicense

**Signature:** `getBankAccountDriversLicense() : String`

Returns the driver's license number associated with the bank account if the calling context meets the following criteria: If the instance is a CustomerPaymentInstrument, and we are in the context of a storefront request, and the current customer is registered and authenticated, and the payment instrument is associated to the profile of the current customer, and the current protocol is HTTPS If the instance is a OrderPaymentInstrumentInfo, and we are in the context of a storefront request, and the current customer is identical to the customer related to the basket, and the current protocol is HTTPS If the instance is a OrderPaymentInstrumentInfo, and we are in the context of a business manager request, and the current user has the permission MANAGE_ORDERS If the instance is a OrderPaymentInstrumentInfo, and the account information has not been masked as a result of the data retention security policy for the site

### getBankAccountDriversLicenseLastDigits

**Signature:** `getBankAccountDriversLicenseLastDigits() : String`

Returns the last 4 characters of the decrypted driver's license number of the bank account associated with this PaymentInstrument.

### getBankAccountDriversLicenseLastDigits

**Signature:** `getBankAccountDriversLicenseLastDigits(count : Number) : String`

Returns the last specified number of characters of the decrypted driver's license number of the bank account associated with this PaymentInstrument.

### getBankAccountDriversLicenseStateCode

**Signature:** `getBankAccountDriversLicenseStateCode() : String`

Returns the driver's license state code associated with a bank account payment instrument.

### getBankAccountHolder

**Signature:** `getBankAccountHolder() : String`

Returns the full name of the holder of a bank account payment instrument.

### getBankAccountNumber

**Signature:** `getBankAccountNumber() : String`

Returns the bank account number if the calling context meets the following criteria: If the instance is a CustomerPaymentInstrument, and we are in the context of a storefront request, and the current customer is registered and authenticated, and the payment instrument is associated to the profile of the current customer, and the current protocol is HTTPS If the instance is a OrderPaymentInstrumentInfo, and we are in the context of a storefront request, and the current customer is identical to the customer related to the basket, and the current protocol is HTTPS If the instance is a OrderPaymentInstrumentInfo, and we are in the context of a business manager request, and the current user has the permission MANAGE_ORDERS If the instance is a OrderPaymentInstrumentInfo, and the account information has not been masked as a result of the data retention security policy for the site

### getBankAccountNumberLastDigits

**Signature:** `getBankAccountNumberLastDigits() : String`

Returns the last 4 characters of the decrypted bank account number.

### getBankAccountNumberLastDigits

**Signature:** `getBankAccountNumberLastDigits(count : Number) : String`

Returns the last specified number of characters of the decrypted bank account card number.

### getBankRoutingNumber

**Signature:** `getBankRoutingNumber() : String`

Returns the bank routing number of a bank account payment instrument.

### getCreditCardExpirationMonth

**Signature:** `getCreditCardExpirationMonth() : Number`

Returns the month of the year in which the credit card expires (1-12).

### getCreditCardExpirationYear

**Signature:** `getCreditCardExpirationYear() : Number`

Returns the year in which the credit card expires, such as '2004'.

### getCreditCardHolder

**Signature:** `getCreditCardHolder() : String`

Returns the name of the credit card owner.

### getCreditCardIssueNumber

**Signature:** `getCreditCardIssueNumber() : String`

Returns the credit card issue number.

### getCreditCardNumber

**Signature:** `getCreditCardNumber() : String`

Returns the decrypted credit card number if the calling context meets the following criteria: If the instance is a CustomerPaymentInstrument, and we are in the context of a storefront request, and the current customer is registered and authenticated, and the payment instrument is associated to the profile of the current customer, and the current protocol is HTTPS If the instance is a OrderPaymentInstrument in the context of a storefront request, and the current authenticated customer is referenced by the basket or order, and the current protocol is HTTPS.

### getCreditCardNumberLastDigits

**Signature:** `getCreditCardNumberLastDigits() : String`

Returns the last 4 characters of the decrypted credit card number.

### getCreditCardNumberLastDigits

**Signature:** `getCreditCardNumberLastDigits(count : Number) : String`

Returns the last specified number of characters of the decrypted credit card number.

### getCreditCardToken

**Signature:** `getCreditCardToken() : String`

Secure credit card data can be replaced by a token by utilizing a tokenization provider, which securely stores the credit card data using the token as a key.

### getCreditCardType

**Signature:** `getCreditCardType() : String`

Returns the type of the credit card.

### getCreditCardValidFromMonth

**Signature:** `getCreditCardValidFromMonth() : Number`

Returns the month of the year in which the credit card became valid (1-12).

### getCreditCardValidFromYear

**Signature:** `getCreditCardValidFromYear() : Number`

Returns the year in which the credit card became valid, such as '2001'.

### getEncryptedBankAccountDriversLicense

**Signature:** `getEncryptedBankAccountDriversLicense(algorithm : String, publicKey : String) : String`

Encrypts the driver's license number of the bank account of this object with the given algorithm and the given public key.

### getEncryptedBankAccountNumber

**Signature:** `getEncryptedBankAccountNumber(algorithm : String, publicKey : String) : String`

Encrypts the bank account number of this object with the given algorithm and the given public key.

### getEncryptedCreditCardNumber

**Signature:** `getEncryptedCreditCardNumber(algorithm : String, publicKey : String) : String`

Encrypts the credit card number of this object with the given algorithm and the given public key.

### getEncryptedCreditCardNumber

**Signature:** `getEncryptedCreditCardNumber(algorithm : String, certificateRef : CertificateRef) : String`

Encrypts the credit card number of this object with the given algorithm and the public key taken from a certificate in the keystore.

### getGiftCertificateCode

**Signature:** `getGiftCertificateCode() : String`

Returns the Gift Certificate code for this Payment Instrument.

### getGiftCertificateID

**Signature:** `getGiftCertificateID() : String`

Returns the Gift Certificate ID for this Payment Instrument.

### getMaskedBankAccountDriversLicense

**Signature:** `getMaskedBankAccountDriversLicense() : String`

Returns the decrypted driver's license number of the bank account with all but the last 4 characters replaced with a '*' character.

### getMaskedBankAccountDriversLicense

**Signature:** `getMaskedBankAccountDriversLicense(ignore : Number) : String`

Returns the decrypted driver's license number of the bank account with all but the specified number characters replaced with a '*' character.

### getMaskedBankAccountNumber

**Signature:** `getMaskedBankAccountNumber() : String`

Returns the decrypted bank account number with all but the last 4 characters replaced with a '*' character.

### getMaskedBankAccountNumber

**Signature:** `getMaskedBankAccountNumber(ignore : Number) : String`

Returns the decrypted bank account number with all but the specified number characters replaced with a '*' character.

### getMaskedCreditCardNumber

**Signature:** `getMaskedCreditCardNumber() : String`

Returns the decrypted credit card number with all but the last 4 characters replaced with a '*' character.

### getMaskedCreditCardNumber

**Signature:** `getMaskedCreditCardNumber(ignore : Number) : String`

Returns the decrypted credit card number with all but the specified number characters replaced with a '*' character.

### getMaskedGiftCertificateCode

**Signature:** `getMaskedGiftCertificateCode() : String`

Returns the masked gift certificate code with all but the last 4 characters replaced with a '*' character.

### getMaskedGiftCertificateCode

**Signature:** `getMaskedGiftCertificateCode(ignore : Number) : String`

Returns the masked gift certificate code with all but the specified number of characters replaced with a '*' character.

### getPaymentMethod

**Signature:** `getPaymentMethod() : String`

Returns the identifier of the payment method represented by this payment instrument.

### isCreditCardExpired

**Signature:** `isCreditCardExpired() : boolean`

Returns true if this payment instrument represents an expired credit card.

### isPermanentlyMasked

**Signature:** `isPermanentlyMasked() : boolean`

Returns true if the account information for this Payment Instrument has been permanently masked as a result of the data retention security policy for the site or a creditcard tokenization, and false otherwise.

### setBankAccountDriversLicense

**Signature:** `setBankAccountDriversLicense(license : String) : void`

Set the driver's license number associated with a bank account payment instrument.

### setBankAccountDriversLicenseStateCode

**Signature:** `setBankAccountDriversLicenseStateCode(stateCode : String) : void`

Set the driver's license state code associated with a bank account payment instrument.

### setBankAccountHolder

**Signature:** `setBankAccountHolder(holder : String) : void`

Set the full name of the holder of a bank account payment instrument.

### setBankAccountNumber

**Signature:** `setBankAccountNumber(accountNumber : String) : void`

Set the bank account number of a bank account payment instrument.

### setBankRoutingNumber

**Signature:** `setBankRoutingNumber(routingNumber : String) : void`

Set the bank routing number of a bank account payment instrument.

### setCreditCardExpirationMonth

**Signature:** `setCreditCardExpirationMonth(aValue : Number) : void`

Sets the month of the year in which the credit card expires.

### setCreditCardExpirationYear

**Signature:** `setCreditCardExpirationYear(aValue : Number) : void`

Sets the year in which the credit card expires, such as '2004'.

### setCreditCardHolder

**Signature:** `setCreditCardHolder(aValue : String) : void`

Sets the name of the credit card owner.

### setCreditCardIssueNumber

**Signature:** `setCreditCardIssueNumber(aValue : String) : void`

Set the credit card issue number.

### setCreditCardNumber

**Signature:** `setCreditCardNumber(aValue : String) : void`

Sets the credit card number for this payment.

### setCreditCardToken

**Signature:** `setCreditCardToken(token : String) : void`

Secure credit card data can be replaced by a token by utilizing a tokenization provider, which securely stores the credit card data using the token as a key.

### setCreditCardType

**Signature:** `setCreditCardType(aValue : String) : void`

Sets the type of the credit card.

### setCreditCardValidFromMonth

**Signature:** `setCreditCardValidFromMonth(aValue : Number) : void`

Sets the month of the year in which the credit card became valid (1-12).

### setCreditCardValidFromYear

**Signature:** `setCreditCardValidFromYear(aValue : Number) : void`

Sets the year in which the credit card became valid, such as '2001'.

### setGiftCertificateCode

**Signature:** `setGiftCertificateCode(giftCertificateCode : String) : void`

Sets the Gift Certificate code for this Payment Instrument.

### setGiftCertificateID

**Signature:** `setGiftCertificateID(giftCertificateID : String) : void`

Sets the Gift Certificate ID for this Payment Instrument.

## Method Detail

## Method Details

### getBankAccountDriversLicense

**Signature:** `getBankAccountDriversLicense() : String`

**Description:** Returns the driver's license number associated with the bank account if the calling context meets the following criteria: If the instance is a CustomerPaymentInstrument, and we are in the context of a storefront request, and the current customer is registered and authenticated, and the payment instrument is associated to the profile of the current customer, and the current protocol is HTTPS If the instance is a OrderPaymentInstrumentInfo, and we are in the context of a storefront request, and the current customer is identical to the customer related to the basket, and the current protocol is HTTPS If the instance is a OrderPaymentInstrumentInfo, and we are in the context of a business manager request, and the current user has the permission MANAGE_ORDERS If the instance is a OrderPaymentInstrumentInfo, and the account information has not been masked as a result of the data retention security policy for the site Otherwise, the method returns the masked driver's license number. If a basket is reopened with OrderMgr.failOrder(Order, Boolean), it always masks sensitive information because during order creation, basket payment information is permanently masked.

**Returns:**

the driver's license number if the calling context meets the necessary criteria.

**See Also:**

isPermanentlyMasked()

---

### getBankAccountDriversLicenseLastDigits

**Signature:** `getBankAccountDriversLicenseLastDigits() : String`

**Description:** Returns the last 4 characters of the decrypted driver's license number of the bank account associated with this PaymentInstrument. If the number is empty or null it will be returned without an exception.

**Returns:**

the last 4 characters of the de-crypted driver's license number.

---

### getBankAccountDriversLicenseLastDigits

**Signature:** `getBankAccountDriversLicenseLastDigits(count : Number) : String`

**Description:** Returns the last specified number of characters of the decrypted driver's license number of the bank account associated with this PaymentInstrument. If the number is empty (i.e. "" or null), it will be returned without an exception. Note that count is limited to 4 in an unsecure environment, and if account information for this payment instrument has been masked due to the data retention security policy for the site.

**Parameters:**

- `count`: number of characters to be returned.

**Returns:**

the last specified number of characters of the decrypted driver's license number.

**See Also:**

isPermanentlyMasked()

---

### getBankAccountDriversLicenseStateCode

**Signature:** `getBankAccountDriversLicenseStateCode() : String`

**Description:** Returns the driver's license state code associated with a bank account payment instrument. Returns null for other payment methods.

**Returns:**

the state in which the bank account driver's license was issued.

---

### getBankAccountHolder

**Signature:** `getBankAccountHolder() : String`

**Description:** Returns the full name of the holder of a bank account payment instrument. Returns null for other payment methods.

**Returns:**

the bank account holder's full name.

---

### getBankAccountNumber

**Signature:** `getBankAccountNumber() : String`

**Description:** Returns the bank account number if the calling context meets the following criteria: If the instance is a CustomerPaymentInstrument, and we are in the context of a storefront request, and the current customer is registered and authenticated, and the payment instrument is associated to the profile of the current customer, and the current protocol is HTTPS If the instance is a OrderPaymentInstrumentInfo, and we are in the context of a storefront request, and the current customer is identical to the customer related to the basket, and the current protocol is HTTPS If the instance is a OrderPaymentInstrumentInfo, and we are in the context of a business manager request, and the current user has the permission MANAGE_ORDERS If the instance is a OrderPaymentInstrumentInfo, and the account information has not been masked as a result of the data retention security policy for the site Otherwise, the method returns the masked bank account number. If a basket is reopened with OrderMgr.failOrder(Order, Boolean), it always masks sensitive information because during order creation, basket payment information is permanently masked.

**Returns:**

the bank account number if the calling context meets the necessary criteria.

**See Also:**

isPermanentlyMasked()

---

### getBankAccountNumberLastDigits

**Signature:** `getBankAccountNumberLastDigits() : String`

**Description:** Returns the last 4 characters of the decrypted bank account number. If the number is empty or null, it will be returned without an exception.

**Returns:**

the last 4 characters of the decrypted bank account number.

---

### getBankAccountNumberLastDigits

**Signature:** `getBankAccountNumberLastDigits(count : Number) : String`

**Description:** Returns the last specified number of characters of the decrypted bank account card number. If the number is empty (i.e. "" or null), it will be returned without an exception. Note that count is limited to 4 in an unsecure environment, and if account information for this payment instrument has been masked due to the data retention security policy for the site.

**Parameters:**

- `count`: number of characters to be returned.

**Returns:**

the last specified characters of the decrypted bank account number.

**See Also:**

isPermanentlyMasked()

---

### getBankRoutingNumber

**Signature:** `getBankRoutingNumber() : String`

**Description:** Returns the bank routing number of a bank account payment instrument. Returns null for other payment methods. If account information has been masked due to the data retention security policy for the site, the return value is fully masked.

**Returns:**

the bank account rounting number.

**See Also:**

isPermanentlyMasked()

---

### getCreditCardExpirationMonth

**Signature:** `getCreditCardExpirationMonth() : Number`

**Description:** Returns the month of the year in which the credit card expires (1-12).

**Returns:**

the month of the year in which the credit card expires (1-12).

---

### getCreditCardExpirationYear

**Signature:** `getCreditCardExpirationYear() : Number`

**Description:** Returns the year in which the credit card expires, such as '2004'.

**Returns:**

the year in which the credit card expires.

---

### getCreditCardHolder

**Signature:** `getCreditCardHolder() : String`

**Description:** Returns the name of the credit card owner.

**Returns:**

the name of the credit card owner.

---

### getCreditCardIssueNumber

**Signature:** `getCreditCardIssueNumber() : String`

**Description:** Returns the credit card issue number. This attribute is only used by specific credit/debit card processors such as Solo and Switch in the UK.

**Returns:**

the credit card issue number

---

### getCreditCardNumber

**Signature:** `getCreditCardNumber() : String`

**Description:** Returns the decrypted credit card number if the calling context meets the following criteria: If the instance is a CustomerPaymentInstrument, and we are in the context of a storefront request, and the current customer is registered and authenticated, and the payment instrument is associated to the profile of the current customer, and the current protocol is HTTPS If the instance is a OrderPaymentInstrument in the context of a storefront request, and the current authenticated customer is referenced by the basket or order, and the current protocol is HTTPS. If the customer is anonymous, and the customer is referenced by the order, and the protocol is secure and the order status is CREATED. If the instance is a OrderPaymentInstrument, and we are in the context of a business manager request, and the current user has the permission MANAGE_ORDERS If the instance is a OrderPaymentInstrument, and the account information has not been masked as a result of the data retention security policy for the site Otherwise, the method returns the masked credit card number. If a basket is reopened with OrderMgr.failOrder(Order, Boolean), it always masks sensitive information because during order creation, basket payment information is permanently masked.

**Returns:**

the decrypted credit card number if the calling context meets the necessary criteria.

**See Also:**

isPermanentlyMasked()

---

### getCreditCardNumberLastDigits

**Signature:** `getCreditCardNumberLastDigits() : String`

**Description:** Returns the last 4 characters of the decrypted credit card number. If the number is empty or null it will be returned without an exception.

**Returns:**

the last 4 characters of the de-crypted credit card number.

---

### getCreditCardNumberLastDigits

**Signature:** `getCreditCardNumberLastDigits(count : Number) : String`

**Description:** Returns the last specified number of characters of the decrypted credit card number. If the number is empty (i.e. "" or null), it will be returned without an exception. Note that count is limited to 4 in an unsecure environment, and if account information for this payment instrument has been masked due to the data retention security policy for the site.

**Parameters:**

- `count`: number of characters to be returned.

**Returns:**

the last specified number of characters of the decrypted credit card number.

**See Also:**

isPermanentlyMasked()

---

### getCreditCardToken

**Signature:** `getCreditCardToken() : String`

**Description:** Secure credit card data can be replaced by a token by utilizing a tokenization provider, which securely stores the credit card data using the token as a key. The stored data can later reused by including the token in a request. In this way credit card processes such as authorization and capture can be implemented without being responsible for persisting the credit card data.

**Returns:**

the token

---

### getCreditCardType

**Signature:** `getCreditCardType() : String`

**Description:** Returns the type of the credit card.

**Returns:**

the type of the credit card.

---

### getCreditCardValidFromMonth

**Signature:** `getCreditCardValidFromMonth() : Number`

**Description:** Returns the month of the year in which the credit card became valid (1-12). This attribute is not used by all credit card types.

**Returns:**

the month of the year in which the credit card became valid (1-12).

---

### getCreditCardValidFromYear

**Signature:** `getCreditCardValidFromYear() : Number`

**Description:** Returns the year in which the credit card became valid, such as '2001'. This attribute is not used by all credit card types.

**Returns:**

the year in which the credit card became valid

---

### getEncryptedBankAccountDriversLicense

**Signature:** `getEncryptedBankAccountDriversLicense(algorithm : String, publicKey : String) : String`

**Description:** Encrypts the driver's license number of the bank account of this object with the given algorithm and the given public key. Returned is the Base64 encoded representation of the result. See also Cipher.encrypt(String, String, String, String, Number) on how to generate RSA key pairs. If account information has been masked due to the data retention security policy for the site, the returned value is the Base64 encoded representation of the encrypted form of the masked number.

**Parameters:**

- `algorithm`: The algorithm to be used for the encryption of this credit card number. Must be a valid, non-null algorithm. Currently, only the following algorithms are supported: ENCRYPTION_ALGORITHM_RSA – outdated, please do not use anymore ENCRYPTION_ALGORITHM_RSA_ECB_OAEPWITHSHA56ANDMGF1PADDING – the current algorithm
- `publicKey`: A Base64 encoded form of the public key to be used to encrypt this bank account driver's license number. Must be a valid, non-blank key.

**Returns:**

the Base64 encoded representation of the bank account driver's license.

**Throws:**

IllegalArgumentException - If algorithm is not a valid known algorithm.
IllegalArgumentException - If publicKey is a null, empty or blank string.

---

### getEncryptedBankAccountNumber

**Signature:** `getEncryptedBankAccountNumber(algorithm : String, publicKey : String) : String`

**Description:** Encrypts the bank account number of this object with the given algorithm and the given public key. Returned is the Base64 encoded representation of the result. If account information has been masked due to the data retention security policy for the site, the returned value is the Base64 encoded representation of the encrypted form of the masked number.

**Parameters:**

- `algorithm`: The algorithm to be used for the encryption of this credit card number. Must be a valid, non-null algorithm. Currently, only the following algorithms are supported: ENCRYPTION_ALGORITHM_RSA – outdated, please do not use anymore ENCRYPTION_ALGORITHM_RSA_ECB_OAEPWITHSHA56ANDMGF1PADDING – the current algorithm
- `publicKey`: A Base64 encoded form of the public key to be used to encrypt this credit card number. Must be a valid, non-blank key.

**Returns:**

the Base64 encoded representation of the bank account number.

**See Also:**

isPermanentlyMasked()

**Throws:**

IllegalArgumentException - If algorithm is not a valid known algorithm.
IllegalArgumentException - If publicKey is a null, empty or blank string.

---

### getEncryptedCreditCardNumber

**Signature:** `getEncryptedCreditCardNumber(algorithm : String, publicKey : String) : String`

**Description:** Encrypts the credit card number of this object with the given algorithm and the given public key. Returned is the Base64 encoded representation of the result. See also Cipher.encrypt(String, String, String, String, Number) on how to generate RSA key pairs. If account information has been masked due to the data retention security policy for the site, the returned value is the Base64 encoded representation of the encrypted form of the masked number.

**Deprecated:**

Please use getEncryptedCreditCardNumber(String, CertificateRef) instead.

**Parameters:**

- `algorithm`: The algorithm to be used for the encryption of this credit card number. Must be a valid, non-null algorithm. Currently, only the following algorithms are supported: ENCRYPTION_ALGORITHM_RSA – outdated, please do not use anymore ENCRYPTION_ALGORITHM_RSA_ECB_OAEPWITHSHA56ANDMGF1PADDING – the current algorithm
- `publicKey`: A Base64 encoded form of the public key to be used to encrypt this credit card number. Must be a valid, non-blank key.

**Returns:**

the Base64 encoded representation of the credit card number.

**See Also:**

isPermanentlyMasked()

**Throws:**

IllegalArgumentException - If algorithm is not a valid known algorithm.
IllegalArgumentException - If publicKey is a null, empty or blank string.

---

### getEncryptedCreditCardNumber

**Signature:** `getEncryptedCreditCardNumber(algorithm : String, certificateRef : CertificateRef) : String`

**Description:** Encrypts the credit card number of this object with the given algorithm and the public key taken from a certificate in the keystore. Returned is the Base64 encoded representation of the result. See also Cipher.encrypt(String, CertificateRef, String, String, Number) on how to generate RSA key pairs. If account information has been masked due to the data retention security policy for the site, the returned value is the Base64 encoded representation of the encrypted form of the masked number.

**Parameters:**

- `algorithm`: The algorithm to be used for the encryption of this credit card number. Must be a valid, non-null algorithm. Currently, only the following algorithms are supported: ENCRYPTION_ALGORITHM_RSA – outdated, please do not use anymore ENCRYPTION_ALGORITHM_RSA_ECB_OAEPWITHSHA56ANDMGF1PADDING – the current algorithm
- `certificateRef`: A reference to a trusted certificate entry containing the public key in the keystore. Must be non-null.

**Returns:**

the Base64 encoded representation of the credit card number.

**See Also:**

isPermanentlyMasked()

**Throws:**

IllegalArgumentException - If algorithm is not a valid known algorithm.
IllegalArgumentException - If certificateRef is null or could not be found.

---

### getGiftCertificateCode

**Signature:** `getGiftCertificateCode() : String`

**Description:** Returns the Gift Certificate code for this Payment Instrument.

**Returns:**

the Gift Certificate code or null if not set.

---

### getGiftCertificateID

**Signature:** `getGiftCertificateID() : String`

**Description:** Returns the Gift Certificate ID for this Payment Instrument.

**Deprecated:**

Use getGiftCertificateCode()

**Returns:**

the Gift Certificate ID or null if not set.

---

### getMaskedBankAccountDriversLicense

**Signature:** `getMaskedBankAccountDriversLicense() : String`

**Description:** Returns the decrypted driver's license number of the bank account with all but the last 4 characters replaced with a '*' character. If the driver's license number is empty, it will be returned without an exception.

**Returns:**

the decrypted driver's license number with all but the last 4 characters replaced with a '*' character.

---

### getMaskedBankAccountDriversLicense

**Signature:** `getMaskedBankAccountDriversLicense(ignore : Number) : String`

**Description:** Returns the decrypted driver's license number of the bank account with all but the specified number characters replaced with a '*' character. If the driver's license number is empty (i.e. "" or null), it will be returned without an exception. Note that ignore is limited to 4 in an unsecure environment, and if account information for this payment instrument has been masked due to the data retention security policy for the site.

**Parameters:**

- `ignore`: the number of characters to leave unmasked.

**Returns:**

the decrypted driver's license number with all but the specified number characters replaced with a '*' character.

**See Also:**

isPermanentlyMasked()

---

### getMaskedBankAccountNumber

**Signature:** `getMaskedBankAccountNumber() : String`

**Description:** Returns the decrypted bank account number with all but the last 4 characters replaced with a '*' character. If the number is empty (i.e. "" or null), it will be returned without an exception.

**Returns:**

the decrypted bank account number with all but the last 4 characters replaced with a '*' character.

---

### getMaskedBankAccountNumber

**Signature:** `getMaskedBankAccountNumber(ignore : Number) : String`

**Description:** Returns the decrypted bank account number with all but the specified number characters replaced with a '*' character. If the card number is empty (i.e. "" or null), it will be returned without an exception. Note that ignore is limited to 4 in an unsecure environment, and if account information for this payment instrument has been masked due to the data retention security policy for the site.

**Parameters:**

- `ignore`: the number of characters to leave unmasked

**Returns:**

the decrypted bank account number with all but the specified number of characters replaced with a '*' character.

**See Also:**

isPermanentlyMasked()

---

### getMaskedCreditCardNumber

**Signature:** `getMaskedCreditCardNumber() : String`

**Description:** Returns the decrypted credit card number with all but the last 4 characters replaced with a '*' character. If the number is empty, it will be returned without an exception.

**Returns:**

the decrypted credit card number with all but the last 4 characters replaced with a '*' character.

---

### getMaskedCreditCardNumber

**Signature:** `getMaskedCreditCardNumber(ignore : Number) : String`

**Description:** Returns the decrypted credit card number with all but the specified number characters replaced with a '*' character. If the card number is empty (i.e. "" or null), it will be returned without an exception. Note that ignore is limited to 4 in an unsecure environment, and if account information for this payment instrument has been masked due to the data retention security policy for the site.

**Parameters:**

- `ignore`: the number of characters to leave unmasked.

**Returns:**

the decrypted credit card number with all but the specified number characters replaced with a '*' character.

**See Also:**

isPermanentlyMasked()

---

### getMaskedGiftCertificateCode

**Signature:** `getMaskedGiftCertificateCode() : String`

**Description:** Returns the masked gift certificate code with all but the last 4 characters replaced with a '*' character.

**Returns:**

the masked gift certificate code.

---

### getMaskedGiftCertificateCode

**Signature:** `getMaskedGiftCertificateCode(ignore : Number) : String`

**Description:** Returns the masked gift certificate code with all but the specified number of characters replaced with a '*' character.

**Parameters:**

- `ignore`: the number of characters to leave unmasked.

**Returns:**

the masked gift certificate code.

**Throws:**

IllegalArgumentException - if ignore is negative.

---

### getPaymentMethod

**Signature:** `getPaymentMethod() : String`

**Description:** Returns the identifier of the payment method represented by this payment instrument.

**Returns:**

the identifier of the payment method represented by this payment instrument.

---

### isCreditCardExpired

**Signature:** `isCreditCardExpired() : boolean`

**Description:** Returns true if this payment instrument represents an expired credit card. This check is only logical if the credit card expiration month and year are set. If either of these attributes are not set, then this method always returns false.

**Returns:**

true if this payment instrument represents an expired credit card, false otherwise

---

### isPermanentlyMasked

**Signature:** `isPermanentlyMasked() : boolean`

**Description:** Returns true if the account information for this Payment Instrument has been permanently masked as a result of the data retention security policy for the site or a creditcard tokenization, and false otherwise. When account information is masked only the last 4 digits of the credit card or bank account number are recoverable. The bank account driver's license number and bank routing number are completely masked.

**Returns:**

whether or not the account information has been masked

---

### setBankAccountDriversLicense

**Signature:** `setBankAccountDriversLicense(license : String) : void`

**Description:** Set the driver's license number associated with a bank account payment instrument.

**Parameters:**

- `license`: the bank account holder driver's license.

---

### setBankAccountDriversLicenseStateCode

**Signature:** `setBankAccountDriversLicenseStateCode(stateCode : String) : void`

**Description:** Set the driver's license state code associated with a bank account payment instrument.

**Parameters:**

- `stateCode`: the state in which the bank account driver's license was issued.

---

### setBankAccountHolder

**Signature:** `setBankAccountHolder(holder : String) : void`

**Description:** Set the full name of the holder of a bank account payment instrument.

**Parameters:**

- `holder`: the bank account holder's full name.

---

### setBankAccountNumber

**Signature:** `setBankAccountNumber(accountNumber : String) : void`

**Description:** Set the bank account number of a bank account payment instrument.

**Parameters:**

- `accountNumber`: the bank account number.

---

### setBankRoutingNumber

**Signature:** `setBankRoutingNumber(routingNumber : String) : void`

**Description:** Set the bank routing number of a bank account payment instrument.

**Parameters:**

- `routingNumber`: the bank account rounting number.

---

### setCreditCardExpirationMonth

**Signature:** `setCreditCardExpirationMonth(aValue : Number) : void`

**Description:** Sets the month of the year in which the credit card expires. Permissible values are from 1 to 12.

**Parameters:**

- `aValue`: the month of the year in which the credit card expires. Permissible values are from 1 to 12.

---

### setCreditCardExpirationYear

**Signature:** `setCreditCardExpirationYear(aValue : Number) : void`

**Description:** Sets the year in which the credit card expires, such as '2004'.

**Parameters:**

- `aValue`: the year in which the credit card expires.

---

### setCreditCardHolder

**Signature:** `setCreditCardHolder(aValue : String) : void`

**Description:** Sets the name of the credit card owner.

**Parameters:**

- `aValue`: the name of the credit card owner.

---

### setCreditCardIssueNumber

**Signature:** `setCreditCardIssueNumber(aValue : String) : void`

**Description:** Set the credit card issue number. This attribute is only used by specific credit/debit card processors such as Solo and Switch in the UK.

**Parameters:**

- `aValue`: the credit card issue number

---

### setCreditCardNumber

**Signature:** `setCreditCardNumber(aValue : String) : void`

**Description:** Sets the credit card number for this payment.

**Parameters:**

- `aValue`: the new value of the credit card number.

---

### setCreditCardToken

**Signature:** `setCreditCardToken(token : String) : void`

**Description:** Secure credit card data can be replaced by a token by utilizing a tokenization provider, which securely stores the credit card data using the token as a key. The stored data can later reused by including the token in a request. In this way credit card processes such as authorization and capture can be implemented without being responsible for persisting the credit card data. An Exception will be thrown when the token is null or blank. When setting a credit card token, the account information (including the creditcard number) is masked and all creditcard attributes are frozen and an attempt to change will be result in an exception.

**Parameters:**

- `token`: the token

**See Also:**

isPermanentlyMasked()

---

### setCreditCardType

**Signature:** `setCreditCardType(aValue : String) : void`

**Description:** Sets the type of the credit card.

**Parameters:**

- `aValue`: the type of the credit card.

---

### setCreditCardValidFromMonth

**Signature:** `setCreditCardValidFromMonth(aValue : Number) : void`

**Description:** Sets the month of the year in which the credit card became valid (1-12). This attribute is not used by all credit card types

**Parameters:**

- `aValue`: the month of the year in which the credit card became valid (1-12).

---

### setCreditCardValidFromYear

**Signature:** `setCreditCardValidFromYear(aValue : Number) : void`

**Description:** Sets the year in which the credit card became valid, such as '2001'. This attribute is not used by all credit card types.

**Parameters:**

- `aValue`: the year in which the credit card became valid

---

### setGiftCertificateCode

**Signature:** `setGiftCertificateCode(giftCertificateCode : String) : void`

**Description:** Sets the Gift Certificate code for this Payment Instrument.

**Parameters:**

- `giftCertificateCode`: the Gift Certificate code.

---

### setGiftCertificateID

**Signature:** `setGiftCertificateID(giftCertificateID : String) : void`

**Description:** Sets the Gift Certificate ID for this Payment Instrument.

**Deprecated:**

Use setGiftCertificateCode(String)

**Parameters:**

- `giftCertificateID`: the Gift Certificate ID.

---
```

--------------------------------------------------------------------------------
/docs/dw_order/ProductLineItem.md:
--------------------------------------------------------------------------------

```markdown
## Package: dw.order

# Class ProductLineItem

## Inheritance Hierarchy

- Object
  - dw.object.PersistentObject
  - dw.object.ExtensibleObject
    - dw.order.LineItem
      - dw.order.ProductLineItem

## Description

Represents a specific product line item.

## Properties

### adjustedGrossPrice

**Type:** Money (Read Only)

The gross price of the product line item after applying all product-level
 adjustments.

### adjustedNetPrice

**Type:** Money (Read Only)

The net price of the product line item after applying all product-level
 adjustments.

### adjustedPrice

**Type:** Money (Read Only)

The price of the product line item after applying all product-level
 adjustments. For net pricing the adjusted net price is returned
 (see getAdjustedNetPrice()). For gross pricing, the adjusted
 gross price is returned (see getAdjustedGrossPrice()).

### adjustedTax

**Type:** Money (Read Only)

The tax of the unit after applying adjustments, in the purchase currency.

### bonusDiscountLineItem

**Type:** BonusDiscountLineItem (Read Only)

The parent bonus discount line item of this line item.  Only
 bonus product line items that have been selected by the customer as
 part of a BONUS_CHOICE discount have one of these.

### bonusProductLineItem

**Type:** boolean (Read Only)

Identifies if the product line item represents a bonus line item.

### bundledProductLineItem

**Type:** boolean (Read Only)

Identifies if the product line item represents a bundled line item.

### bundledProductLineItems

**Type:** Collection (Read Only)

A collection containing the bundled product line items.

### catalogProduct

**Type:** LineItemCtnr.createProductLineItem(String, Shipment) (Read Only)

Returns true if the product line item represents a catalog product.
 
 That flag is determined during product line item creation with
 LineItemCtnr.createProductLineItem(String, Shipment), stored at the line item container and can
 be accessed as productLineItem.catalogProduct. It represents what can be evaluated with

  dw.catalog.ProductMgr.getProduct( productID ) != null
     && dw.catalog.ProductMgr.getProduct( productID ).isAssignedToSiteCatalog()
 

 If the product is not available during product line item creation it is considered a non catalog product line item without
 connection to a product.

### category

**Type:** Category

The category the product line item is associated with. If the
 line item is not associated with a category, or the category does not
 exist in the site catalog, the method returns null.

### categoryID

**Type:** String

The ID of the category the product line item is associated with.

### externalLineItemStatus

**Type:** String

The value set for the external line item status
 or null if no value set.

### externalLineItemText

**Type:** String

The value set for the external line item text
 or null if no value set.

### gift

**Type:** boolean

Returns true if this line item represents a gift, false otherwise.

### giftMessage

**Type:** String

The value set for gift message or null if no value set.

### manufacturerName

**Type:** String

The name of the manfacturer of the product.

### manufacturerSKU

**Type:** String

The name of the manfacturer's SKU of this product line item.

### minOrderQuantity

**Type:** Quantity (Read Only)

The minimal order quantity allowed for the product represented by the
 ProductLineItem (copied from product on initialization).
 Note: the quantity of a ProductLineItem must obey the limits set by the
 ProductLineItem's attributes 'MinOrderQuantity' and 'StepQuantity', i.e.
 for a 'MinOrderQuantity' of 2.0 and a 'StepQuantity' of 2.5 then values
 2.0, 4.5, 7.0... are allowed values.

### minOrderQuantityValue

**Type:** Number

Return the value portion of getMinOrderQuantity().

### optionID

**Type:** String (Read Only)

The ID of the product option this product line item
 represents. If the product line item does not represent an option,
 null is returned.

### optionModel

**Type:** ProductOptionModel (Read Only)

The product option model for a product line item representing an option product.
 
 The returned option model has preselected values based on the dependent option line items of this product line
 item. Null is returned if this line item does not represent an option product.

### optionProductLineItem

**Type:** boolean (Read Only)

Identifies if the product line item represents an option line item.
 Option line items do not represent true products but rather options of
 products.  An option line item always has a parent product line item
 representing a true product.

### optionProductLineItems

**Type:** Collection (Read Only)

A collection containing option product line items.

### optionValueID

**Type:** String (Read Only)

The ID of the product option value this product line item
 represents. If the product line item does not represent an option,
 null is returned.

### orderItem

**Type:** OrderItem (Read Only)

The order-item extension for this item, or null. An order-item
 extension will only exist for a ProductLineItem which belongs to an Order.
 
 Order post-processing APIs (gillian) are now inactive by default and will throw
 an exception if accessed. Activation needs preliminary approval by Product Management.
 Please contact support in this case. Existing customers using these APIs are not
 affected by this change and can use the APIs until further notice.

### parent

**Type:** ProductLineItem (Read Only)

The parent line item of this line item or null if the line item
 is independent.

### position

**Type:** Number

The position within the line item container assigned to the ProductLineItem upon its creation, may be
 used as a sort-order.
 
 The position is updated in the following way:
 
 When a ProductLineItem is added to the LineItemCtnr, it is assigned the next available position, based on the
 current count
 When a ProductLineItem is removed from the LineItemCtnr then LineItemCtnr method reassignPositions is called,
 so that the 'gap' left by the removed line-item is refilled. This method is dependent on no 2 ProductLineItem
 having the same position.
 When a LineItemCtnr is copied (e.g. when a PlacedOrder is created from a Basket), no special position
 handling is necessary as the ProductLineItems are added according to their current position ordering in the
 source LineItemCtnr.

### priceAdjustments

**Type:** Collection (Read Only)

An iterator of price adjustments that have been applied to this
 product line item such as promotions on the purchase price
 (i.e. $10 Off or 10% Off).

### product

**Type:** Product (Read Only)

The product associated with the product line item.
 
 The product line item might not be related to an actual catalog product, for example if it represents an option,
 or was not created from a catalog product, or if the product does not exist in the catalog anymore. In these
 cases, the method returns null.

### productID

**Type:** String (Read Only)

The ID of the related product.
 
 Returns empty if no product is related.

### productInventoryList

**Type:** ProductInventoryList

The inventory list the product line item is associated with. If the
 line item is not associated with a inventory list, or the inventory list does not
 exist, the method returns null.

### productInventoryListID

**Type:** String

The ID of the inventory list the product line item is associated with.

### productListItem

**Type:** ProductListItem (Read Only)

The associated ProductListItem.

### productName

**Type:** String

The name of the product that was copied when
 product was added to line item container.

### proratedPrice

**Type:** Money (Read Only)

The price of this product line item after considering all
 dependent price adjustments and prorating all Buy-X-Get-Y
 and order-level discounts, according to the scheme described in
 PriceAdjustment.getProratedPrices(). For net pricing the
 net price is returned. For gross pricing, the gross price is returned.

### proratedPriceAdjustmentPrices

**Type:** Map (Read Only)

A Map of PriceAdjustment to Money instances. They keys to this
 map are the price adjustments that apply to this ProductLineItem either
 directly or indirectly when discounts are prorated according to the
 scheme described in PriceAdjustment.getProratedPrices().
 The values in the map are the portion of the adjustment which applies to
 this particular product line item.

### qualifyingProductLineItemForBonusProduct

**Type:** ProductLineItem (Read Only)

The ProductLineItem that qualified the basket for this bonus product.
 
 This method is only applicable if the product line item is a bonus product line item, and if the promotion is a
 product promotion with number of qualifying products granting a bonus-product discount. If these conditions
 aren't met, the method returns null. If there are multiple product line items that triggered this bonus product,
 this method returns the last one by position within the order.

### quantity

**Type:** Quantity (Read Only)

The quantity of the product represented by this ProductLineItem.

### quantityValue

**Type:** Number

The value of the quantity of this ProductLineItem.

### relatedBonusProductLineItems

**Type:** Collection (Read Only)

All bonus product line items for which this line item is a
 qualifying product line item. This method is usually called when
 rendering the cart so that bonus products can be shown next to the
 products that triggered their creation.

### reserved

**Type:** Basket.reserveInventory(Number) (Read Only)

Returns if the product line item is reserved.
 
 Reservations for the basket can be created with e.g. Basket.reserveInventory(Number).
 
 Method must only be called for basket product line items. Exception is thrown if called for order product line
 item.

### shipment

**Type:** Shipment

The associated Shipment.

### shippingLineItem

**Type:** ProductShippingLineItem (Read Only)

The dependent shipping line item of this line item.
 The shipping line item can define product-specific shipping
 costs for this product line item.

### stepQuantity

**Type:** Quantity (Read Only)

Returns step quantity allowed for the product represented by the ProductLineItem
 (copied from product on initialization).
 Note: the quantity of a ProductLineItem must obey the limits set by the
 ProductLineItem's attributes 'MinOrderQuantity' and 'StepQuantity', i.e.
 for a 'MinOrderQuantity' of 2.0 and a 'StepQuantity' of 2.5 then values
 2.0, 4.5, 7.0... are allowed values.

### stepQuantityValue

**Type:** Number

Return the value portion of getStepQuantity().

## Constructor Summary

## Method Summary

### createPriceAdjustment

**Signature:** `createPriceAdjustment(promotionID : String) : PriceAdjustment`

Creates a product price adjustment.

### createPriceAdjustment

**Signature:** `createPriceAdjustment(promotionID : String, discount : Discount) : PriceAdjustment`

Creates a product price adjustment representing a specific discount.

### createShippingLineItem

**Signature:** `createShippingLineItem() : ProductShippingLineItem`

Creates the dependent shipping line item for this line item.

### getAdjustedGrossPrice

**Signature:** `getAdjustedGrossPrice() : Money`

Returns the gross price of the product line item after applying all product-level adjustments.

### getAdjustedNetPrice

**Signature:** `getAdjustedNetPrice() : Money`

Returns the net price of the product line item after applying all product-level adjustments.

### getAdjustedPrice

**Signature:** `getAdjustedPrice() : Money`

Returns the price of the product line item after applying all product-level adjustments.

### getAdjustedPrice

**Signature:** `getAdjustedPrice(applyOrderLevelAdjustments : boolean) : Money`

Returns the price of this product line item after considering all dependent price adjustments and optionally prorating all order-level price adjustments.

### getAdjustedTax

**Signature:** `getAdjustedTax() : Money`

Returns the tax of the unit after applying adjustments, in the purchase currency.

### getBonusDiscountLineItem

**Signature:** `getBonusDiscountLineItem() : BonusDiscountLineItem`

Returns the parent bonus discount line item of this line item.

### getBundledProductLineItems

**Signature:** `getBundledProductLineItems() : Collection`

Returns a collection containing the bundled product line items.

### getCategory

**Signature:** `getCategory() : Category`

Returns the category the product line item is associated with.

### getCategoryID

**Signature:** `getCategoryID() : String`

Returns the ID of the category the product line item is associated with.

### getExternalLineItemStatus

**Signature:** `getExternalLineItemStatus() : String`

Returns the value set for the external line item status or null if no value set.

### getExternalLineItemText

**Signature:** `getExternalLineItemText() : String`

Returns the value set for the external line item text or null if no value set.

### getGiftMessage

**Signature:** `getGiftMessage() : String`

Returns the value set for gift message or null if no value set.

### getManufacturerName

**Signature:** `getManufacturerName() : String`

Returns the name of the manfacturer of the product.

### getManufacturerSKU

**Signature:** `getManufacturerSKU() : String`

Returns the name of the manfacturer's SKU of this product line item.

### getMinOrderQuantity

**Signature:** `getMinOrderQuantity() : Quantity`

Returns the minimal order quantity allowed for the product represented by the ProductLineItem (copied from product on initialization).

### getMinOrderQuantityValue

**Signature:** `getMinOrderQuantityValue() : Number`

Return the value portion of getMinOrderQuantity().

### getOptionID

**Signature:** `getOptionID() : String`

Returns the ID of the product option this product line item represents.

### getOptionModel

**Signature:** `getOptionModel() : ProductOptionModel`

Returns the product option model for a product line item representing an option product.

### getOptionProductLineItems

**Signature:** `getOptionProductLineItems() : Collection`

Returns a collection containing option product line items.

### getOptionValueID

**Signature:** `getOptionValueID() : String`

Returns the ID of the product option value this product line item represents.

### getOrderItem

**Signature:** `getOrderItem() : OrderItem`

Returns the order-item extension for this item, or null.

### getParent

**Signature:** `getParent() : ProductLineItem`

Returns the parent line item of this line item or null if the line item is independent.

### getPosition

**Signature:** `getPosition() : Number`

Returns the position within the line item container assigned to the ProductLineItem upon its creation, may be used as a sort-order.

### getPriceAdjustmentByPromotionID

**Signature:** `getPriceAdjustmentByPromotionID(promotionID : String) : PriceAdjustment`

Returns the first price adjustment associated to the specified promotion ID.

### getPriceAdjustmentByPromotionIDAndCouponCode

**Signature:** `getPriceAdjustmentByPromotionIDAndCouponCode(promotionID : String, couponCode : String) : PriceAdjustment`

Returns the price adjustment associated to the specified promotion ID and coupon code combination.

### getPriceAdjustments

**Signature:** `getPriceAdjustments() : Collection`

Returns an iterator of price adjustments that have been applied to this product line item such as promotions on the purchase price (i.e.

### getPriceAdjustmentsByPromotionID

**Signature:** `getPriceAdjustmentsByPromotionID(promotionID : String) : Collection`

Returns the collection of price adjustments associated to the specified promotion ID.

### getProduct

**Signature:** `getProduct() : Product`

Returns the product associated with the product line item.

### getProductID

**Signature:** `getProductID() : String`

Returns the ID of the related product.

### getProductInventoryList

**Signature:** `getProductInventoryList() : ProductInventoryList`

Returns the inventory list the product line item is associated with.

### getProductInventoryListID

**Signature:** `getProductInventoryListID() : String`

Returns the ID of the inventory list the product line item is associated with.

### getProductListItem

**Signature:** `getProductListItem() : ProductListItem`

Returns the associated ProductListItem.

### getProductName

**Signature:** `getProductName() : String`

Returns the name of the product that was copied when product was added to line item container.

### getProratedPrice

**Signature:** `getProratedPrice() : Money`

Returns the price of this product line item after considering all dependent price adjustments and prorating all Buy-X-Get-Y and order-level discounts, according to the scheme described in PriceAdjustment.getProratedPrices().

### getProratedPriceAdjustmentPrices

**Signature:** `getProratedPriceAdjustmentPrices() : Map`

Returns a Map of PriceAdjustment to Money instances.

### getQualifyingProductLineItemForBonusProduct

**Signature:** `getQualifyingProductLineItemForBonusProduct() : ProductLineItem`

Returns the ProductLineItem that qualified the basket for this bonus product.

### getQuantity

**Signature:** `getQuantity() : Quantity`

Returns the quantity of the product represented by this ProductLineItem.

### getQuantityValue

**Signature:** `getQuantityValue() : Number`

Returns the value of the quantity of this ProductLineItem.

### getRelatedBonusProductLineItems

**Signature:** `getRelatedBonusProductLineItems() : Collection`

Returns all bonus product line items for which this line item is a qualifying product line item.

### getShipment

**Signature:** `getShipment() : Shipment`

Returns the associated Shipment.

### getShippingLineItem

**Signature:** `getShippingLineItem() : ProductShippingLineItem`

Returns the dependent shipping line item of this line item.

### getStepQuantity

**Signature:** `getStepQuantity() : Quantity`

Returns step quantity allowed for the product represented by the ProductLineItem (copied from product on initialization).

### getStepQuantityValue

**Signature:** `getStepQuantityValue() : Number`

Return the value portion of getStepQuantity().

### isBonusProductLineItem

**Signature:** `isBonusProductLineItem() : boolean`

Identifies if the product line item represents a bonus line item.

### isBundledProductLineItem

**Signature:** `isBundledProductLineItem() : boolean`

Identifies if the product line item represents a bundled line item.

### isCatalogProduct

**Signature:** `isCatalogProduct() : boolean`

Returns true if the product line item represents a catalog product.

### isGift

**Signature:** `isGift() : boolean`

Returns true if this line item represents a gift, false otherwise.

### isOptionProductLineItem

**Signature:** `isOptionProductLineItem() : boolean`

Identifies if the product line item represents an option line item.

### isReserved

**Signature:** `isReserved() : boolean`

Returns if the product line item is reserved.

### removePriceAdjustment

**Signature:** `removePriceAdjustment(priceAdjustmentLineItem : PriceAdjustment) : void`

Removes the specified price adjustment from the product line item.

### removeShippingLineItem

**Signature:** `removeShippingLineItem() : void`

Removes the dependent shipping line item for this line item.

### replaceProduct

**Signature:** `replaceProduct(newProduct : Product) : void`

Replaces the current product of the product line item with the product specified in parameter newProduct.

### setCategory

**Signature:** `setCategory(category : Category) : void`

Sets the specified category as the product line item category context.

### setCategoryID

**Signature:** `setCategoryID(categoryID : String) : void`

Sets the ID of the category the product line item is associated with.

### setExternalLineItemStatus

**Signature:** `setExternalLineItemStatus(status : String) : void`

Sets the value to set for the external line item status.

### setExternalLineItemText

**Signature:** `setExternalLineItemText(text : String) : void`

Sets the value to set for the external line item text.

### setGift

**Signature:** `setGift(isGift : boolean) : void`

Controls if this line item is a gift or not.

### setGiftMessage

**Signature:** `setGiftMessage(message : String) : void`

Sets the value to set for the gift message.

### setManufacturerName

**Signature:** `setManufacturerName(name : String) : void`

Sets the name of the manufacturer of this product.

### setManufacturerSKU

**Signature:** `setManufacturerSKU(sku : String) : void`

Sets the SKU of the manufacturer of this product.

### setMinOrderQuantityValue

**Signature:** `setMinOrderQuantityValue(quantityValue : Number) : void`

Set the minimum order quantity value for this object.

### setPosition

**Signature:** `setPosition(aValue : Number) : void`

Sets the position within the line item container.

### setPriceValue

**Signature:** `setPriceValue(value : Number) : void`

Sets price attributes of the line item based on the current purchase currency, taxation policy and line item quantity.

### setProductInventoryList

**Signature:** `setProductInventoryList(productInventoryList : ProductInventoryList) : void`

Sets the specified inventory list as the product line item inventory context.

### setProductInventoryListID

**Signature:** `setProductInventoryListID(productInventoryListID : String) : void`

Sets the ID of the inventory list the product line item is associated with.

### setProductName

**Signature:** `setProductName(aValue : String) : void`

Sets the name of the product.

### setQuantityValue

**Signature:** `setQuantityValue(quantityValue : Number) : void`

Updates the quantity value of the product line item.

### setShipment

**Signature:** `setShipment(shipment : Shipment) : void`

Associates the specified product line item with the specified shipment.

### setStepQuantityValue

**Signature:** `setStepQuantityValue(quantityValue : Number) : void`

Set the step quantity value for this object.

### updateOptionPrice

**Signature:** `updateOptionPrice() : void`

Determines and sets the price of a option line item based on the selected option value this line item represents.

### updateOptionValue

**Signature:** `updateOptionValue(optionValue : ProductOptionValue) : void`

Updates an option line item with a new option value.

### updatePrice

**Signature:** `updatePrice(price : Money) : void`

Updates the price attributes of the line item based on the specified price.

### updateQuantity

**Signature:** `updateQuantity(quantityValue : Number) : Number`

Updates the quantity value of the product line item and all its dependent product line items.

## Method Detail

## Method Details

### createPriceAdjustment

**Signature:** `createPriceAdjustment(promotionID : String) : PriceAdjustment`

**Description:** Creates a product price adjustment. The price adjustment line item is being initialized with the tax class code and tax rate of the product line item. The promotion ID is mandatory and must not be the ID of any actual promotion defined in B2C Commerce. If there already exists a price adjustment for the same promotionID, an exception is thrown.

**Parameters:**

- `promotionID`: Promotion ID

**Returns:**

The new price adjustment

---

### createPriceAdjustment

**Signature:** `createPriceAdjustment(promotionID : String, discount : Discount) : PriceAdjustment`

**Description:** Creates a product price adjustment representing a specific discount. The price adjustment line item is initialized with the tax class code and tax rate of the product line item. The promotion ID is mandatory and must not be the ID of any actual promotion defined in B2C Commerce. If a price adjustment already exists for the same promotionID, an exception is thrown. The possible discounts are FixedPriceDiscount, AmountDiscount, PercentageDiscount. Example: var myProductItem : dw.order.ProductLineItem; // assume known var paFixedUnitPrice100 : dw.order.PriceAdjustment = myProductItem.createPriceAdjustment("myPromotionID1", new FixedPriceDiscount(100.00)); var paTenPercent : dw.order.PriceAdjustment = myProductItem.createPriceAdjustment("myPromotionID2", new PercentageDiscount(10)); var paReduceBy20 : dw.order.PriceAdjustment = myProductItem.createPriceAdjustment("myPromotionID3", new AmountDiscount(20.00);

**Parameters:**

- `promotionID`: Unique custom promotion ID, not null
- `discount`: The desired discount, not null

**Returns:**

The new custom price adjustment

---

### createShippingLineItem

**Signature:** `createShippingLineItem() : ProductShippingLineItem`

**Description:** Creates the dependent shipping line item for this line item. The shipping line item can define product-specific shipping costs for this product line item. This method has replace semantics: If there is an existing shipping line item it will be replaced with a new shipping line item.

**Returns:**

the created shipping line item

---

### getAdjustedGrossPrice

**Signature:** `getAdjustedGrossPrice() : Money`

**Description:** Returns the gross price of the product line item after applying all product-level adjustments.

**Returns:**

gross price after applying product-level adjustments

**See Also:**

getAdjustedNetPrice()
getAdjustedPrice()

---

### getAdjustedNetPrice

**Signature:** `getAdjustedNetPrice() : Money`

**Description:** Returns the net price of the product line item after applying all product-level adjustments.

**Returns:**

net price after applying product-level adjustments

**See Also:**

getAdjustedGrossPrice()
getAdjustedPrice()

---

### getAdjustedPrice

**Signature:** `getAdjustedPrice() : Money`

**Description:** Returns the price of the product line item after applying all product-level adjustments. For net pricing the adjusted net price is returned (see getAdjustedNetPrice()). For gross pricing, the adjusted gross price is returned (see getAdjustedGrossPrice()).

**Returns:**

Adjusted net or gross price

**See Also:**

getAdjustedGrossPrice()
getAdjustedNetPrice()

---

### getAdjustedPrice

**Signature:** `getAdjustedPrice(applyOrderLevelAdjustments : boolean) : Money`

**Description:** Returns the price of this product line item after considering all dependent price adjustments and optionally prorating all order-level price adjustments. For net pricing the net price is returned. For gross pricing, the gross price is returned.

**Parameters:**

- `applyOrderLevelAdjustments`: If true, order-level adjustments will be applied to line item price.

**Returns:**

Adjusted net or gross price

**See Also:**

getAdjustedPrice()

---

### getAdjustedTax

**Signature:** `getAdjustedTax() : Money`

**Description:** Returns the tax of the unit after applying adjustments, in the purchase currency.

**Returns:**

the tax of the unit after applying adjustments, in the purchase currency.

---

### getBonusDiscountLineItem

**Signature:** `getBonusDiscountLineItem() : BonusDiscountLineItem`

**Description:** Returns the parent bonus discount line item of this line item. Only bonus product line items that have been selected by the customer as part of a BONUS_CHOICE discount have one of these.

**Returns:**

the bonus discount line item of this line item or null

---

### getBundledProductLineItems

**Signature:** `getBundledProductLineItems() : Collection`

**Description:** Returns a collection containing the bundled product line items.

**Returns:**

a collection containing the bundled product line items.

---

### getCategory

**Signature:** `getCategory() : Category`

**Description:** Returns the category the product line item is associated with. If the line item is not associated with a category, or the category does not exist in the site catalog, the method returns null.

**Returns:**

Category or null

---

### getCategoryID

**Signature:** `getCategoryID() : String`

**Description:** Returns the ID of the category the product line item is associated with.

**Returns:**

Category ID or null.

---

### getExternalLineItemStatus

**Signature:** `getExternalLineItemStatus() : String`

**Description:** Returns the value set for the external line item status or null if no value set.

**Returns:**

the value set for the external line item status or null if no value set.

---

### getExternalLineItemText

**Signature:** `getExternalLineItemText() : String`

**Description:** Returns the value set for the external line item text or null if no value set.

**Returns:**

the value set for the external line item text or null if no value set.

---

### getGiftMessage

**Signature:** `getGiftMessage() : String`

**Description:** Returns the value set for gift message or null if no value set.

**Returns:**

the value set for gift message or null if no value set.

---

### getManufacturerName

**Signature:** `getManufacturerName() : String`

**Description:** Returns the name of the manfacturer of the product.

**Returns:**

The name of the manfacturer of the product.

---

### getManufacturerSKU

**Signature:** `getManufacturerSKU() : String`

**Description:** Returns the name of the manfacturer's SKU of this product line item.

**Returns:**

the name of the manfacturer's SKU of this product line item.

---

### getMinOrderQuantity

**Signature:** `getMinOrderQuantity() : Quantity`

**Description:** Returns the minimal order quantity allowed for the product represented by the ProductLineItem (copied from product on initialization). Note: the quantity of a ProductLineItem must obey the limits set by the ProductLineItem's attributes 'MinOrderQuantity' and 'StepQuantity', i.e. for a 'MinOrderQuantity' of 2.0 and a 'StepQuantity' of 2.5 then values 2.0, 4.5, 7.0... are allowed values.

**Returns:**

the minimal order quantity allowed for the product.

---

### getMinOrderQuantityValue

**Signature:** `getMinOrderQuantityValue() : Number`

**Description:** Return the value portion of getMinOrderQuantity().

**Returns:**

the minimal order quantity value allowed for the product.

---

### getOptionID

**Signature:** `getOptionID() : String`

**Description:** Returns the ID of the product option this product line item represents. If the product line item does not represent an option, null is returned.

**Returns:**

the ID of the product option this product line item represents.

---

### getOptionModel

**Signature:** `getOptionModel() : ProductOptionModel`

**Description:** Returns the product option model for a product line item representing an option product. The returned option model has preselected values based on the dependent option line items of this product line item. Null is returned if this line item does not represent an option product.

**Returns:**

the product option model for a product line item representing an option product.

---

### getOptionProductLineItems

**Signature:** `getOptionProductLineItems() : Collection`

**Description:** Returns a collection containing option product line items.

**Returns:**

a collection containing option product line items.

---

### getOptionValueID

**Signature:** `getOptionValueID() : String`

**Description:** Returns the ID of the product option value this product line item represents. If the product line item does not represent an option, null is returned.

**Returns:**

the ID of the product option value this product line item represents.

---

### getOrderItem

**Signature:** `getOrderItem() : OrderItem`

**Description:** Returns the order-item extension for this item, or null. An order-item extension will only exist for a ProductLineItem which belongs to an Order. Order post-processing APIs (gillian) are now inactive by default and will throw an exception if accessed. Activation needs preliminary approval by Product Management. Please contact support in this case. Existing customers using these APIs are not affected by this change and can use the APIs until further notice.

**Returns:**

null or the order-item extension

---

### getParent

**Signature:** `getParent() : ProductLineItem`

**Description:** Returns the parent line item of this line item or null if the line item is independent.

**Returns:**

the parent line item of this line item or null if the line item is independent.

---

### getPosition

**Signature:** `getPosition() : Number`

**Description:** Returns the position within the line item container assigned to the ProductLineItem upon its creation, may be used as a sort-order. The position is updated in the following way: When a ProductLineItem is added to the LineItemCtnr, it is assigned the next available position, based on the current count When a ProductLineItem is removed from the LineItemCtnr then LineItemCtnr method reassignPositions is called, so that the 'gap' left by the removed line-item is refilled. This method is dependent on no 2 ProductLineItem having the same position. When a LineItemCtnr is copied (e.g. when a PlacedOrder is created from a Basket), no special position handling is necessary as the ProductLineItems are added according to their current position ordering in the source LineItemCtnr.

**Returns:**

the position within the line item container assigned to the ProductLineItem upon its creation.

---

### getPriceAdjustmentByPromotionID

**Signature:** `getPriceAdjustmentByPromotionID(promotionID : String) : PriceAdjustment`

**Description:** Returns the first price adjustment associated to the specified promotion ID. It is highly recommended to use getPriceAdjustmentsByPromotionID(String) instead. If there are multiple price adjustments for the same promotion, this method will return the first found. Alternatively, to uniquely identify a price adjustment using its promotion id and coupon code, use getPriceAdjustmentByPromotionIDAndCouponCode(String, String)

**Parameters:**

- `promotionID`: Promotion id

**Returns:**

The price adjustment associated with the promotion ID or null

---

### getPriceAdjustmentByPromotionIDAndCouponCode

**Signature:** `getPriceAdjustmentByPromotionIDAndCouponCode(promotionID : String, couponCode : String) : PriceAdjustment`

**Description:** Returns the price adjustment associated to the specified promotion ID and coupon code combination.

**Parameters:**

- `promotionID`: Promotion id
- `couponCode`: the code of the coupon used to apply the promotion, or null if the promotion is not coupon based.

**Returns:**

The price adjustment associated with the promotion ID and coupon code combination, or null

---

### getPriceAdjustments

**Signature:** `getPriceAdjustments() : Collection`

**Description:** Returns an iterator of price adjustments that have been applied to this product line item such as promotions on the purchase price (i.e. $10 Off or 10% Off).

**Returns:**

a collection of price adjustments that have been applied to this product line item.

---

### getPriceAdjustmentsByPromotionID

**Signature:** `getPriceAdjustmentsByPromotionID(promotionID : String) : Collection`

**Description:** Returns the collection of price adjustments associated to the specified promotion ID. If only one coupon code is allowed per order, then the collection should only ever have a single entry in it. The multiple coupon code feature can cause multiple price adjustments to be returned.

**Parameters:**

- `promotionID`: Promotion id

**Returns:**

The collection of price adjustments associated with the promotion ID or null if the promotionID was null. If there are no price adjustments for the passed promotion, the collection will be empty.

---

### getProduct

**Signature:** `getProduct() : Product`

**Description:** Returns the product associated with the product line item. The product line item might not be related to an actual catalog product, for example if it represents an option, or was not created from a catalog product, or if the product does not exist in the catalog anymore. In these cases, the method returns null.

**Returns:**

the product of the line item, or null

**See Also:**

isCatalogProduct()

---

### getProductID

**Signature:** `getProductID() : String`

**Description:** Returns the ID of the related product. Returns empty if no product is related.

**Returns:**

the ID of the related product.

**See Also:**

isCatalogProduct()
getProduct()

---

### getProductInventoryList

**Signature:** `getProductInventoryList() : ProductInventoryList`

**Description:** Returns the inventory list the product line item is associated with. If the line item is not associated with a inventory list, or the inventory list does not exist, the method returns null.

**Returns:**

ProductInventoryList or null

---

### getProductInventoryListID

**Signature:** `getProductInventoryListID() : String`

**Description:** Returns the ID of the inventory list the product line item is associated with.

**Returns:**

ProductInventoryList ID or null.

---

### getProductListItem

**Signature:** `getProductListItem() : ProductListItem`

**Description:** Returns the associated ProductListItem.

**Returns:**

item or null.

---

### getProductName

**Signature:** `getProductName() : String`

**Description:** Returns the name of the product that was copied when product was added to line item container.

**Returns:**

the name of the product.

---

### getProratedPrice

**Signature:** `getProratedPrice() : Money`

**Description:** Returns the price of this product line item after considering all dependent price adjustments and prorating all Buy-X-Get-Y and order-level discounts, according to the scheme described in PriceAdjustment.getProratedPrices(). For net pricing the net price is returned. For gross pricing, the gross price is returned.

**Returns:**

Adjusted and prorated net or gross price

---

### getProratedPriceAdjustmentPrices

**Signature:** `getProratedPriceAdjustmentPrices() : Map`

**Description:** Returns a Map of PriceAdjustment to Money instances. They keys to this map are the price adjustments that apply to this ProductLineItem either directly or indirectly when discounts are prorated according to the scheme described in PriceAdjustment.getProratedPrices(). The values in the map are the portion of the adjustment which applies to this particular product line item.

**Returns:**

Map of PriceAdjustment to Money instances, representing the prorated adjustments applied to this ProductLineItem.

---

### getQualifyingProductLineItemForBonusProduct

**Signature:** `getQualifyingProductLineItemForBonusProduct() : ProductLineItem`

**Description:** Returns the ProductLineItem that qualified the basket for this bonus product. This method is only applicable if the product line item is a bonus product line item, and if the promotion is a product promotion with number of qualifying products granting a bonus-product discount. If these conditions aren't met, the method returns null. If there are multiple product line items that triggered this bonus product, this method returns the last one by position within the order.

**Returns:**

the ProductLineItem that qualified the basket for this bonus product. Returns null if this is not a bonus product, or if there was no distinct qualifying product.

---

### getQuantity

**Signature:** `getQuantity() : Quantity`

**Description:** Returns the quantity of the product represented by this ProductLineItem.

**Returns:**

the quantity of the product.

---

### getQuantityValue

**Signature:** `getQuantityValue() : Number`

**Description:** Returns the value of the quantity of this ProductLineItem.

**Returns:**

quantity value of product line item

---

### getRelatedBonusProductLineItems

**Signature:** `getRelatedBonusProductLineItems() : Collection`

**Description:** Returns all bonus product line items for which this line item is a qualifying product line item. This method is usually called when rendering the cart so that bonus products can be shown next to the products that triggered their creation.

**Returns:**

the bonus product line items triggered by the addition of this product to the cart.

---

### getShipment

**Signature:** `getShipment() : Shipment`

**Description:** Returns the associated Shipment.

**Returns:**

The shipment of the product line item

---

### getShippingLineItem

**Signature:** `getShippingLineItem() : ProductShippingLineItem`

**Description:** Returns the dependent shipping line item of this line item. The shipping line item can define product-specific shipping costs for this product line item.

**Returns:**

the shipping line item of this line item or null

---

### getStepQuantity

**Signature:** `getStepQuantity() : Quantity`

**Description:** Returns step quantity allowed for the product represented by the ProductLineItem (copied from product on initialization). Note: the quantity of a ProductLineItem must obey the limits set by the ProductLineItem's attributes 'MinOrderQuantity' and 'StepQuantity', i.e. for a 'MinOrderQuantity' of 2.0 and a 'StepQuantity' of 2.5 then values 2.0, 4.5, 7.0... are allowed values.

**Returns:**

step quantity allowed for the product.

---

### getStepQuantityValue

**Signature:** `getStepQuantityValue() : Number`

**Description:** Return the value portion of getStepQuantity().

**Returns:**

step quantity value allowed for the product.

---

### isBonusProductLineItem

**Signature:** `isBonusProductLineItem() : boolean`

**Description:** Identifies if the product line item represents a bonus line item.

**Returns:**

true if the product line item represents a bonus line item, false otherwise.

---

### isBundledProductLineItem

**Signature:** `isBundledProductLineItem() : boolean`

**Description:** Identifies if the product line item represents a bundled line item.

**Returns:**

true if the product line item represents a bundled line item.

---

### isCatalogProduct

**Signature:** `isCatalogProduct() : boolean`

**Description:** Returns true if the product line item represents a catalog product. That flag is determined during product line item creation with LineItemCtnr.createProductLineItem(String, Shipment), stored at the line item container and can be accessed as productLineItem.catalogProduct. It represents what can be evaluated with dw.catalog.ProductMgr.getProduct( productID ) != null && dw.catalog.ProductMgr.getProduct( productID ).isAssignedToSiteCatalog() If the product is not available during product line item creation it is considered a non catalog product line item without connection to a product.

**Returns:**

true if product line item represents catalog product, otherwise false

**See Also:**

getProduct()

---

### isGift

**Signature:** `isGift() : boolean`

**Description:** Returns true if this line item represents a gift, false otherwise.

**Returns:**

true if this line item represents a gift, false otherwise.

---

### isOptionProductLineItem

**Signature:** `isOptionProductLineItem() : boolean`

**Description:** Identifies if the product line item represents an option line item. Option line items do not represent true products but rather options of products. An option line item always has a parent product line item representing a true product.

**Returns:**

true if the product line item represents an option line item, false otherwise.

---

### isReserved

**Signature:** `isReserved() : boolean`

**Description:** Returns if the product line item is reserved. Reservations for the basket can be created with e.g. Basket.reserveInventory(Number). Method must only be called for basket product line items. Exception is thrown if called for order product line item.

**Returns:**

true if line item is reserved, false otherwise.

---

### removePriceAdjustment

**Signature:** `removePriceAdjustment(priceAdjustmentLineItem : PriceAdjustment) : void`

**Description:** Removes the specified price adjustment from the product line item.

**Parameters:**

- `priceAdjustmentLineItem`: The price adjustment to remove

---

### removeShippingLineItem

**Signature:** `removeShippingLineItem() : void`

**Description:** Removes the dependent shipping line item for this line item.

---

### replaceProduct

**Signature:** `replaceProduct(newProduct : Product) : void`

**Description:** Replaces the current product of the product line item with the product specified in parameter newProduct. The following rules apply: Preserve line item attributes UUID, Quantity, CategoryID, ExternalLineItemStatus, ExternalLineItemText, isGift, GiftMessage, Position, Parent, Shipment Replace product-specific attributes ProductID, ProductName, MinOrderQuantity, StepQuantity, ManufacturerName, ManufacturerSKU Remove all price adjustments related to the product line item Remove the shipping line item related to the product line item Remove all bundled line items of current product, and add bundled line items if new product is a bundle Remove all option line items of current product, and add option line items if new product is an option product; use default option selections Set all price attributes to N/A Preserve all custom attributes of line item, but override order-required attributes with values from new product The primary use is to replace one variation product with another, without having to both create a new line item for the replacement and remove the line item for the replaced product.

**Parameters:**

- `newProduct`: The new product of the product line item

---

### setCategory

**Signature:** `setCategory(category : Category) : void`

**Description:** Sets the specified category as the product line item category context.

**Parameters:**

- `category`: Category instance or null

---

### setCategoryID

**Signature:** `setCategoryID(categoryID : String) : void`

**Description:** Sets the ID of the category the product line item is associated with.

**Parameters:**

- `categoryID`: the Category ID or null.

---

### setExternalLineItemStatus

**Signature:** `setExternalLineItemStatus(status : String) : void`

**Description:** Sets the value to set for the external line item status.

**Parameters:**

- `status`: the value to set for the external line item status.

---

### setExternalLineItemText

**Signature:** `setExternalLineItemText(text : String) : void`

**Description:** Sets the value to set for the external line item text.

**Parameters:**

- `text`: the value to set for the external line item text.

---

### setGift

**Signature:** `setGift(isGift : boolean) : void`

**Description:** Controls if this line item is a gift or not.

**Parameters:**

- `isGift`: set to true if you want this line item to represent a gift.

---

### setGiftMessage

**Signature:** `setGiftMessage(message : String) : void`

**Description:** Sets the value to set for the gift message.

**Parameters:**

- `message`: the value to set for the gift message.

---

### setManufacturerName

**Signature:** `setManufacturerName(name : String) : void`

**Description:** Sets the name of the manufacturer of this product.

**Parameters:**

- `name`: The name of the manfacturer of this product

---

### setManufacturerSKU

**Signature:** `setManufacturerSKU(sku : String) : void`

**Description:** Sets the SKU of the manufacturer of this product.

**Parameters:**

- `sku`: The SKU of the manfacturer of this product

---

### setMinOrderQuantityValue

**Signature:** `setMinOrderQuantityValue(quantityValue : Number) : void`

**Description:** Set the minimum order quantity value for this object. This will be used to validate and adjust quantities when setQuantityValue() is called. For typical catalog product line items, it is usually desirable to have this value inherited from the product attributes, but for non-catalog products, it is sometimes desirable to set this value programmatically. Null is accepted and represents Quantity.NA. Otherwise, the quantity value must be > 0.

**Parameters:**

- `quantityValue`: The minimal order quantity allowed for the product or null.

---

### setPosition

**Signature:** `setPosition(aValue : Number) : void`

**Description:** Sets the position within the line item container. This value may be used as a sort-order. The position is updated in the following way: When a ProductLineItem is added to the LineItemCtnr, it is assigned the next available position, based on the current count When a ProductLineItem is removed from the LineItemCtnr then LineItemCtnr method reassignPositions is called, so that the 'gap' left by the removed line-item is refilled. This method is dependent on no 2 ProductLineItem having the same position. When a LineItemCtnr is copied (e.g. when an Order is created from a Basket), no special position handling is necessary as the ProductLineItems are added according to their current position ordering in the source LineItemCtnr.

**Parameters:**

- `aValue`: the position within the line item container.

---

### setPriceValue

**Signature:** `setPriceValue(value : Number) : void`

**Description:** Sets price attributes of the line item based on the current purchase currency, taxation policy and line item quantity. The method sets the 'basePrice' attribute of the line item. Additionally, it sets the 'netPrice' attribute of the line item if the current taxation policy is 'net', and the 'grossPrice' attribute, if the current taxation policy is 'gross'. The 'netPrice'/'grossPrice' attributes are set by multiplying the specified price value with the line item quantity. If null is specified as value, the price attributes are reset to Money.NA.

**Parameters:**

- `value`: Price value or null

---

### setProductInventoryList

**Signature:** `setProductInventoryList(productInventoryList : ProductInventoryList) : void`

**Description:** Sets the specified inventory list as the product line item inventory context.

**Parameters:**

- `productInventoryList`: ProductInventoryList instance or null

---

### setProductInventoryListID

**Signature:** `setProductInventoryListID(productInventoryListID : String) : void`

**Description:** Sets the ID of the inventory list the product line item is associated with.

**Parameters:**

- `productInventoryListID`: the ProductInventoryList ID or null.

---

### setProductName

**Signature:** `setProductName(aValue : String) : void`

**Description:** Sets the name of the product.

**Parameters:**

- `aValue`: the name of the product.

---

### setQuantityValue

**Signature:** `setQuantityValue(quantityValue : Number) : void`

**Description:** Updates the quantity value of the product line item. Validates the specified quantity value against the line item's min order and step quantity and adjusts it if necessary. In particular, if 0 is passed, then the value will be adjusted to the min order quantity, not removed from the line item container. Null values or values < 0.0 are not accepted.

**Parameters:**

- `quantityValue`: Quantity value.

---

### setShipment

**Signature:** `setShipment(shipment : Shipment) : void`

**Description:** Associates the specified product line item with the specified shipment. The method is only applicable for independent product line items. If called for any dependent line item (option or bundled line item), the method will throw an exception. The shipment for all dependent line items will be updated automatically by the method. Product line item and shipment must belong to the same line item ctnr.

**Parameters:**

- `shipment`: The new shipment of the product line item

---

### setStepQuantityValue

**Signature:** `setStepQuantityValue(quantityValue : Number) : void`

**Description:** Set the step quantity value for this object. This will be used to validate and adjust quantities when updateQuantity() is called. For typical catalog product line items, it is usually desirable to have this value inherited from the product attributes, but for non-catalog products, it is sometimes desirable to set this value programmatically. Null is accepted and represents Quantity.NA. Otherwise, the quantity value must be > 0.

**Parameters:**

- `quantityValue`: The minimal order quantity allowed for the product or null.

---

### updateOptionPrice

**Signature:** `updateOptionPrice() : void`

**Description:** Determines and sets the price of a option line item based on the selected option value this line item represents.

---

### updateOptionValue

**Signature:** `updateOptionValue(optionValue : ProductOptionValue) : void`

**Description:** Updates an option line item with a new option value. This method will not do anything if the current line item is no option line item, if the specified value does not exist for the current option or if this value is already selected. Note, that this method will update the attributes optionValueID, productID, productName and lineItemText. It will not update the price attributes of the line item. To update the price of the line item you need to call updateOptionPrice() in addition. This is usually done during calculation in the calculate hook.

**Parameters:**

- `optionValue`: The value to update the option line item with

---

### updatePrice

**Signature:** `updatePrice(price : Money) : void`

**Description:** Updates the price attributes of the line item based on the specified price. The base price is set to the specified value. If the line item is based on net pricing then the net price attribute is set. If the line item is based on gross pricing then the gross price attribute is set. Whether or not a line item is based on net or gross pricing is a site-wide configuration parameter. In either case, this price is equal to the product of the base price and the quantity of this line item in its container.

**Deprecated:**

Use setPriceValue(Number)

**Parameters:**

- `price`: The price to use when performing the update. This price must not be null and must either be equal to NOT_AVAIALBLE or must have a currency code equal to that of the parent container.

---

### updateQuantity

**Signature:** `updateQuantity(quantityValue : Number) : Number`

**Description:** Updates the quantity value of the product line item and all its dependent product line items. Validates the specified quantity value against the line item's min order and step quantity and adjusts it if necessary. The adjusted quantity value is returned. In general, quantity values < 0.0 are not accepted.

**Deprecated:**

Use setQuantityValue(Number) followed by getQuantity() instead.

**Parameters:**

- `quantityValue`: Numeric quantity value.

**Returns:**

Adjusted quantity value

---
```

--------------------------------------------------------------------------------
/docs/best-practices/sfra_controllers.md:
--------------------------------------------------------------------------------

```markdown
# Salesforce B2C Commerce SFRA Controllers: Best Practices & Examples

This guide provides a condensed overview of best practices and code patterns for developing controllers within the Salesforce B2C Commerce Storefront Reference Architecture (SFRA).

**IMPORTANT**: Before developing SFRA controllers, consult the **Performance and Stability Best Practices** guide from this MCP server. Review the storefront development guidelines, index-friendly APIs, and critical page performance requirements to ensure your controllers follow SFCC performance standards and avoid database-intensive operations.

## 🚀 Enhanced SFRA Documentation Access

This MCP server provides comprehensive access to SFRA documentation through enhanced tools that can help you understand SFRA architecture and develop better controllers:

### **Essential SFRA Documentation Tools**

1. **`get_sfra_categories`** - Discover all available SFRA documentation categories
2. **`get_sfra_documents_by_category`** - Explore documents by functional area (core, product, order, customer, pricing, store)
3. **`get_sfra_document`** - Get detailed information about specific SFRA classes or models
4. **`search_sfra_documentation`** - Find specific functionality across all SFRA documentation

### **Recommended Documentation Workflow for Controller Development**

Before writing SFRA controllers, use these tools to understand the available functionality:

```javascript
// 1. Explore core SFRA classes essential for controllers
get_sfra_documents_by_category("core")
// Returns: server, request, response, querystring, render

// 2. Get detailed Server class documentation
get_sfra_document("server") 
// Comprehensive server.js documentation with middleware patterns

// 3. Understand Request and Response objects
get_sfra_document("request")
get_sfra_document("response")

// 4. For product controllers, explore product models
get_sfra_documents_by_category("product")
// Returns: product-full, product-bundle, product-tile, product-search, product-line-items

// 5. For cart/checkout controllers, explore order models  
get_sfra_documents_by_category("order")
// Returns: cart, order, billing, shipping, payment, totals

// 6. Search for specific functionality
search_sfra_documentation("middleware")
search_sfra_documentation("validation")
```

### **SFRA Model Documentation for Controller Development**

The enhanced documentation system provides access to comprehensive model documentation that's essential for controller development:

- **Product Models**: `product-full`, `product-bundle`, `product-tile` - Understanding product data structures
- **Cart Models**: `cart`, `billing`, `shipping`, `payment`, `totals` - Essential for checkout controllers  
- **Customer Models**: `account`, `address` - For customer management controllers
- **Pricing Models**: `price-default`, `price-range`, `price-tiered` - For pricing logic in controllers

Always consult the relevant model documentation before implementing controller logic to understand available properties and methods.

## Core Concepts

### MVC Pattern & Cartridge Path

SFRA uses a Model-View-Controller (MVC) pattern to enforce separation of concerns.

- **Controller** (`/controllers`): Handles user requests, calls models for data, and determines which view to render.
- **Model** (`/models`): Contains business logic, interacts with the B2C Commerce Script API, and returns pure JSON objects to the controller.
- **View** (`/templates`): ISML templates responsible only for rendering data (pdict) provided by the controller. Business logic in templates is an anti-pattern.

**Cartridge Path**: A colon-separated list of cartridges that dictates the code execution order. Custom cartridges must be placed before the `app_storefront_base` cartridge to override or extend functionality.

> **Never edit the `app_storefront_base` cartridge directly.**

## Routing & Middleware

SFRA's routing is inspired by Express.js, using a chain of middleware functions to process requests.

- **Endpoint Syntax**: URLs map to Controller-RouteName (e.g., `Home-Show` maps to the `Show` route in `Home.js`).
- **server Object**: The core of routing, required in every controller (`var server = require('server');`). It provides methods like `get`, `post`, `append`, etc., to define and modify routes.

### Storefront URL Patterns

SFRA storefront URLs follow a predictable pattern that maps directly to your controller and route structure:

```
https://{instance-hostname}/on/demandware.store/Sites-{site-id}-Site/{locale}/{Controller-Route}
```

**URL Components:**
- **Instance Hostname**: Your SFCC instance domain (e.g., `your-instance.dx.commercecloud.salesforce.com`)
- **Site ID**: The site identifier configured in Business Manager (e.g., `RefArchGlobal`)
- **Locale**: Language and region code, format depends on site configuration
- **Controller-Route**: Maps to your controller file and route method

#### URL Examples

**Standard locale in path:**
```
https://your-instance.dx.commercecloud.salesforce.com/on/demandware.store/Sites-RefArchGlobal-Site/en_GB/Home-Show
https://your-instance.dx.commercecloud.salesforce.com/on/demandware.store/Sites-RefArchGlobal-Site/en_US/Product-Show?pid=12345
https://your-instance.dx.commercecloud.salesforce.com/on/demandware.store/Sites-RefArchGlobal-Site/fr_FR/Account-Login
```

**Locale as query parameter (alternative configuration):**
```
https://your-instance.dx.commercecloud.salesforce.com/on/demandware.store/Sites-RefArchGlobal-Site/Home-Show?lang=en_GB
https://your-instance.dx.commercecloud.salesforce.com/on/demandware.store/Sites-RefArchGlobal-Site/jsPDF-Test?lang=en_GB
```

#### Controller Mapping Examples

| URL | Controller File | Route Method |
|-----|----------------|--------------|
| `/Home-Show` | `controllers/Home.js` | `server.get('Show', ...)` |
| `/Product-Show` | `controllers/Product.js` | `server.get('Show', ...)` |
| `/Cart-AddProduct` | `controllers/Cart.js` | `server.post('AddProduct', ...)` |
| `/Account-Login` | `controllers/Account.js` | `server.get('Login', ...)` |
| `/CheckoutServices-SubmitPayment` | `controllers/CheckoutServices.js` | `server.post('SubmitPayment', ...)` |

**Important Notes:**
- The locale format (`en_GB` in path vs `?lang=en_GB` parameter) depends on your site's locale configuration in Business Manager
- Custom controllers follow the same pattern: if you create `controllers/MyCustom.js` with route `Test`, it's accessible at `/MyCustom-Test`
- Route names are case-sensitive and must match exactly what you define in your controller

### Middleware Chain (req, res, next)

Each route is a series of functions:

- **req**: The request object, containing query strings (`req.querystring`), form data (`req.form`), etc.
- **res**: The response object, used to render templates (`res.render()`), return JSON (`res.json()`), or modify view data (`res.setViewData()`).
- **next()**: A callback that passes control to the next function in the chain. It must be called to avoid a request timeout, unless the function terminates the request (e.g., with `res.render()`).

## Controller Extension APIs

The primary goal is to customize functionality without modifying base code. Always start by importing the base controller: `var page = module.superModule;`.

| Method | Use Case | Description |
|--------|----------|-------------|
| `server.append()` | **Most Common**. Add or modify data for the view after base logic runs. | Adds middleware to the end of the route's chain. Ideal for using `res.getViewData()` to get base data, modifying it, and using `res.setViewData()` to pass it to the template. |
| `server.prepend()` | Perform validation or setup before base logic runs. | Adds middleware to the beginning of the route's chain. Useful for permission checks or preparing data the base controller needs. |
| `server.replace()` | Fundamentally change a route's behavior or prevent base logic from running. | Discards the original middleware chain and replaces it with a new one. Use this for state-changing actions like payment calls to avoid double execution. |

> **Critical Rule**: Never use `server.append` for routes that perform state-changing actions (e.g., payment authorizations, inventory updates). The base logic will execute first, and your appended logic will run second, potentially causing duplicate transactions. Use `server.replace` for these scenarios.

## Built-in SFRA Middlewares

SFRA provides several pre-built middleware functions in `app_storefront_base/cartridge/scripts/middleware/` that handle common functionality. These middlewares follow the standard `(req, res, next)` pattern and can be chained together.

### Cache Middlewares (`cache.js`)

These middlewares set appropriate cache headers for different types of content:

#### `applyDefaultCache`
Sets standard 24-hour cache for general content.
```javascript
var cache = require('*/cartridge/scripts/middleware/cache');

server.get('Show', cache.applyDefaultCache, function (req, res, next) {
    // Your controller logic here
    // Page will be cached for 24 hours
    next();
});
```

#### `applyPromotionSensitiveCache`
Sets 24-hour cache with personalization flag for promotion-sensitive pages.
```javascript
server.get('ProductList', cache.applyPromotionSensitiveCache, function (req, res, next) {
    // Page cached for 24 hours but marked as personalized
    // Useful for pages that show different content based on promotions
    next();
});
```

#### `applyShortPromotionSensitiveCache`
Sets 1-hour cache with personalization for highly dynamic promotional content.
```javascript
server.get('FlashSale', cache.applyShortPromotionSensitiveCache, function (req, res, next) {
    // Short cache for time-sensitive promotional content
    next();
});
```

#### `applyInventorySensitiveCache`
Sets 30-minute cache for inventory-dependent pages.
```javascript
server.get('ProductAvailability', cache.applyInventorySensitiveCache, function (req, res, next) {
    // Short cache for pages that depend on inventory levels
    next();
});
```

### CSRF Protection (`csrf.js`)

Critical security middlewares for preventing Cross-Site Request Forgery attacks:

#### `generateToken`
Generates and adds CSRF token to view data. Required for forms that will be submitted via POST.
```javascript
var csrfProtection = require('*/cartridge/scripts/middleware/csrf');

server.get('ShowForm', csrfProtection.generateToken, function (req, res, next) {
    res.render('myForm', {
        // csrf token automatically available in pdict.csrf
    });
    next();
});
```

#### `validateRequest`
Validates CSRF token for standard form submissions. Logs out user and redirects on failure.
```javascript
server.post('SubmitForm', csrfProtection.validateRequest, function (req, res, next) {
    // Process form submission - token has been validated
    next();
});
```

#### `validateAjaxRequest`
Validates CSRF token for AJAX requests. Redirects to AJAX-specific error page on failure.
```javascript
server.post('AjaxSubmit', csrfProtection.validateAjaxRequest, function (req, res, next) {
    // Process AJAX form submission
    res.json({ success: true });
    next();
});
```

#### CRITICAL: CSRF Middleware Automation

**❌ COMMON MISTAKE**: Manually adding CSRF tokens to viewData

```javascript
// ❌ WRONG - Don't do this in SFRA controllers!
server.get('ShowForm', csrfProtection.generateToken, function(req, res, next) {
    res.render('myForm', {
        csrf: res.getViewData().csrf,    // ❌ Redundant
        // OR
        csrf: {
            tokenName: req.csrf.tokenName,  // ❌ Redundant
            token: req.csrf.token           // ❌ Redundant  
        }
    });
});
```

**✅ CORRECT APPROACH**: Let middleware handle it automatically

```javascript
// ✅ CORRECT - Middleware automatically adds CSRF to pdict
server.get('ShowForm', csrfProtection.generateToken, function(req, res, next) {
    res.render('myForm', {
        // No need to manually add CSRF - middleware does this
        pageTitle: 'My Form',
        otherData: 'value'
    });
    // pdict.csrf.tokenName and pdict.csrf.token are automatically available
    next();
});
```

**How CSRF Middleware Works in SFRA:**
- `csrfProtection.generateToken` automatically adds `csrf.tokenName` and `csrf.token` to viewData
- Templates access tokens directly via `${pdict.csrf.tokenName}` and `${pdict.csrf.token}`
- `csrfProtection.validateRequest` and `validateAjaxRequest` handle validation automatically
- **Never manually add CSRF data to viewData** - it's redundant and can cause issues

### User Authentication (`userLoggedIn.js`)

Middlewares for protecting routes that require authentication:

#### `validateLoggedIn`
Ensures user is logged in, redirects to login page if not. Preserves query parameters.
```javascript
var userLoggedIn = require('*/cartridge/scripts/middleware/userLoggedIn');

server.get('AccountDashboard', userLoggedIn.validateLoggedIn, function (req, res, next) {
    // User is guaranteed to be logged in here
    next();
});
```

#### `validateLoggedInAjax`
AJAX-friendly version that returns JSON response instead of redirecting.
```javascript
server.post('UpdateProfile', userLoggedIn.validateLoggedInAjax, function (req, res, next) {
    var viewData = res.getViewData();
    if (viewData.loggedin) {
        // Process the request
        res.json({ success: true });
    } else {
        // viewData.redirectUrl contains login URL for client-side redirect
        res.json({ 
            success: false, 
            redirectUrl: viewData.redirectUrl 
        });
    }
    next();
});
```

### Consent Tracking (`consentTracking.js`)

Handles privacy consent management and tracking permissions:

#### `consent`
Manages tracking consent state and generates CSRF tokens when needed.
```javascript
var consentTracking = require('*/cartridge/scripts/middleware/consentTracking');

server.get('Home', consentTracking.consent, function (req, res, next) {
    // Consent status available in pdict.tracking_consent
    // Can be: true (consented), false (declined), null (not set)
    next();
});
```

### Page Metadata (`pageMetaData.js`)

Processes and computes page metadata for SEO:

#### `computedPageMetaData`
Consolidates page metadata from various sources into a single object.
```javascript
var pageMetaData = require('*/cartridge/scripts/middleware/pageMetaData');

server.get('ProductDetail', pageMetaData.computedPageMetaData, function (req, res, next) {
    // Computed metadata available in pdict.CurrentPageMetaData
    // Includes title, description, keywords, and pageMetaTags array
    next();
});
```

### Middleware Chaining Examples

#### Complete Product Detail Page
```javascript
var server = require('server');
var cache = require('*/cartridge/scripts/middleware/cache');
var consentTracking = require('*/cartridge/scripts/middleware/consentTracking');
var pageMetaData = require('*/cartridge/scripts/middleware/pageMetaData');

server.get('Show', 
    cache.applyPromotionSensitiveCache,
    consentTracking.consent,
    pageMetaData.computedPageMetaData,
    function (req, res, next) {
        // All middleware has executed:
        // - Page cached for 24 hours with personalization
        // - Consent tracking set up
        // - Page metadata computed
        // - CSRF token generated (by consent middleware)
        
        var pid = req.querystring.pid;
        // Product logic here...
        next();
    }
);
```

#### Secure Form Submission
```javascript
var csrfProtection = require('*/cartridge/scripts/middleware/csrf');
var userLoggedIn = require('*/cartridge/scripts/middleware/userLoggedIn');

// Show form
server.get('ShowContactForm', 
    userLoggedIn.validateLoggedIn,
    csrfProtection.generateToken,
    function (req, res, next) {
        res.render('contactForm');
        next();
    }
);

// Process form
server.post('SubmitContactForm',
    userLoggedIn.validateLoggedIn,
    csrfProtection.validateRequest,
    function (req, res, next) {
        // User authenticated and CSRF validated
        // Process form safely
        next();
    }
);
```

### Custom Middleware Best Practices

When creating custom middleware:

1. **Follow the Pattern**: Always accept `(req, res, next)` parameters
2. **Call next()**: Always call `next()` unless terminating the request
3. **Handle Errors**: Use try-catch and pass errors to `next(error)`
4. **Set View Data**: Use `res.setViewData()` to pass data to templates
5. **Check Existing Data**: Use `res.getViewData()` to avoid overwriting existing data

```javascript
// Custom middleware example
function customMiddleware(req, res, next) {
    try {
        var viewData = res.getViewData() || {};
        viewData.customProperty = 'customValue';
        res.setViewData(viewData);
        next();
    } catch (error) {
        next(error);
    }
}
```

## Remote Include Architecture (Controller Perspective)

Remote includes bridge controller design, caching, and security. Each `<isinclude url="...">` triggers a secondary request whose lifecycle is independent of the parent page.

### 1. Execution Model Recap
1. Parent controller builds main page (may be fully cached)
2. Application Server streams HTML with remote include placeholders
3. Web Adapter detects placeholders → performs new HTTP requests to each include URL
4. Include controller runs with `req.includeRequest === true`
5. Web Adapter stitches fragment responses into final payload

### 2. Mandatory Middleware Ordering
Always begin remote include routes with the gatekeeper:
```javascript
server.get('MiniCart',
  server.middleware.include,  // Ensures only include-origin requests allowed
  /* cache or auth middleware here */
  function (req, res, next) {
     // Build fragment model – NO parent pdict access
     res.render('components/header/miniCart');
     return next();
  }
);
```

Add authentication right AFTER the gatekeeper if user‑specific:
```javascript
server.get('AccountSummary',
  server.middleware.include,
  userLoggedIn.validateLoggedIn,
  cache.applyShortPromotionSensitiveCache,
  function (req, res, next) {
     res.render('account/summary');
     next();
  }
);
```

### 3. Data Passing Constraints
Include controllers cannot see parent `pdict`. All inputs must be query parameters defined in the template:
```isml
<isinclude url="${URLUtils.url('PromoSlot-Include', 'slotId', 'hp_banner_1')}" />
```
Avoid volatile params that reduce cache hits (e.g., timestamps, indexes, random tokens).

### 4. Caching Strategy Patterns
| Fragment | Typical TTL | Notes |
|----------|------------|-------|
| MiniCart | 0 (uncached) | Basket must reflect real-time state |
| Personalized Banner | 5–15m | Balance freshness vs recompute cost |
| Static Navigation | 12–24h | Rarely changes; high CDN / app cache hit rate |
| Inventory Badge | 1–5m | Short TTL isolates volatility |

### 5. Performance Guardrails
| Concern | Guidance |
|---------|----------|
| Count per page | Target < 20 (soft). Overuse causes waterfall latency. |
| Nesting depth | Keep ≤ 2. Depth 3+ complicates tracing & raises miss amplification. |
| Fragment size | Keep payload lean (<10KB ideal) – remote includes are for targeted data. |
| Parallelism | Web Adapter fetches includes concurrently; slowest fragment = page delay. Optimize worst offender first. |

### 6. Observability & Tracing
Search logs by extended request ID pattern: `baseId-depth-index`.
Example sequence: `Qx1Ab-0-00` (page) → `Qx1Ab-1-01` (first fragment) → `Qx1Ab-2-03` (nested fragment).

Add structured logging:
```javascript
Logger.info('Include {0} depth={1} start', request.httpPath, request.requestID);
```

### 7. Security Checklist
```text
[ ] server.middleware.include first
[ ] Auth middleware if user-specific data
[ ] No PII in query params
[ ] Explicit cache middleware (or intentional no-cache)
[ ] Fragment output sanitized (no raw user input)
[ ] Error handling returns safe minimal content
```

If any box unchecked → treat as deployment blocker.

### 8. Anti‑Patterns & Refactors
| Anti‑Pattern | Risk | Refactor |
|--------------|------|----------|
| Remote include per search result | N network calls, poor TTFB | Single controller renders list with local includes |
| Passing large serialized JSON in query | URL length + logging exposure | Use lightweight ID → lookup inside fragment |
| Relying on parent csrf/viewData | Undefined behavior, security gaps | Regenerate context in fragment |
| Deep chain (>2 levels) | Hard to debug, compounded latency | Flatten – merge sibling fragments |

### 9. Example: Structured Composite Page
Home page shell (24h cache) + fragments:
- `MiniCart` (0 TTL)
- `PromoBanner` (15m)
- `CategoryRefinements` (1h)
Each can be independently invalidated without purging page shell cache.

### 10. Decision Flow
```text
Need different TTL? ── no ─▶ Local include
    │
    yes
Is data easily param encoded? ── no ─▶ Controller aggregation instead
    │
    yes
Contains sensitive data? ── yes ─▶ Add auth middleware
    │
    (Proceed) Remote include
```

---

## Code Examples

### 1. Basic Controller: Hello World

**File**: `cartridges/my_cartridge/cartridge/controllers/Hello.js`

```javascript
'use strict';
var server = require('server');

server.get('Show', function (req, res, next) {
    res.print('<h1>Hello World!</h1>');
    next();
});

module.exports = server.exports();
```

**Access via URL**: `.../default/Hello-Show`

### 2. Rendering an ISML Template with Data

```javascript
'use strict';
var server = require('server');
var ProductFactory = require('*/cartridge/scripts/factories/product');

server.get('Show', function (req, res, next) {
    var product = ProductFactory.get({ pid: req.querystring.pid });
    res.render('product/productDetails', {
        product: product // This object becomes 'pdict' in the template
    });
    next();
});

module.exports = server.exports();
```

The `product/productDetails.isml` template can then access `${pdict.product.productName}`.

### 3. Returning JSON for an AJAX Call

```javascript
'use strict';
var server = require('server');
var CartModel = require('*/cartridge/models/cart');
var BasketMgr = require('dw/order/BasketMgr');

server.get('GetCart', function (req, res, next) {
    var basket = BasketMgr.getCurrentBasket();
    var cart = new CartModel(basket);
    res.json(cart); // Serializes the 'cart' object to JSON
    next();
});

module.exports = server.exports();
```

The `res.json()` method is the standard way to create API endpoints for client-side JavaScript.

### 4. Extending a Base Controller (Product-Show)

**File**: `cartridges/my_cartridge/cartridge/controllers/Product.js`

```javascript
'use strict';
var server = require('server');
var page = module.superModule; // Get the base controller
server.extend(page);

// Add a new step to the end of the 'Show' route
server.append('Show', function (req, res, next) {
    var viewData = res.getViewData(); // Get data prepared by the base controller

    // Add custom property
    viewData.exampleData = 'This is custom data!';
    
    res.setViewData(viewData); // Pass modified data to the template
    next();
});

module.exports = server.exports();
```

This non-intrusively adds `exampleData` to the pdict object on the Product Detail Page.

### 5. Handling a Form Submission with CSRF Protection

```javascript
'use strict';
var server = require('server');
var csrfProtection = require('*/cartridge/scripts/middleware/csrf');

// Route to display the form
server.get('ShowForm', csrfProtection.generateToken, function (req, res, next) {
    //... logic to render form...
    res.render('myFormTemplate', {
        // ✅ CORRECT: No need to manually pass CSRF - middleware handles this
        formData: someData
    });
    // CSRF token automatically available as pdict.csrf.tokenName and pdict.csrf.token
    next();
});

// Route to handle the submission
server.post('SubmitForm', csrfProtection.validateRequest, function (req, res, next) {
    var myForm = server.forms.getForm('myForm');
    if (myForm.valid) {
        // Process valid form
        res.json({ success: true });
    } else {
        // Handle invalid form
        res.json({ success: false, error: 'Invalid form data' });
    }
    next();
});

module.exports = server.exports();
```

The template must include a hidden input for the CSRF token: `<input type="hidden" name="${pdict.csrf.tokenName}" value="${pdict.csrf.token}"/>`

## Key Best Practices

### Security

- Always use the `csrfProtection` middleware for any POST request that changes state.
- Enforce HTTPS for sensitive routes using `server.middleware.https`.
- Apply the principle of least privilege for user access control.

### Performance

- Use page caching via `res.cacheExpiration(hours)` or the cache middleware.
- Lazy load modules by placing `require()` statements inside the route functions where they are used, not at the top of the file. This reduces initial load time.
- Offload long-running tasks to asynchronous Jobs instead of running them in a synchronous controller request.

### Error Handling

- Wrap potentially failing code (especially Script API calls) in `try...catch` blocks.
- Leverage the global `Error.js` controller for uncaught exceptions. It correctly handles both page renders and AJAX JSON responses.
- Log detailed errors for developers but show user-friendly messages on the storefront.

### Testing

- Controllers should be tested with integration tests, not unit tests.
- Use a stack of Mocha, Chai, and request-promise to make HTTP requests to controller endpoints on a sandbox and assert the response.
- It is mandatory to provide integration tests for controllers that return JSON.

## Standard SFRA Controllers

SFRA provides a comprehensive set of base controllers that handle core ecommerce functionality. Understanding these controllers is essential for customization and extension. Each controller returns specific model structures that provide data to templates and AJAX responses.

**Note**: The following documentation is based on actual SFRA controller implementations found in the base cartridge.

### Core Page Controllers

#### **Home Controller** (`Home.js`)
Handles homepage rendering with Page Designer integration.

**Key Routes:**

##### `Home-Show`: Main homepage endpoint
- **Returns**: Homepage view with Page Designer content or fallback template
- **Models Returned**:
  - Uses Page Designer page 'homepage' if available and visible
  - Falls back to `home/homePage.isml` template with no explicit model data
  - Page metadata is set via `pageMetaHelper.setPageMetaTags()`
- **Template**: Page Designer 'homepage' or `home/homePage.isml`
- **Middlewares**: `consentTracking.consent`, `cache.applyDefaultCache`, `pageMetaData.computedPageMetaData`

##### `Home-ErrorNotFound`: 404 error handling
- **Returns**: 404 error page with status code 404
- **Models Returned**: No explicit model data passed
- **Template**: `error/notFound.isml`

#### **Product Controller** (`Product.js`)
Manages product detail pages, variations, and product-related functionality.

**Key Routes:**

##### `Product-Show`: Main product detail page
- **Returns**: Complete product detail information with Page Designer support
- **Models Returned**:
  - `pdict.product` - Complete product model from `productHelper.showProductPage()`
  - `pdict.addToCartUrl` - URL for adding product to cart
  - `pdict.resources` - Localized resource strings from `productHelper.getResources()`
  - `pdict.breadcrumbs` - Navigation breadcrumb array
  - `pdict.canonicalUrl` - SEO canonical URL
  - `pdict.schemaData` - Schema.org structured data
  - Uses Page Designer product page if available, otherwise falls back to standard template
- **Template**: Page Designer page or `product/productDetails.isml`
- **Middlewares**: `cache.applyPromotionSensitiveCache`, `consentTracking.consent`, `pageMetaData.computedPageMetaData`
- **Notes**: Sets `res.cachePeriod = 0` for pages with visibility rules; returns 404 for offline products (except sets/bundles)

##### `Product-ShowInCategory`: Product detail within category context
- **Returns**: Product detail with category navigation context
- **Models Returned**: Same as `Product-Show` plus:
  - Category-aware breadcrumbs from `productHelper.showProductPage()`
- **Template**: Standard product template (no Page Designer support)

##### `Product-Variation`: AJAX endpoint for product variation selection
- **Returns**: JSON response with updated product data and rendered HTML components
- **Models Returned**:
```javascript
{
    "product": {
        // Full product model with updated variation data
        "price": {...}, // With rendered HTML via priceHelper
        "attributesHtml": "...", // Rendered attributes template
        "promotionsHtml": "...", // Rendered promotions template  
        "optionsHtml": "..." // Rendered options template
    },
    "resources": {...} // Localized strings from productHelper.getResources()
}
```

### Shopping Cart & Checkout Controllers

#### **Cart Controller** (`Cart.js`)
Manages shopping cart functionality and basket operations.

**Key Routes:**

##### `Cart-Show`: Shopping cart page display
- **Returns**: Complete shopping cart page
- **Models Returned**:
  - Returns the entire `CartModel(currentBasket)` object directly to template
  - Includes automatic currency update and shipping method validation
  - `reportingURLs` set in viewData for analytics
- **Template**: `cart/cart.isml`
- **Middlewares**: `server.middleware.https`, `consentTracking.consent`, `csrfProtection.generateToken`

##### `Cart-MiniCart`: Header mini-cart component
- **Returns**: Mini-cart icon with quantity
- **Models Returned**:
  - `pdict.quantityTotal` - Total quantity of items in basket
- **Template**: `/components/header/miniCart.isml`
- **Middlewares**: `server.middleware.include`

##### `Cart-AddProduct`: Add products to cart (POST)
- **Returns**: JSON response with comprehensive cart update information
- **Models Returned**:
```javascript
{
    "reportingURL": "...", // Analytics reporting URL
    "quantityTotal": 5, // Total quantity in cart
    "message": "Product added to cart", // Success/error message
    "cart": {...}, // Complete CartModel object
    "newBonusDiscountLineItem": {...}, // Bonus product info if applicable
    "error": false, // Boolean error flag
    "pliUUID": "uuid-string", // Product line item UUID
    "minicartCountOfItems": "5 Items" // Localized item count string
}
```

##### `Cart-Get`: Get current cart data
- **Returns**: JSON response with current cart state
- **Models Returned**: Complete `CartModel(currentBasket)` object as JSON

##### `Cart-RemoveProductLineItem`: Remove items from cart
- **Returns**: JSON response with updated cart data
- **Models Returned**: Similar structure to `Cart-AddProduct` with updated cart state

#### **Checkout Controller** (`Checkout.js`)
Manages the complete checkout process including shipping, billing, and payment.

**Key Routes:**

##### `Checkout-Begin`: Main checkout entry point
- **Returns**: Checkout page with customer, shipping, and billing forms
- **Models Returned**:
  - `pdict.order` - Complete `OrderModel` with basket data, customer info, and shipping/billing forms
  - `pdict.customer` - `AccountModel` with customer profile and address book
  - `pdict.forms` - Form objects for guest customer, registered customer, shipping, and billing
  - `pdict.expirationYears` - Array of credit card expiration years (current + 10 years)
  - `pdict.currentStage` - Current checkout stage ('customer', 'shipping', 'payment', 'placeOrder')
  - `pdict.reportingURLs` - Analytics reporting URLs
  - `pdict.oAuthReentryEndpoint` - OAuth reentry point identifier
- **Template**: `checkout/checkout.isml`
- **Middlewares**: `server.middleware.https`, `consentTracking.consent`, `csrfProtection.generateToken`
- **Notes**: Validates basket, handles multi-shipping, updates currency, calculates totals, and determines appropriate checkout stage

#### **CheckoutServices Controller** (`CheckoutServices.js`)
Provides AJAX services for checkout process steps including customer information, payment processing, and order placement.

**Key Routes:**

##### `CheckoutServices-Get`: Get current checkout state for multi-shipping
- **Returns**: JSON response with current basket and customer state
- **Models Returned**:
    - `order` - Complete `OrderModel` with basket data for multi-shipping context
    - `customer` - `AccountModel` with customer profile information
    - `error` - Boolean indicating validation status
    - `message` - Error message if shipping addresses are invalid
- **Middlewares**: `server.middleware.https`
- **Notes**: Only used in multi-ship checkout when clicking "Next: Payment"

##### `CheckoutServices-SubmitCustomer`: Submit guest customer information (POST)
- **Returns**: JSON response with customer submission result
- **Models Returned**:
```javascript
// Success
{
    "customer": {...}, // AccountModel
    "error": false,
    "order": {...}, // OrderModel with updated customer email
    "csrfToken": "...", // New CSRF token
    "redirectUrl": null
}

// Error
{
    "form": {...}, // Customer form with validation state
    "fieldErrors": [...], // Array of field-specific errors
    "serverErrors": [],
    "error": true
}
```
- **Middlewares**: `server.middleware.https`, `csrfProtection.validateAjaxRequest`
- **Notes**: Validates guest customer form and sets customer email in basket

##### `CheckoutServices-LoginCustomer`: Submit registered customer login (POST)
- **Returns**: JSON response with login result
- **Models Returned**:
```javascript
// Success
{
    "customer": {...}, // AccountModel for authenticated customer
    "error": false,
    "order": {...}, // OrderModel
    "csrfToken": "...", // Refreshed CSRF token after login
    "redirectUrl": "https://checkout-begin-shipping-url"
}

// Error - Invalid credentials
{
    "form": {...}, // Customer form
    "fieldErrors": [...],
    "serverErrors": [],
    "customerErrorMessage": "Invalid login credentials",
    "error": true
}
```
- **Middlewares**: `server.middleware.https`, `csrfProtection.validateAjaxRequest`
- **Notes**: Authenticates customer and refreshes session tokens

##### `CheckoutServices-SubmitPayment`: Submit payment and billing information (POST)
- **Returns**: JSON response with payment processing result
- **Models Returned**:
```javascript
// Success
{
    "renderedPaymentInstruments": "...", // HTML for stored payment instruments
    "customer": {...}, // AccountModel
    "order": {...}, // OrderModel with updated totals and payment
    "form": {...}, // Billing form (with sensitive data cleared)
    "error": false
}

// Error - Form validation
{
    "form": {...}, // Billing form with validation state
    "fieldErrors": [...], // Array of form field errors
    "serverErrors": [...], // Array of payment processing errors
    "error": true
}

// Error - Cart issues
{
    "error": true,
    "cartError": true,
    "fieldErrors": [],
    "serverErrors": [],
    "redirectUrl": "cart-show-url"
}
```
- **Middlewares**: `server.middleware.https`, `csrfProtection.validateAjaxRequest`
- **Form Parameters**: Complete billing address, contact info, and credit card fields
- **Notes**: Validates billing form, processes payment via hooks, calculates totals, and handles payment instrument storage

##### `CheckoutServices-PlaceOrder`: Place the final order (POST)
- **Returns**: JSON response with order placement result
- **Models Returned**:
```javascript
// Success
{
    "error": false,
    "orderID": "order-number",
    "orderToken": "order-token",
    "continueUrl": "order-confirmation-url"
}

// Error - Validation failure
{
    "error": true,
    "errorStage": {
        "stage": "shipping|payment",
        "step": "address|paymentInstrument"
    },
    "errorMessage": "Specific error message"
}

// Error - Fraud detection
{
    "error": true,
    "cartError": true,
    "redirectUrl": "fraud-error-url",
    "errorMessage": "Technical error message"
}
```
- **Middlewares**: `server.middleware.https`
- **Notes**: Comprehensive order validation, fraud detection, payment authorization, and order creation

#### **CheckoutAddressServices Controller** (`CheckoutAddressServices.js`)
Handles address-related AJAX services during checkout, specifically for multi-shipping scenarios.

**Key Routes:**

##### `CheckoutAddressServices-CreateNewAddress`: Create new shipment for multi-shipping (POST)
- **Returns**: JSON response with new shipment information
- **Models Returned**:
```javascript
// Success
{
    "uuid": "new-shipment-uuid", // UUID of created shipment
    "customer": {...}, // AccountModel
    "order": {...} // OrderModel with new shipment structure
}

// Error - No basket
{
    "redirectUrl": "cart-show-url",
    "error": true
}

// Error - Shipment creation failed
{
    "redirectUrl": "checkout-begin-url",
    "error": true
}
```
- **Middlewares**: `server.middleware.https`
- **Parameters**: `productLineItemUUID` - Product line item to move to new shipment
- **Notes**: Creates new shipment and moves specified product line item to it

##### `CheckoutAddressServices-AddNewAddress`: Save shipping address in multi-shipping (POST)
- **Returns**: JSON response with address save result
- **Models Returned**:
```javascript
// Success
{
    "customer": {...}, // AccountModel
    "order": {...}, // OrderModel with updated shipping addresses
    "error": false
}

// Error - Form validation
{
    "form": {...}, // Shipping form with validation state
    "fieldErrors": [...], // Array of address validation errors
    "serverErrors": [],
    "error": true
}
```
- **Middlewares**: `server.middleware.https`, `csrfProtection.validateAjaxRequest`
- **Form Parameters**: Complete shipping address fields, shipping method, gift options
- **Notes**: Validates shipping form and applies address to appropriate shipment in multi-shipping context

##### `CheckoutAddressServices-SelectShippingAddress`: Select existing address (POST)
- **Returns**: JSON response with address selection result
- **Models Returned**:
```javascript
{
    "customer": {...}, // AccountModel
    "order": {...}, // OrderModel with selected address applied
    "error": false
}
```
- **Notes**: Applies selected address from customer's address book to shipment

#### **CheckoutShippingServices Controller** (`CheckoutShippingServices.js`)
Manages shipping method selection and calculation during checkout.

**Key Routes:**

##### `CheckoutShippingServices-ToggleMultiShip`: Toggle multi-shipping mode (POST)
- **Returns**: JSON response with multi-shipping toggle result
- **Models Returned**:
```javascript
// Success
{
    "customer": {...}, // AccountModel
    "order": {...}, // OrderModel with updated shipment structure
    "error": false
}

// Error - No basket
{
    "error": true,
    "cartError": true,
    "fieldErrors": [],
    "serverErrors": [],
    "redirectUrl": "cart-show-url"
}
```
- **Middlewares**: `server.middleware.https`
- **Parameters**: `usingMultiShip` - Boolean flag to enable/disable multi-shipping
- **Notes**: Either splits line items into separate shipments or consolidates them into single shipment

##### `CheckoutShippingServices-UpdateShippingMethodsList`: Get available shipping methods (POST)
- **Returns**: JSON response with shipping methods for specific shipment
- **Models Returned**:
```javascript
{
    "order": {...}, // OrderModel with updated shipping options
    "customer": {...}, // AccountModel
    "error": false
}
```
- **Middlewares**: `server.middleware.https`, `csrfProtection.validateAjaxRequest`
- **Notes**: Updates available shipping methods based on shipment address

##### `CheckoutShippingServices-SelectShippingMethod`: Select shipping method (POST)
- **Returns**: JSON response with shipping method selection result
- **Models Returned**:
```javascript
{
    "order": {...}, // OrderModel with updated shipping costs and totals
    "customer": {...}, // AccountModel
    "error": false
}
```
- **Middlewares**: `server.middleware.https`, `csrfProtection.validateAjaxRequest`
- **Parameters**: `shipmentUUID`, `shippingMethodID`
- **Notes**: Applies selected shipping method to specified shipment and recalculates totals

##### `CheckoutShippingServices-SubmitShipping`: Submit shipping information (POST)
- **Returns**: JSON response with shipping submission result
- **Models Returned**:
```javascript
// Success
{
    "order": {...}, // OrderModel with finalized shipping information
    "customer": {...}, // AccountModel
    "error": false,
    "csrfToken": "..." // Refreshed CSRF token
}

// Error
{
    "form": {...}, // Shipping form with validation errors
    "fieldErrors": [...],
    "serverErrors": [],
    "error": true
}
```
- **Middlewares**: `server.middleware.https`, `csrfProtection.validateAjaxRequest`
- **Notes**: Final shipping step validation and preparation for payment stage

### Order Management Controllers

#### **Order Controller** (`Order.js`)
Manages order confirmation, history, and details.

**Key Routes:**

##### `Order-Confirm`: Order confirmation page (POST)
- **Returns**: Order confirmation page with order details
- **Models Returned**:
  - `pdict.order` - Complete `OrderModel` with all order details, line items, and totals
  - `pdict.returningCustomer` - Boolean indicating if customer is registered
  - `pdict.passwordForm` - Password creation form for guest customers (optional)
  - `pdict.reportingURLs` - Analytics URLs for order tracking
  - `pdict.orderUUID` - Order UUID for tracking
- **Template**: `checkout/confirmation/confirmation.isml`
- **Middlewares**: `consentTracking.consent`, `server.middleware.https`, `csrfProtection.generateToken`
- **Notes**: Validates order ID and token, prevents duplicate confirmations, handles both guest and registered customer confirmations

##### `Order-History`: Customer order history
- **Returns**: List of customer's past orders
- **Models Returned**:
  - `pdict.orders` - Paginated list of customer orders
  - `pdict.orderPagination` - Pagination information
  - `pdict.breadcrumbs` - Navigation breadcrumbs
- **Template**: `account/orderHistory.isml`
- **Middlewares**: `userLoggedIn.validateLoggedIn`, `consentTracking.consent`

##### `Order-Details`: Individual order details
- **Returns**: Detailed view of specific order
- **Models Returned**:
  - `pdict.order` - Complete `OrderModel` with full order details
  - `pdict.exitLinkUrl` - URL to return to order history
  - `pdict.breadcrumbs` - Navigation breadcrumbs
- **Template**: `account/orderDetails.isml`
- **Middlewares**: `userLoggedIn.validateLoggedIn`, `consentTracking.consent`

### Account Management Controllers

#### **Account Controller** (`Account.js`)
Manages customer account functionality and authentication.

**Key Routes:**

##### `Account-Show`: Account dashboard
- **Returns**: Complete customer account dashboard
- **Models Returned**:
  - `pdict.account` - Account model from `accountHelpers.getAccountModel(req)`
  - `pdict.accountlanding` - Boolean flag set to true
  - `pdict.breadcrumbs` - Navigation breadcrumbs array
  - `pdict.reportingURLs` - Analytics URLs (if registration completion)
  - `pdict.payment` - Payment information from account model
  - `pdict.viewSavedPaymentsUrl` - URL to payment instruments list
  - `pdict.addPaymentUrl` - URL to add new payment method
- **Template**: `account/accountDashboard.isml`
- **Middlewares**: `server.middleware.https`, `userLoggedIn.validateLoggedIn`, `consentTracking.consent`

##### `Account-Login`: Customer login (POST)
- **Returns**: JSON response with authentication result
- **Models Returned**:
```javascript
// Success
{
    "success": true,
    "redirectUrl": "redirect-url-from-accountHelpers.getLoginRedirectURL()"
}

// Failure (various error scenarios)
{
    "error": ["Error message from Resource bundle or custom message"]
}
```
- **Special Handling**: Account lockout triggers email notification via hooks

##### `Account-SubmitRegistration`: New customer registration
- **Returns**: JSON response with registration result
- **Models Returned**: Uses form validation with `server.forms.getForm('profile')`
```javascript
// Success response structure varies based on form validation
// Error responses include field-specific validation errors
{
    // Form validation errors for specific fields
    "fieldErrors": {...},
    // General registration errors
    "error": [...]
}
```

#### **Address Controller** (`Address.js`)
Manages customer address book functionality.

**Key Routes:**

##### `Address-List`: Display customer's address book
- **Returns**: List of customer's saved addresses
- **Models Returned**:
  - `pdict.addressBook` - Array of `AddressModel` objects from customer's address book
  - `pdict.actionUrls` - URLs for delete and list actions
  - `pdict.breadcrumbs` - Navigation breadcrumbs array
- **Template**: `account/addressBook.isml`
- **Middlewares**: `userLoggedIn.validateLoggedIn`, `consentTracking.consent`

##### `Address-AddAddress`: Add new address form (GET)
- **Returns**: New address creation form
- **Models Returned**:
  - `pdict.addressForm` - Empty address form for new address creation
  - `pdict.breadcrumbs` - Navigation breadcrumbs
- **Template**: `account/addEditAddress.isml`
- **Middlewares**: `csrfProtection.generateToken`, `consentTracking.consent`, `userLoggedIn.validateLoggedIn`

##### `Address-EditAddress`: Edit existing address form (GET)
- **Returns**: Pre-populated address edit form
- **Models Returned**:
  - `pdict.addressForm` - Address form populated with existing address data
  - `pdict.breadcrumbs` - Navigation breadcrumbs
- **Template**: `account/addEditAddress.isml`

##### `Address-SaveAddress`: Save address (POST)
- **Returns**: JSON response with save result
- **Models Returned**: Form validation results and success/error status

##### `Address-DeleteAddress`: Delete address (POST)
- **Returns**: JSON response with deletion result
- **Models Returned**: Success/error status for address deletion

#### **PaymentInstruments Controller** (`PaymentInstruments.js`)
Manages customer's saved payment methods.

**Key Routes:**

##### `PaymentInstruments-List`: Display saved payment methods
- **Returns**: List of customer's saved payment instruments
- **Models Returned**:
  - `pdict.paymentInstruments` - Array of customer's saved payment methods
  - `pdict.actionUrls` - URLs for payment instrument management
  - `pdict.breadcrumbs` - Navigation breadcrumbs
- **Template**: `account/payment/paymentMethods.isml`
- **Middlewares**: `userLoggedIn.validateLoggedIn`, `consentTracking.consent`

##### `PaymentInstruments-AddPayment`: Add new payment method form
- **Returns**: New payment method creation form
- **Models Returned**:
  - `pdict.paymentForm` - Payment instrument form
  - `pdict.breadcrumbs` - Navigation breadcrumbs
- **Template**: `account/payment/addPayment.isml`

##### `PaymentInstruments-SavePayment`: Save payment method (POST)
- **Returns**: JSON response with save result
- **Models Returned**: Form validation and success/error status

### Search & Navigation Controllers

#### **Search Controller** (`Search.js`)
Handles product search, category navigation, and refinements.

**Key Routes:**

##### `Search-Show`: Main search/category listing page
- **Returns**: Product listing page with search results or category products
- **Models Returned**:
  - `pdict.productSearch` - Complete `ProductSearchModel` with search results, refinements, and pagination
  - `pdict.maxSlots` - Maximum recommendation slots
  - `pdict.reportingURLs` - Analytics reporting URLs
  - `pdict.refineurl` - Base URL for refinements
  - `pdict.breadcrumbs` - Category/search breadcrumbs
  - `pdict.apiProductSearch` - Raw search API results for analytics
- **Template**: `search/searchResults.isml`
- **Middlewares**: `cache.applyPromotionSensitiveCache`, `consentTracking.consent`, `pageMetaData.computedPageMetaData`

##### `Search-UpdateGrid`: AJAX grid update for sorting/pagination
- **Returns**: Updated product grid HTML
- **Models Returned**:
  - `pdict.productSearch` - Updated search results with new sorting/pagination
- **Template**: `/search/productGrid.isml`
- **Notes**: Called when shopper changes sort order or requests more results

##### `Search-Refinebar`: Refinement sidebar component
- **Returns**: Refinement filters sidebar
- **Models Returned**:
  - `pdict.productSearch` - Search model with available refinements
- **Template**: `/search/refinementBar.isml`
- **Middlewares**: `cache.applyDefaultCache`

##### `Search-GetSuggestions`: Search suggestions for autocomplete
- **Returns**: JSON search suggestions
- **Models Returned**:
```javascript
{
    "suggestions": [...], // Array of search term suggestions
    "productSuggestions": [...], // Array of product suggestions
    "categorySuggestions": [...] // Array of category suggestions
}
```

#### **SearchServices Controller** (`SearchServices.js`)
Provides AJAX services for search functionality including autocomplete and refinements.

### Content & Utility Controllers

#### **Page Controller** (`Page.js`)
Handles content pages and Page Designer content.

**Key Routes:**

##### `Page-Show`: Display content pages
- **Returns**: Content page with Page Designer or static content
- **Models Returned**:
  - `pdict.page` - Page model with content and metadata
  - `pdict.breadcrumbs` - Navigation breadcrumbs
- **Template**: Page Designer page or content template
- **Middlewares**: `cache.applyDefaultCache`, `consentTracking.consent`, `pageMetaData.computedPageMetaData`

#### **PageDesigner Controller** (`PageDesigner.js`)
Handles Page Designer specific functionality and components.

#### **ContactUs Controller** (`ContactUs.js`)
Manages contact forms and customer inquiries.

**Key Routes:**

##### `ContactUs-Show`: Display contact form
- **Returns**: Contact us form page
- **Models Returned**:
  - `pdict.contactUsForm` - Contact form object
  - `pdict.breadcrumbs` - Navigation breadcrumbs
- **Template**: `contactUs/contactUs.isml`
- **Middlewares**: `csrfProtection.generateToken`, `consentTracking.consent`

##### `ContactUs-Submit`: Process contact form submission (POST)
- **Returns**: JSON response with submission result
- **Models Returned**: Form validation results and success/error status

### Authentication & Security Controllers

#### **Login Controller** (`Login.js`)
Handles customer authentication flows.

**Key Routes:**

##### `Login-Show`: Display login form
- **Returns**: Login page with forms
- **Models Returned**:
  - `pdict.loginForm` - Customer login form
  - `pdict.profileForm` - New customer registration form
  - `pdict.breadcrumbs` - Navigation breadcrumbs
  - `pdict.oAuthReentryEndpoint` - OAuth reentry point
- **Template**: `account/login.isml`
- **Middlewares**: `csrfProtection.generateToken`, `consentTracking.consent`

##### `Login-Logout`: Customer logout
- **Returns**: Redirect to home page after logout
- **Models Returned**: No models (redirect response)

##### `Login-OAuthReentry`: Handle OAuth authentication reentry
- **Returns**: Continues checkout or redirects based on context
- **Models Returned**: Varies based on OAuth flow context

#### **CSRF Controller** (`CSRF.js`)
Provides CSRF token management services.

**Key Routes:**

##### `CSRF-Generate`: Generate new CSRF token
- **Returns**: JSON response with new CSRF token
- **Models Returned**:
```javascript
{
    "csrf": {
        "tokenName": "csrf_token",
        "token": "generated-token-value"
    }
}
```

### Privacy & Compliance Controllers

#### **ConsentTracking Controller** (`ConsentTracking.js`)
Manages privacy consent and tracking preferences.

**Key Routes:**

##### `ConsentTracking-SetSession`: Set tracking consent preference
- **Returns**: JSON response with consent status
- **Models Returned**: Consent preference status and updates

##### `ConsentTracking-GetContent`: Get consent banner content
- **Returns**: HTML content for consent banner
- **Models Returned**:
  - `pdict.consentContent` - Localized consent text and options

### Communication Controllers

#### **EmailSubscribe Controller** (`EmailSubscribe.js`)
Manages email subscription functionality.

**Key Routes:**

##### `EmailSubscribe-Subscribe`: Newsletter subscription (POST)
- **Returns**: JSON response with subscription result
- **Models Returned**: Subscription status and validation results

### Store Locator Controllers

#### **Stores Controller** (`Stores.js`)
Handles store locator functionality.

**Key Routes:**

##### `Stores-Find`: Store locator search
- **Returns**: Store search results page
- **Models Returned**:
  - `pdict.stores` - Array of store locations
  - `pdict.searchKey` - Current search terms
  - `pdict.googleMapsApi` - Google Maps API configuration
- **Template**: `storeLocator/storeLocator.isml`

##### `Stores-Details`: Individual store details
- **Returns**: Detailed store information
- **Models Returned**:
  - `pdict.store` - Complete store model with details
  - `pdict.breadcrumbs` - Navigation breadcrumbs

### Error Handling Controllers

#### **Error Controller** (`Error.js`)
Provides centralized error handling for the application.

**Key Routes:**

##### `Error-ErrorHandling`: Global error handler
- **Returns**: Error page or JSON error response based on request type
- **Models Returned**:
  - `pdict.error` - Error information and message
  - `pdict.message` - User-friendly error message
- **Template**: `error/error.isml`
- **Notes**: Handles both page requests and AJAX requests appropriately

##### `Error-Start`: Application startup error handling
- **Returns**: Startup error page
- **Models Returned**: Application startup error information

### Recommendation Controllers

#### **EinsteinCarousel Controller** (`EinsteinCarousel.js`)
Handles Einstein product recommendations and carousels.

**Key Routes:**

##### `EinsteinCarousel-GetRecommendations`: Get product recommendations
- **Returns**: JSON response with recommended products
- **Models Returned**:
```javascript
{
    "recommendations": [...], // Array of recommended products
    "errorMessage": "...", // Error message if recommendations fail
    "product": {...} // Context product for recommendations
}
```

### Reporting & Analytics Controllers

#### **ReportingEvent Controller** (`ReportingEvent.js`)
Handles analytics event tracking.

**Key Routes:**

##### `ReportingEvent-Track`: Track analytics events
- **Returns**: JSON response confirming event tracking
- **Models Returned**: Event tracking confirmation and status

### URL Management Controllers

#### **RedirectURL Controller** (`RedirectURL.js`)
Manages URL redirects and rewrites.

#### **Link Controller** (`Link.js`)
Handles dynamic link generation and routing.

#### **SourceCodeRedirect Controller** (`SourceCodeRedirect.js`)
Manages source code-based redirects for campaign tracking.

### Component Controllers

#### **Tile Controller** (`Tile.js`)
Handles tile components for product grids and carousels.

#### **Default Controller** (`Default.js`)
Provides fallback functionality and default route handling.

### Model Integration Notes from Actual Implementation

Based on examination of the actual controller code:

1. **Product Controllers**: Use `productHelper.showProductPage()` which returns a comprehensive result object with product, template, URLs, and metadata
2. **Cart Controllers**: Extensively use `CartModel` class and include transaction wrapping for basket modifications
3. **Account Controllers**: Use `accountHelpers.getAccountModel()` and form validation through `server.forms.getForm()`
4. **Template vs Page Designer**: Many controllers check for Page Designer pages first, then fall back to standard ISML templates
5. **Analytics Integration**: Controllers frequently include `reportingURLs` for analytics tracking
6. **Error Handling**: Controllers return appropriate HTTP status codes (404, etc.) and error templates
7. **Middleware Patterns**: Consistent use of HTTPS, CSRF protection, consent tracking, and caching middlewares
8. **Transaction Management**: Cart operations wrapped in `Transaction.wrap()` for data integrity

**Important**: The actual SFRA implementations include more complex logic for basket calculations, Page Designer integration, form validation, and error handling than initially documented. Controllers frequently delegate to helper modules for business logic implementation.

```
Page 38/43FirstPrevNextLast