flamingo.me/flamingo-commerce/v3@v3.11.0/product/Readme.md (about) 1 # Product Module 2 3 * Provides product domain models and the related secondary ports 4 * Provides controller for product detail view, including variant logic 5 * Provides template functions for: 6 * get a (filtered) list of products (e.g. for product teasers) 7 * get product urls 8 * get a specific product 9 10 ## Domain Layer 11 * A product is identified by a "MarketplaceCode" 12 * There are different product types, each of them need to implement the `BasicProduct` interface. 13 14 ### The product model 15  16 17 ## Details about Price fields 18 19  20 21 * The product has one main price (see PriceInfo Property) that stands for the value of that product. 22 * The product has a maintained price in a certain currency - eventually different by channel or locale. 23 * The price is either maintained as gross (B2C use cases) or net price (B2B use cases). How to interpret the price is up to the cart and view logic. 24 * Any logic depending on the gross/net knowledge should use the configuration under `commerce.product.priceIsGross` 25 26 * the product might be currently discounted and has a discounted price (the discounted price is also either gross or net like the normal price) 27 28 About Charges: 29 * A Charge is a price that needs to be paid for that product. This is normally the product price. 30 * But this concept allows to control "in what currency and type" a customer needs to pay the price of the product (See loyalty below) 31 32 Loyalty prices: 33 * The product might also have loyalty prices that allows to set a price in points, but also a minimum amount of points that need to be spent. 34 * In cases where the customer needs to spend a certain amount of points, the Method "GetCharges()" will return the different charges. Again it is up for other modules to interpret if this is gross or net. 35 36 ### Secondary Ports 37 The module defines two secondary ports: 38 39 * ProductService interface to receive products 40 * SearchService interface, to search for product by any passed filter 41 42 ### Product Types 43 44 #### Simple Products 45 Represents a simple product that can be purchased directly. 46 47 #### ConfigurableProduct and ConfigurableProductWithActiveVariant 48 Represents a product, that has several Variants. The configurable product cannot be sold directly. 49 50 But from a "Configurable Product" you can get the Saleable Variants - this is a product with Type "ConfigurableProductWithActiveVariant" 51 52 Here is an example illustrating this: 53 54 ```go 55 // ... 56 // productService is the injected implementation of interface "ProductService" 57 product, err := c.productService.Get(ctx, "id_of_a_configurable_product") 58 if product.Type() == TYPECONFIGURABLE { 59 // type assert ConfigurableProduct 60 if configurableProduct, ok := product.(ConfigurableProduct); ok { 61 variantProduct, err := configurableProduct.GetConfigurableWithActiveVariant("id_of_an_variant") 62 } 63 } 64 ``` 65 66 ## Product Detail View 67 68 The view gets the following Data passed: 69 70 ```go 71 // productViewData is used for product rendering 72 productViewData struct { 73 // simple / configurable / configurable_with_variant 74 RenderContext string 75 Product domain.BasicProduct 76 VariantSelected bool 77 VariantSelection variantSelection 78 BackURL string 79 } 80 ``` 81 82 ## Template functions 83 84 ### getProduct 85 86 Returns the product or nil: 87 `- var product = getProduct("marketplacecode")` 88 89 90 ### getProductUrl 91 92 Returns the correct url to the product: 93 `getProductUrl(product)` 94 95 The returned products urls slug will be 96 97 * generated if the confuration `commerce.product.generateSlug` is set to true 98 * use the configured attribute to fetch the utlSlug from the product data. 99 100 ### findProducts 101 102 findProducts is a template function that returns a search result to show products: 103 104 * it will dynamically adjust the search request based on url parameters that match the given namespace 105 * the template function requires 4 parameters: 106 107 * `namespace`: A name of the findProduct call - it is used to check URL parameters with that namespace 108 * `searchConfig`: A map with the following keys supported: 109 110 * `query`: Optional - the search string that a "human" might have entered to filter the search 111 * `pageSize`, `page`: Optional - set the page and the pageSize (for pagination) 112 * `sortBy`, `sortDirection` (`A`/`D`): Optional - set the field that should be used to sort the search result 113 114 * `keyValueFilters`: Optional - A map of key values that are used as additional keyValue Filters in the searchRequest 115 * `filterConstrains`: Optional - A map that supports the following keys: 116 117 * `blackList` or `whiteList` (if both given `whiteList` is preferred): This is a comma separated list of filter keys, that are evaluated during: 118 119 * using url Parameters to set keyValueFilters - only allowed keys will be used 120 * modifying the searchResult `FacetCollection` and remove disallowed facets 121 122 See the following example: 123 124 ```pug 125 126 - 127 var searchResult1 = findProducts("list1", 128 {"query":"","pageSize": "10","sortDirection":"A","sortBy":'name'}, 129 {"brand":"Hello Kitty"}, 130 {"whiteList":"brand,color,sortBy"}) 131 132 ul 133 each product in searchResult1.products 134 li Title: #{product.baseData.title} Retailer: #{product.baseData.retailerCode} Brand: #{product.baseData.attributes["brandCode"].value} 135 136 - 137 var searchResult2 = findProducts("list2", 138 {"query":"","pageSize": "10","sortDirection":"A","sortBy":'name'}, 139 {"brand":"Hello Kitty"}, 140 {"whiteList":"brand,color"}) 141 142 ul 143 each product in searchResult2.products 144 li Title: #{product.baseData.title} Retailer: #{product.baseData.retailerCode} Brand: #{product.baseData.attributes["brandCode"].value} 145 ``` 146 147 It will show in the list1 10 products that match the brand "Hello Kitty". 148 If you call the page that contains the call to that template function with urlparameters, the response can be dynamically modified. 149 For example: 150 151 `URL/?list1.brand=Apple&list2.color=black` 152 153 will modify the result of the two lists accordingly - while 154 155 `URL/?list2.notallowedkey=black` 156 157 will not. 158 159 160 ## FakeService 161 162 With enabled fake services `domain.ProductService` and `domain.SearchService` are responding with preconfigured fake products on invocation. 163 164 ````yaml 165 commerce: 166 product: 167 fakeservice: 168 enabled: true # boolean: enables fake services 169 currency: "EUR" # string: currency for the fake services 170 jsonTestDataFolder: "testdata/products" 171 jsonTestDataLiveSearch: "testdata/livesearch/livesearch.json" 172 jsonTestDataCategoryFacetItems: "testdata/facets/categoryFacetItems.json" 173 defaultProducts: true 174 ```` 175 176 The configuration option `jsonTestDataFolder` tells fakeservices to look for json files with product data in the defined folder. 177 Json files represent MarketPlaceCodes with their filename and `domain.BasicProduct` within the contents. 178 You can find an example product under: `test/integrationtest/projecttest/tests/graphql/testdata/products/json_simple.json` 179 180 The configuration option `jsonTestDataLiveSearch` provides a possibility to fake live search results separately. When you leave it 181 empty, livesearch will just be redirected to normal search (without promotions and suggestions). The contents of the json file is a map 182 of `search query => fake results`. The fake results must match the `fake.liveSearchData` struct and all mentioned marketplace codes must be available in the `jsonTestDataFolder`. 183 184 The configuration option `jsonTestDataCategoryFacetItems` provides a possibility to fake the contents of the category facet individually. When you leave it 185 empty, the default category facet items will be used. These can be found in `product/infrastructure/fake/testdata/categoryFacetItems.json` 186 which can be used as a reference for building your own file. 187 188 The configuration option `defaultProducts` toggles the delivery of default test products. Json files will be still delivered. 189 190 ### SearchService 191 The fake service returns specific products if the query matches their marketplace code. This corresponds to the file name of the products in your project. There are also available default products with the marketplace codes: 192 - fake_configurable 193 - fake_configurable_with_active_variant 194 - fake_simple 195 - fake_simple_with_fixed_price 196 - fake_simple_out_of_stock 197 - fake_fixed_simple_without_discounts 198 199 If you query the fake service with `no-results` no products are returned. 200 In case no product with the given query is found and `no-results` is not used all preconfigured fake products are returned. 201 202 ## Dependencies: 203 * search package: the product.SearchService uses the search Result and Filter objects.