<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="368500" data-post-id="368500">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hello there!</p>
<p>It’s been a while since the last release of <a href="https://leanpub.com/phoenix-product-codex" rel="noopener nofollow ugc">Phoenix Product Codex</a>, and for good reason: I just published a new release with <strong>two</strong> new chapters spanning <strong>72</strong> pages.</p>
<p><strong>Chapter 6</strong> is about modeling the <code>families</code> table, but doesn’t stop there. We also make it possible to accept a <code>:category_name</code>/<code>:category_code</code> and/or <code>:brand_name</code> in the JSON body of a <code>POST</code> to the <code>/api/families</code> route, besides only <code>:id</code> values of the associated category and brand records. Moreover, we implement association fields across all modeled schemas, so that we can flexibly get a family’s supplier, a supplier’s families, a category’s suppliers, etc.–eventually, also by adding more nested routes to all top-level routes.</p>
<p><strong>Chapter 7</strong> is a break from database modeling, and deals with implementing the improvements of the previous chapter across all types of records. We implement a “flexible identifier” feature for <code>GET</code>ting records by their unique identifiers other than their <code>:id</code>, so that you can now do (for example). <code>GET /api/categories/Rotary%20Valves</code> (by the category <code>:name</code>) or <code>GET /api/categories/161</code> (by the category <code>:code</code>). Most importantly in this chapter, we evaluate the associated fields that we should <code>Repo.preload/2</code> by default for each type of entity, and even more importantly, we make JSON responses consistent across all entity types by centralizing the <code>*JSON</code> modules’ <code>data/1</code> function within a new <code>ResponseData</code> module and using the <code>defdelegate/2</code> macro from the <code>*JSON</code> modules to the new <code>ResponseData.data/1</code> function. Therein, we use recursion and Ecto’s schema reflection capabilities to automatically populate the response map with non-<code>nil</code> association values. It works out nicely.</p>
<p>Many thanks to <a class="mention" href="/u/belgoros" rel="nofollow">@belgoros</a> for the first testimonial and his kind words:</p>
<blockquote>
<p>An amazing and completely unusual approach to presenting the material of the book, as if you are looking for a solution to the problem with the author and go through all stages of searching for a solution with him. This is exactly what is happening in practice and, in my opinion, this is a huge advantage of this book compared to other books or courses.</p>
</blockquote>
<p>With the summer already underway, things are getting relatively quieter and more predictable in my other businesses, so expect to see more frequent updates during July and August.</p>
<p>With the next release, the book will break the barrier of 200 pages. Though the number of pages is a misleading indicator of progress (due to the amounts of code snippets), I am marking the book as 28% complete in terms of scope (not pages). We still have a lot of ground to cover, but the data bedrock of the <code>Products</code> Elixir application are almost complete, and due to be completed in Chapter 8 (variants and kits/bundles in the <strong>Catalog</strong> context) and Chapter 9 (descriptions in a new <strong>Content</strong> module, and tags and other metadata for sales-item status, availability, discontinuation, etc. in the <strong>Taxonomy</strong> module).</p>
<p>Though it’s tentative for now, I foresee that we’ll deal with business logic for issuing unique and lexicographically (i.e. also more typo-resistant) item codes for variants in Chapter 10. After that chapter we’ll be ready to import real-world data from the <a href="https://isatek.gr" rel="noopener nofollow ugc">ISATEK</a> product portfolio into our database (and also implement an exporting feature into CSV/ODS/XLS/XLSX), and we can then move on to implementing features like caching, pagination/filtering/sorting/search and HATEOAS, API rate limiting, webhooks for event notifications, API documentation with OpenAPI, audit logging, and monitoring with the Phoenix LiveDashboard, before we finally learn how to deploy our app to production.</p>
<p>A big thank you to the 49 early adopters who have purchased <a href="https://leanpub.com/phoenix-product-codex" rel="noopener nofollow ugc">Phoenix Product Codex</a> at such an early state. Enjoy the two new chapters!</p>
<p>Cheers from Athens,<br>
Isaak<br>
<a href="mailto:isaak@overbring.com" rel="nofollow">isaak@overbring.com</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="368500" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenix-product-codex-develop-and-deploy-a-rest-api-for-product-data-management-with-elixir-and-phoenix-self-published-leanpub/70643/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-368500" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="368500"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #21"></div>
  </section>
</div>
    <div class="postbit" id="368534" data-post-id="368534">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dani" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dani
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Awesome. Thanks <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="368534" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenix-product-codex-develop-and-deploy-a-rest-api-for-product-data-management-with-elixir-and-phoenix-self-published-leanpub/70643/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-368534" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="368534"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #22"></div>
  </section>
</div>
    <div class="postbit" id="370743" data-post-id="370743">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="noargs" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/noargs/120/25027_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  noargs
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hi Isaak, I bought this book recently. However i found out that Viex doesn’t fetch any tin status anymore (I assume API changed or only offer paid service). What do you recommend to follow along your book.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370743" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenix-product-codex-develop-and-deploy-a-rest-api-for-product-data-management-with-elixir-and-phoenix-self-published-leanpub/70643/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-370743" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370743"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #23"></div>
  </section>
</div>
    <div class="postbit" id="370799" data-post-id="370799">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hi <a class="mention" href="/u/noargs" rel="nofollow">@noargs</a>, it works just fine here, albeit with a Greek TIN:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex(1)&gt; Viex.lookup("EL802586446")
...%Viex.Response{
  valid: true,
  company: "OVERBRING ΜΟΝΟΠΡΟΣΩΠΗ ΙΔΙΩΤΙΚΗ ΚΕΦΑΛΑΙΟΥΧΙΚΗ ΕΤΑΙΡΕΙΑ||OVERBRING LABS",
  address: "ΛΕΩΦΟΡΟΣ ΑΝΔΡΕΑ ΣΥΓΓΡΟΥ 110       11741 - ΑΘΗΝΑ"
}
</code></pre>
<p>Note that EU VIES doesn’t work correctly for some countries, most notably Germany, due to national data privacy laws. However, this is already addressed in the book w.r.t. testing.</p>
<p>Each country (should) have its own national commercial registry anyway that offers an API with richer (and better) data. For example, Greece has the GSIS RgWsPublic2 SOAP web service (for which I wrote <a href="https://hex.pm/packages/vatchex_greece" rel="nofollow">VatchexGreece</a>) and the <a href="https://opendata-api.businessportal.gr/opendata/docs/" rel="noopener nofollow ugc">ΓΕΜΗ Open Data API</a> that one day I’ll write an Elixir client for.</p>
<p>In case you are interested in data for businesses in countries with crappy VIES info, there are paid services around: <a href="https://www.google.com/search?q=vat+search+api" class="inline-onebox" rel="noopener nofollow ugc">Google Search</a>. I found this one that has a free tier with 100 requests that should be plenty for running through the book: <a href="https://vatlayer.com/pricing" class="inline-onebox" rel="noopener nofollow ugc">Start using the API | vatlayer API</a>. You’ll need to make <code>GET</code> requests with Req, and the shape of the returned data will be different, but it should be trivial to use. No affiliation or endorsement on my end, and I have never used it.</p>
<p>In any case, you could also mock Viex until you find a solution, or simply avoid it altogether and enter data manually. EU VIES it is not central to the book’s quest, even though it is a useful part of the app, when its data are available for a country.</p>
<p>Hope this helps!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370799" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenix-product-codex-develop-and-deploy-a-rest-api-for-product-data-management-with-elixir-and-phoenix-self-published-leanpub/70643/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-370799" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370799"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #24"></div>
  </section>
</div>
    <div class="postbit" id="370808" data-post-id="370808">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="kevinschweikert" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kevinschweikert/120/26866_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  kevinschweikert
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Just to add it to the list - the creator of <code>req</code> also built a tiny wrapper <a href="https://github.com/wojtekmach/vies" class="inline-onebox" rel="noopener nofollow ugc">GitHub - wojtekmach/vies: VIES VAT number check library using Req. · GitHub</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370808" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenix-product-codex-develop-and-deploy-a-rest-api-for-product-data-management-with-elixir-and-phoenix-self-published-leanpub/70643/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-370808" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370808"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #25"></div>
  </section>
</div>
    <div class="postbit" id="370809" data-post-id="370809">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Very nice! And so much simpler to use the REST API that returns JSON instead of using the SOAP API that returns XML! <a href="https://ec.europa.eu/taxation_customs/vies/#/technical-information" class="inline-onebox" rel="noopener nofollow ugc">Vies on-the-Web - European Commission</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370809" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenix-product-codex-develop-and-deploy-a-rest-api-for-product-data-management-with-elixir-and-phoenix-self-published-leanpub/70643/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-370809" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370809"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #26"></div>
  </section>
</div>
    <div class="postbit" id="370832" data-post-id="370832">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="noargs" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/noargs/120/25027_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  noargs
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thanks for the detailed explanation. I did try your tin but it came out false along with others. However i was only interested to learn building Api with elixir. So i think i would carry on without going much into tin. <img src="https://forum.elixirforum.com/images/emoji/apple/grinning_face.png?v=15" title=":grinning_face:" class="emoji" alt=":grinning_face:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370832" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenix-product-codex-develop-and-deploy-a-rest-api-for-product-data-management-with-elixir-and-phoenix-self-published-leanpub/70643/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-370832" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370832"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #27"></div>
  </section>
</div>
    <div class="postbit" id="370861" data-post-id="370861">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Interesting! Maybe it’s geo-blocked?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370861" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenix-product-codex-develop-and-deploy-a-rest-api-for-product-data-management-with-elixir-and-phoenix-self-published-leanpub/70643/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-370861" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370861"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #28"></div>
  </section>
</div>
    <div class="postbit" id="370867" data-post-id="370867">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="noargs" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/noargs/120/25027_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  noargs
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>If thats the case they shouldn’t have blocked it if someone access from Europe. We have VAT here</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370867" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenix-product-codex-develop-and-deploy-a-rest-api-for-product-data-management-with-elixir-and-phoenix-self-published-leanpub/70643/30">Post #29</a>
	                </div>
	            </div>
              <div id="likers-container-370867" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370867"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #29"></div>
  </section>
</div>
    <div class="postbit" id="373160" data-post-id="373160">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="waseigo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/waseigo/120/34129_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  waseigo
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hello Phoenix and PDM fans,</p>
<p>After an Elixir-packed summer to “sharpen the functional-programming saw” for the upcoming chapters of Phoenix Product Codex, I just released <strong>Chapter 8</strong> on Leanpub!</p>
<p>In this one, we <em>almost</em> complete the modeling of the database with the new table for product variants (<code>variants</code>) and its <code>Variant</code> schema module with validation functions. All that’s left for completing the database ERD is a consequence of what we come up with in this chapter.</p>
<p>We explore three distinct approaches to modeling product variants and bundles (kits):</p>
<ol>
<li>a simple, battle-tested method,</li>
<li>a wastefully redundant one, and</li>
<li>one (that we pick) that ends up making use of our relational database.</li>
</ol>
<p>An analysis of real-world scenarios and practical considerations informs our decision, such as <em>“breaking bulk”</em>, equipment breakage/shrinkage, minimum order quantities, and the need to track both component variants and bundles without losing hierarchical or pricing context.</p>
<p>With this approach, we make the need for the separate <code>items</code> table of the original ERD concept redundant, as we’ll be dynamically generating item codes from category and variant codes.</p>
<p>So, when we return to modeling bundles/kits in Chapter 10 after the upcoming Chapter 9’s side-quest, we’ll be using a <code>kit_compositions</code> table to define bundle recipes relationally. This will enable nested bundles (bundles including bundles that might themselves include bundles, etc.) while ensuring data integrity through custom Ecto changeset validations to prevent self-references and circular dependencies.</p>
<p>Beyond that, we extend the flexible-identifier feature to variants, and also come up with a way to avoid redundant information in the returned JSON with nested associations.</p>
<p>Chapter 9 (not released today yet) is a <em>side-quest</em>; we need to find a way to generate unique, typo-resistant variant codes within product categories that doesn’t succumb to combinatorial explosion–especially if we want to extend this to typo-resistance across all item codes and not just within a product category. We’ll be seeing how a brute-force approach of “rolling the dice” is slow, unreliable and doesn’t scale, and so we’ll be developing a solution with a Markov Chain.</p>
<p>Already in Chapter 8 we evaluate the performance of two different approaches of testing uniqueness with <code>MapSet.intersect/2</code> and <code>MapSet.member?/2</code> and see how these scale very differently.</p>
<p>Chapter 9 is progressing nicely, so expect to see an update within this week.</p>
<p>Happy coding,<br>
Isaak</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373160" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenix-product-codex-develop-and-deploy-a-rest-api-for-product-data-management-with-elixir-and-phoenix-self-published-leanpub/70643/31">Post #30</a>
	                </div>
	            </div>
              <div id="likers-container-373160" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373160"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #30"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/70643/load_more?page=4">Load more posts (7 remaining)</a>
</div></template></turbo-stream>