<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Sandra's Blog]]></title><description><![CDATA[I build, enhance, and automate enterprise workflows for a living. Oracle ERP (Fusion Cloud and EBS) is my home base. My favorite tool for extending the enterpri]]></description><link>https://sandra-suarez.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1770685887537/a16f59d4-6de0-46ae-93a9-57597b4acb63.png</url><title>Sandra&apos;s Blog</title><link>https://sandra-suarez.com</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 05 Oct 2026 23:46:23 GMT</lastBuildDate><atom:link href="https://sandra-suarez.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Intercompany in ERP: Why One Wrong Pointer Can Break the Whole Flow]]></title><description><![CDATA[Intercompany is one of the hardest financial plumbing problems in ERP. A single transaction has to flow cleanly across operating units, post correctly to multiple sub-ledgers, and net to zero in conso]]></description><link>https://sandra-suarez.com/intercompany-in-erp-why-one-wrong-pointer-can-break-the-whole-flow</link><guid isPermaLink="true">https://sandra-suarez.com/intercompany-in-erp-why-one-wrong-pointer-can-break-the-whole-flow</guid><category><![CDATA[Intercompany]]></category><category><![CDATA[ERP]]></category><category><![CDATA[ERP Software]]></category><category><![CDATA[ERP implementation]]></category><category><![CDATA[orclapex]]></category><category><![CDATA[Oracle]]></category><dc:creator><![CDATA[sssuarez]]></dc:creator><pubDate>Mon, 01 Jun 2026 16:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/66310658-d8ac-4d93-99a3-6f93df6752f6.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Intercompany is one of the hardest financial plumbing problems in ERP. A single transaction has to flow cleanly across operating units, post correctly to multiple sub-ledgers, and net to zero in consolidation. It all depends on the setup being just right.</p>
<p>This post is for anyone who designs, configures, or troubleshoots these flows. I'll walk through what intercompany is, the three most common types and when each applies, why it's genuinely hard, how to validate your setups, and how we cut 67% of the steps out of the most manual part using Oracle APEX. 👊🏼 🏆 💪🏼</p>
<hr />
<h2>3 Key Takeaways ✍️</h2>
<ol>
<li><p>Oracle ERP supports numerous intercompany types. It's essential to choose the right one for your scenario. Else, accounting, inventory and operational problems can compound quietly for years. This is painful to undo.</p>
</li>
<li><p>The most common intercompany GL failure is not a missing setup, but a wrong pointer. One misconfigured Transaction Type reference cascades into multiple wrong accounts across AR, AP, and the GL. You won't see it until you run the full cycle and trace back the actual entries.</p>
</li>
<li><p>Intercompany elimination only works if Intercompany (IC) Receivable, IC Payable, IC Revenue, and IC COGS are on dedicated, segregated accounts. If you mix them with your external AR/AP and sales accounts, elimination becomes a manual exercise every month end close cycle.</p>
</li>
</ol>
<hr />
<h2>What Intercompany Is and Why It Exists</h2>
<p>When two operating units (OUs) or legal entities inside the same parent company buy or sell from each other, those transactions still have to look "arm's length" on each entity's books — as if they were dealing with an outside, unrelated company.</p>
<p>One OU ships the product and records a receivable and revenue. The other OU receives the product and records a matching payable and inventory cost.</p>
<p>At consolidation, it should all zero out. IC Receivable nets against IC Payable. IC Revenue nets against IC COGS.</p>
<p>This is the theory at least. But here's why it is harder in practice.</p>
<hr />
<h2>Many Types of Intercompany</h2>
<p>This is where most implementations stumble. In Oracle ERP, both R12 and Fusion, there are over seven distinct types. Each one triggers different accounting flows, setup dependencies and operational behaviors. I highlight the most commonly used below.</p>
<p><strong>1. Internal Requisition / Internal Sales Order (IR/ISO) (also referred to as Transfer Orders)</strong></p>
<p>This is used for inventory replenishment across operating units. For example, if one OU needs stock, the other ships it. The receiving OU creates an Internal Requisition. The ERP then converts it to an Internal Sales Order in the shipping OU. The shipping OU picks, packs, ships, and invoices the receiving OU at a transfer price through the IC invoicing programs.</p>
<p>This is the most common type in manufacturing and distribution environments.</p>
<p><strong>2. External Drop Ship</strong></p>
<p>A customer-facing sales order is fulfilled directly by an external supplier who ships to the customer. The OU does not need to touch the inventory. Intercompany accounting flows through the purchase order receipt instead of the sales order shipment.</p>
<p><strong>3. Internal Drop Ship</strong></p>
<p>A customer-facing sales order is fulfilled by another internal operating unit, which ships directly to the end customer. The selling OU books the external sale and owns the customer relationship. The fulfilling OU ships the product and invoices the selling OU at transfer price. There are two shipments and two invoices here, but also, two profit margins to watch and verify.</p>
<blockquote>
<p>⚠️ The distinction between Type 1 and Type 3 matters more than most teams realize. In Type 1, the receiving OU is the end customer. In Type 3, there is an external customer beyond the receiving OU. The shipping network configuration, the Intercompany price list, and the revenue recognition events are all different. Careful with the configuration.</p>
</blockquote>
<hr />
<h2>Why Intercompany Is Genuinely Hard</h2>
<p><strong>1. It's a long, multi-step, multi-domain chain.</strong></p>
<p>Intercompany is one of the more complex cross-module configurations in ERP. It touches at least seven modules before a single transaction posts: Inventory, Costing, Order Management, Receivables, Tax, Payables and Accounting.</p>
<p>Intercompany accounting in Oracle ERP is driven by a sequence of interdependent setups: the Intercompany (IC) Relations configuration, the shipping network, the OM Transaction Type, Sub-ledger Accounting (SLA) rules, the AP setup in the receiving OU, and the IC price list. Each one feeds the next.</p>
<p>A mistake at any point in the chain shows up silently in the GL output. There is no single "intercompany setup" screen. It is spread across Inventory, Order Management, Receivables, Payables, General Ledger, etc. You have to understand all modules to trace it correctly.</p>
<p><strong>2. The errors do not throw out error messages.</strong></p>
<p>Unlike a missing required field that throws a validation error, a wrong account configuration in intercompany does not stop the process. The IC programs run, the invoices get created and the GL entries post. You are not informed it may be to the wrong accounts until it's too late.</p>
<p>On a recent engagement, we ran the IC cycle end-to-end. It completed without a single error message. When we pulled Account Inquiry, we found IC revenue posting to an external sales account and IC payables hiding inside an inventory accrual account. Nothing indicated anything was broken. Everything just pointed to the wrong place.</p>
<p><strong>3. The return leg is almost always an afterthought.</strong></p>
<p>Most teams configure the outbound IC flow and then discover at the first return that the return path uses a different network that does not trigger IC invoicing. Outbound and return shipping networks are frequently asymmetric. Consider and design the return flow before go-live.</p>
<h2>The Validation Checklist</h2>
<p>The only way to know your intercompany setup is correct is to run the full IC cycle in a test environment and trace the actual GL entries. Here is what to look for:</p>
<ol>
<li><p><strong>Amounts match.</strong> The IC AR invoice amount in the shipping OU must equal the IC AP invoice amount in the receiving OU, both at the transfer price from the IC price list. Any difference indicates a setup or perhaps a timing issue.</p>
</li>
<li><p><strong>Accounts are correct.</strong> Trace every entry in the GL Account Inquiry. Compare what actually posted against what's configured in IC Relations and the Sub-ledger Accounting (SLA). If they don't match, go back and retrace the full chain.</p>
</li>
<li><p><strong>Currency and Foreighn Exchange (FX) rate.</strong> If the IC invoice is in a different currency than the functional currency of either set of books, verify that the conversion rate matches what your IC Currency Conversion profile option specifies. FX mismatches create reconciliation differences that are hard to find.</p>
</li>
<li><p><strong>Same GL period.</strong> The AR and AP entries must post in the same accounting period. Timing differences, such as where the AR side posts in period 1 and the AP side posts in period 2, create reconciliation issues for that period.</p>
</li>
<li><p><strong>Dedicated IC accounts throughout.</strong> IC Receivable must be segregated from external AR. IC Payable must be segregated from external AP. IC Revenue must be segregated from third-party sales. IC COGS must have its own account. Mixing any of these with external accounts makes elimination at each month end a manual journal entry exercise.</p>
</li>
<li><p><strong>Elimination-ready.</strong> IC Receivable (shipping OU) + IC Payable (receiving OU) must net to zero. IC Revenue (shipping OU) + IC COGS (receiving OU) must net to zero.</p>
</li>
</ol>
<blockquote>
<p>Any non-zero balance on that last check will surface up at time of consolidation. ⚠️ <strong>Historical entries accumulate fast.</strong> If your IC cycle goes live with wrong accounts, every transaction posts to the wrong GL accounts from day one. The longer it runs wrong, the larger the reclassification effort.</p>
</blockquote>
<hr />
<h2>What We Automated and Why It Mattered</h2>
<p>A client's intercompany order booking process was manual and painful. The Intercompany Specialist had to log into multiple EBS responsibilities, create a PO Requisition by hand, run "Create Internal Orders," then open the Order Import Corrections form just to fix the currency. From there, it was back into the Internal Sales Order to populate a dozen header and line fields, attach three document types, and trigger an eConfirmation. With 300 to 400 transactions per year at roughly 15-20 minutes each, that's over 100 hours of repetitive, error-prone work annually. We built an APEX automation to collapse most of these steps into a single APEX session.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/0ebdf844-68b2-486b-b7a2-dd5d43fbc8d8.png" alt="" style="display:block;margin:0 auto" />

<blockquote>
<p>Before vs. After: the 9 manual steps required to create and book a single intercompany sales order: now collapsed into 3 steps with APEX. And this is just Stage 1 of a typical 15-20 step intercompany flow.</p>
</blockquote>
<hr />
<h2>ERP Features We Leveraged</h2>
<p>The solution is built entirely on standard Oracle IC programs: Requisition Import, Create Internal Orders, and Order Import all run as designed. What we built on top was a PL/SQL orchestration layer that 1) populates the interface tables, 2) fires each concurrent program in its proper sequence, 3) waits for each to complete, 4) validates the output, and then moves to the next step. We stood up a single custom concurrent program, "XX Launch Intercompany Process," to control the end-to-end chain.</p>
<p>We came up with the concept of <em>'Intercompany Profiles</em>' to capture setups by intercompany scenario - by customer, OU, Legal Entity (LE), and/or intercompany type. Each profile stores pre-defined values such as the OU, org, subinventory, price list, currency, shipping method, FOB, and freight terms so that each new transaction starts pre-configured for the user. Two Descriptive Flexfields on the Requisition Header and Lines capture the External SO traceability IDs throughout the end to end process.</p>
<blockquote>
<p>"<em>Set it once, and then reference it every time.</em>"</p>
</blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/bf973787-126f-4138-b66a-2e17b92543bb.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>What APEX Contributed</h2>
<p>EBS forms can't do what APEX does. The specialist has a single APEX webpage to navigate to and work with. They pick a profile, select the External Sales Order from a filtered list, and immediately, APEX displays populated fields for review before submission. For example, if there's a negative margin on the order, they can email for approval directly from the APEX app before submitting.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/04388d26-da35-4104-bc92-0d9cd8135286.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/31222aa9-63df-4327-8184-d519dd3f00c4.png" alt="" style="display:block;margin:0 auto" />

<p>Once submitted, a progress tracker shows each concurrent program firing and completing in real time.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/ddb1c6bc-9159-43d3-a30d-b738cce87828.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/3d9c2a6f-00ab-4bcc-8f7d-44ba17378542.png" alt="" style="display:block;margin:0 auto" />

<p>The log file, below, for the main controller Concurrent Program, 'Launch Intercompany Process' (shown above), includes details of each step taken during the Intercompany Automation Process. It also includes the Requisition Number and Internal Sales Order Number created by the process and status of uploaded attachments.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/376fb109-07e9-4fc8-9663-21dec94f369d.png" alt="" style="display:block;margin:0 auto" />

<p><strong>And keep in mind</strong>: everything above is just the booking stage. Fulfillment of both sales orders, warehouse receipts, IC AR and AP invoice generation, GL transfers, posting, and reconciliation all still lie ahead. Each can be a multi-step process of its own. This is how a single intercompany transaction can stretch to over 20 steps end-to-end.</p>
<hr />
<h2>Closing Thoughts</h2>
<p>Everything above, the three intercompany types, the chain-of-dependency failures and the validation checklist - apply whether you're on R12 or Fusion. The specific configurations, tables and SLA behavior, vary by version and deserve their own treatment. But get the concepts right first. Then you can focus on the version-specific execution. Have fun!</p>
<p><em>As always, reach out and let me know how your intercompany design goes. I'd love to hear what you find.</em> 🙏</p>
]]></content:encoded></item><item><title><![CDATA[Solving Sell-Side Consignment in Oracle ERP]]></title><description><![CDATA[Oracle's consignment solution, across EBS 11i, R12, and even Fusion Cloud, only covers the buy side. Here's how we designed a complete sell-side consignment process using standard EBS transactions.

I]]></description><link>https://sandra-suarez.com/solving-sell-side-consignment-in-oracle-erp</link><guid isPermaLink="true">https://sandra-suarez.com/solving-sell-side-consignment-in-oracle-erp</guid><category><![CDATA[Oracle]]></category><category><![CDATA[ERP Solutions ]]></category><category><![CDATA[ERP]]></category><category><![CDATA[workflow]]></category><category><![CDATA[workflow optimization]]></category><category><![CDATA[Workflow Automation]]></category><dc:creator><![CDATA[sssuarez]]></dc:creator><pubDate>Tue, 26 May 2026 01:43:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/c5604853-93ea-4dd0-9986-82b06ca90394.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><em>Oracle's consignment solution, across EBS 11i, R12, and even Fusion Cloud, only covers the buy side. Here's how we designed a complete sell-side consignment process using standard EBS transactions.</em></p>
</blockquote>
<p>If you've been looking for a way to handle sell-side consignment in Oracle EBS, where <em><strong>your company</strong></em> is the consignor placing samples at a customer's location, this post is for you. Oracle doesn't have a module for it. Not in 11.5.10, not in R12, and not fully in Fusion Cloud either.</p>
<p>This post documents how we designed and validated a complete sell-side consignment process using nothing but standard, out-of-the-box EBS transactions. I'm sharing it here because I couldn't find this solution documented anywhere when I needed it, and I suspect others are stuck on the same problem.</p>
<h2>3 Key Takeaways ✍️</h2>
<p>In case you are pressed for time, here are three key points I hope you take:</p>
<h3>💡 Takeaway 1</h3>
<p><strong>Oracle's consignment module is buy-side only, across all versions.</strong> EBS 11.5.10, R12, and Fusion Cloud all provide consignment tracking for when your company is the <em>consignee</em>. None of them natively support the scenario where your company is the <em>consignor</em>.</p>
<h3>💡 Takeaway 2</h3>
<p><strong>Separate billing from inventory movement.</strong> Bill Only Sales Orders handle invoicing (they don't touch inventory) and Account Alias Issues handle the inventory relief (they don't create invoices). When these two are combined in the right sequence, you get the benefits of both - without needing to pick, pack, or ship product that hasn't moved.</p>
<h3>💡 Takeaway 3</h3>
<p><strong>Test with real numbers in a live instance.</strong> Our most surprising discovery, that the Account Alias must point to COGS, not back to the inventory account, only surfaced because we inspected GL entries line by line. The configuration may look correct but the results were wrong.</p>
<h2>1. The Problem Statement</h2>
<p>If you've ever searched Oracle's documentation for "consignment," you've found <strong>supplier-side (buy-side) consignment tracking</strong>. This is the scenario where your company is the consignee: a supplier parks inventory at your warehouse, and you pay for it only when you consume it. This is true in EBS (11.5.10, R12), and even Fusion Cloud.</p>
<p>But what if your company is the <strong>consignor</strong>? For example, you may manufacture inventory or samples for customer evaluation, ship them to a customer's location, and the customer sits on them for 10, 30, or 60 days before deciding to buy. Until they commit, the product stays on <em>your</em> books.</p>
<p>That's sell-side consignment. And no version of Oracle ERP has a native workflow for it (yet).</p>
<h3>💡 <em>What Is Consignment?</em></h3>
<blockquote>
<p><em>I</em>n a consignment arrangement, goods are physically transferred to the customer (the "consignee"), but title and ownership remain with the vendor (the "consignor") until the customer decides to purchase. Until that point, the inventory stays on the vendor's balance sheet.</p>
</blockquote>
<p><strong>Here's the scenario we faced</strong>: my client, a Canadian manufacturer, needed to place consignment samples with its French subsidiary's end customers across France. Canada needed to retain ownership until purchase, track inventory at each consigned location, and record the intercompany sale (Canada as supplier to the French entity) if and only when France's customer purchased.</p>
<h2>2. The Business Pain Points</h2>
<p>My client was shipping samples from Canada to its French entity using Oracle ERP's Intercompany Internal Requisition / Internal Sales Order (IR/ISO) workflow to move inventory between the two legal entities. Once a sample arrived in France, it was forwarded to the end customer for evaluation with no corresponding record in the ERP. Only if the customer decided to buy would the external sale be recorded. Here's what was going wrong:</p>
<h4>Pain Point #1: Ownership Integrity</h4>
<p>Intercompany orders (from CAN to FR) result in a shipment event, which trigger ownership transfer to the subsidiary. This contradicts the entire premise of consignment. Auditors would not be able to truly reconcile who owned what when.</p>
<h4>Pain Point #2: Fake Logistics</h4>
<p>If and when the customer decided to purchase, the external customer order process required pick, pack, and ship confirm for product that was <em>already physically sitting at the customer's location</em>. Warehouse operators were executing "phantom" shipping confirmations - generating move orders, packing slips, and Bill of Lading documents for items that moved weeks ago.</p>
<h4>Pain Point #3: No Consignment Visibility</h4>
<p>There was no way to see, at a glance, which samples were sitting at which customer's location, how long they'd been there, or what their total inventory value was. Samples disappeared into a black hole between shipment and purchase.</p>
<h2>3. Approaches We Evaluated (and Why Most Failed)</h2>
<p>We didn't arrive at the final design on day one. Over multiple tweaks and research, testing, and iteration, we evaluated six different approaches:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/ba3f50ba-ae36-4155-9b24-3c60859b9914.png" alt="" style="display:block;margin:0 auto" />

<h2>4. The Solution: The Consignment Sale Model</h2>
<h3>💡 Here's the insight we landed on: separate billing from inventory movement.</h3>
<p>The design uses four standard EBS transaction types, combined in a specific sequence and zero code customization (<em>except for generation of custom shipping documents to accompany samples during subinventory transfer "shipments"</em>).</p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/716ebdcc-8921-421e-a62e-4f1ea4dcf8f5.png" alt="" style="display:block;margin:0 auto" />

<h3>Why This Works</h3>
<p><strong>Subinventory Transfers</strong> keep inventory on the consignor's books while tracking physical location. The Material account on each subinventory drives the GL, so a transfer from Finished Goods subinventory to a customer-specific consignment subinventory simply reclassifies the balance sheet. This is perfect for consignment - no P&amp;L impact and no ownership change.</p>
<div>
<div>💡</div>
<div>NOTE: we did build a customization that generated and printed shipment documentation to support the subinventory transfer '<em>shipments</em>'.</div>
</div>

<p><strong>Bill Only Sales Orders</strong> create the invoice and recognize revenue without triggering any inventory transaction. In other words, a Bill Only SO does not touch inventory. It fires <code>Dr: Receivable / Cr: Revenue</code> only.</p>
<p>To support the external customer sale, <strong>Account Alias Issues</strong> relieve inventory from the consignment subinventory and record COGS. The GL fires <code>Dr: COGS / Cr: Inventory</code>.</p>
<blockquote>
<p><em>By designing the Bill Only SO and Account Alias in the proper sequence, you get both the financial transaction and the inventory movement without ever needing to pick, pack, or ship anything.</em></p>
</blockquote>
<p>For the intercompany sale between the corporation's legal entities (Canada to France), a <em><strong>Miscellaneous Receipt</strong></em> <em>brings inventory onto the French's subsidiary's books at the intercompany transfer price, hitting an IC Clearing account that offsets the receivable at consolidation.</em></p>
<h2>5. End-to-End Process Walk-through</h2>
<p>Here's the complete flow for a sample that travels from the Canadian parent --&gt; the French subsidiary --&gt; the French customer's location, and is eventually purchased. I've included the GL entries at each step because getting the accounting right was our first priority.</p>
<h3>Phase 1: Ship to Consignment</h3>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/8358e51d-8841-43fc-8aed-bc9e184d0651.png" alt="" style="display:block;margin:0 auto" />

<h3>Phase 2: Customer Evaluates</h3>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/f79a7026-3e89-46ac-b256-1cfba7776a0a.png" alt="" style="display:block;margin:0 auto" />

<h3>Phase 3A: Customer Returns (No Sale)</h3>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/914ef98b-104a-4c35-b90e-1966dbe66450.png" alt="" style="display:block;margin:0 auto" />

<h3>Phase 3B: Customer Purchases</h3>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/c9b8423b-2d3f-445a-8c28-5cc100b2d70b.png" alt="" style="display:block;margin:0 auto" />

<h2>6. Consignment Model vs. Intercompany Process</h2>
<p>Here's a side-by-side comparison. This table was key to getting stakeholder buy-in:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/544b1b99-730a-44b3-b552-0fc36dc76199.png" alt="" style="display:block;margin:0 auto" />

<h2>7. Subinventory Strategy: Per-Customer vs. Single Consignment Bucket</h2>
<p>One design decision we spent time on: should you create a dedicated consignment subinventory for each customer, or use a single bucket for all consigned samples?</p>
<div>
<div>💡</div>
<div>Recommendation: dedicate a subinventory to each customer.</div>
</div>

<p>Here's why: with per-customer subinventories, each one gets its own Material account in the GL. That means the balance of consigned inventory at each customer is visible in your chart of accounts without any custom reporting. Oracle's standard on-hand reports work as-is: filter by subinventory and you see the customer. Partial returns stay traceable because product goes back to the customer-specific subinventory. And each subinventory maps naturally to a consignment agreement with that customer.</p>
<p>The single-bucket approach is simpler to set up (one subinventory for everyone), but you lose all native customer-level visibility. You'd need custom SQL joining <code>MTL_MATERIAL_TRANSACTIONS</code>and Sales Order tables to figure out which customer has which sample.</p>
<p>The setup overhead for per-customer subinventories is two steps: create the subinventory, assign a Material account, done. If your customer base is manageable (dozens, not thousands), the per-customer approach is the clear winner.</p>
<h2>8. The Gotchas That Burned Us During Testing 🔥</h2>
<p>These are hard-won lessons earned during testing. Each one of these caused real problems during our validation. I'm sharing them so you don't have to learn them the hard way.</p>
<h4>1. Gotcha #1: Not Recognizing COGS</h4>
<p>The Account Alias <strong>must</strong> point to the COGS account - not the consignment inventory account. If you point it back at the inventory account, the debit and credit net to zero. The inventory never leaves your books. COGS is never recognized. We caught this during testing when the GL entries balanced perfectly - which was the sign something was wrong. This is the kind of result you only catch by inspecting GL entries line by line. Be careful.</p>
<h4>2. Gotcha #2: Bill Only SO Does NOT Relieve Inventory</h4>
<p>This is by design (<em><strong>but misunderstood by many clients</strong></em>). If you book the Bill Only SO and forget to execute the Account Alias Issue, you'll have revenue on the P&amp;L but the product will still be sitting in your consignment subinventory, indefinitely. COGS will be understated. Build an automated check (we use Oracle APEX to house the business logic and report errors) that flags any Bill Only invoice without a corresponding Account Alias Issue within a defined window.</p>
<h4>3. Gotcha #3: Costing in your Subsidiary Organization</h4>
<p>The Miscellaneous Receipt in the subsidiary organization requires an item cost for the item, even if the item is simply passing through the org. Without it, Oracle posts the receipt at $0, resulting with inventory on the books at zero cost. When the subsidiary sells it to the end customer, their margin looks like 100% - a major overstatement. To resolve this, define a cost for every sample item in your subsidiary as part of the item setup process, <em>before</em> any Misc Receipt is executed. In our case, we automated the setup of an item cost, again with Oracle APEX.</p>
<h2>9. Advice for the ERP Community</h2>
<p>Here's what I'd pass along if you're solving this same problem:</p>
<ol>
<li><p><strong>Start with the GL, not the transactions.</strong> We ranked our design priorities with GL integrity as first, EBS transaction flow as second and end-to-end walk-through, third. Getting the accounting right forced us to pick the right transaction types, not the other way around. If you start by asking "what EBS transactions are available?" you could end up with a workflow that creates technically valid but inaccurate accounting entries.</p>
</li>
<li><p><strong>Test with real numbers in a live instance.</strong> Our Account Alias discovery (Gotcha #1) only surfaced because we ran a transaction and inspected the GL entries line by line. The configuration looked correct but the accounting was wrong. Whiteboard designs don't catch this so watch out for this.</p>
</li>
<li><p><strong>Separate physical movement from ownership transfer.</strong> This is our fundamental principle. Product moves in the system when it moves in the real world (subinventory transfers). Ownership changes only when the customer says "I'll buy it" (Bill Only SO + Account Alias). If your design couples these two events (physical movement and ownership change), you don't have consignment - you'll just have a regular sale with delayed shipping.</p>
</li>
<li><p><strong>Don't fight the ERP - configure it.</strong> Every transaction in our design is a standard, out-of-the-box EBS function: no custom workflows, no modified PL/SQL, and no form personalizations. We configured standard transactions in a specific sequence to produce a behavior Oracle ERP doesn't natively support. This proved to be the safest approach.</p>
</li>
</ol>
<h2>Conclusion</h2>
<p>Sell-side consignment is a gap that spans Oracle EBS 11.5.10, R12, and even Fusion Cloud. But with a disciplined combination of subinventory transfers, Bill Only Sales Orders, Account Alias Issues, and Miscellaneous Receipts, executed in the right sequence, pointed at the right accounts, we were able to build a complete, auditable consignment process. The design principles apply regardless of which Oracle platform you're on. Good Luck!</p>
]]></content:encoded></item><item><title><![CDATA[The Hidden Cost of a Product Recall]]></title><description><![CDATA[Introduction
A product recall is one of the most time-sensitive crises a manufacturing company can face. The ramifications ripple across every corner of the enterprise - procurement, inventory, produc]]></description><link>https://sandra-suarez.com/the-hidden-cost-of-a-product-recall</link><guid isPermaLink="true">https://sandra-suarez.com/the-hidden-cost-of-a-product-recall</guid><category><![CDATA[orclapex]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[ERP Software]]></category><category><![CDATA[ERP Development]]></category><dc:creator><![CDATA[sssuarez]]></dc:creator><pubDate>Fri, 13 Mar 2026 02:14:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/a78f7243-6711-437d-8442-9c7a375ba4cc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>A product recall is one of the most time-sensitive crises a manufacturing company can face. The ramifications ripple across every corner of the enterprise - procurement, inventory, production, sales, shipping, and your customer install base, all at once.</p>
<p>The challenge isn't just <em><strong>what</strong></em> to do. It's being able to see the full picture fast enough so you can act.</p>
<p>In this post, I'll walk through how we built a single-page dashboard that gives decision-makers an instant, enterprise-wide view of a recalled raw material's impact, so they can act in minutes, not days.</p>
<h2>Problem Statement</h2>
<p>When a raw material (RM) is flagged for recall or a quality issue surfaces, you need to quickly answer questions like:</p>
<ul>
<li><p>Which Bills of Materials (BOMs) reference this RM?</p>
</li>
<li><p>Which Work Orders (WOs), Purchase Orders (POs), and Sales Orders (SOs) need to go on hold?</p>
</li>
<li><p>What Finished Goods (FGs) are at risk. And do any have a substitute RM?</p>
</li>
<li><p>What's already shipped and sitting at customer sites?</p>
</li>
<li><p>What's in-transit or pending receipt?</p>
</li>
</ul>
<p>The problem is that this data lives across <em><strong>every</strong></em> corner of your ERP, and it's tangled like a spider web. Tracing a single RM through open and closed orders, multiple BOM versions, serial numbers, and shipment records is overwhelming.</p>
<h3><strong>The Current Reality</strong></h3>
<p>Without a dedicated solution, here's the typical workflow in a recall situation:</p>
<ol>
<li><p>Work with software developers to write SQL queries and export inventory data, PO status, sales history, shipment details, and customer reach.</p>
</li>
<li><p>Receive the exports, massage them in Excel</p>
</li>
<li><p>Only then can they extract the critical decision criteria and begin to act.</p>
</li>
</ol>
<p><strong>This process takes days.</strong> It involves sifting through multiple BOM versions and alternates, open and closed orders across modules, and a massive collection of interrelated data. And because of the time and resource drain on primary decisions (halt operations? notify customers?), there are no resources left for secondary analysis, e.g., understanding the full RM-to-FG impact, identifying all downstream ramifications, or exploring how to prevent this in the future.</p>
<h2>Solution Overview</h2>
<p>We delivered a <strong>one-pane-of-glass dashboard</strong>, a single-page APEX app that summarizes the full impact of a recalled raw material across the enterprise.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/46dd69f4-28b0-41a8-9840-16f7bd08ca81.png" alt="" style="display:block;margin:0 auto" />

<p>At the top of the page, key metrics are displayed as clickable badges - On-Hand Quantity, On-Hand in FGs, Shipments, Open Jobs, All Jobs, Open POs and All POs. Each badge is drillable. Click on any one and it takes you directly to the detail - the Work Orders, Purchase Orders, Sales Orders, Shipments or Inventory transactions behind that number. No more hunting across multiple ERP screens or waiting on a developer to pull the data for you.</p>
<p>With this one page summary, a decision-maker can quickly assess the lay of the land and execute: reach out to Sales to communicate customer impact and put WOs, SOs and POs on hold.</p>
<p><em><strong>Screenshot of on-hand inventory drill down by subinventory for a RM, along with serial number lineage.</strong></em></p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/9209f268-8048-4e62-935c-3f278d537adf.png" alt="" style="display:block;margin:0 auto" />

<p><em><strong>Screenshot of on-hand inventory drill down by subinventory for a Finished Good</strong></em></p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/3b8cd591-b79b-4b27-9418-d7289518a4cf.png" alt="" style="display:block;margin:0 auto" />

<p><em><strong>Screenshot of Recent Shipment Lines Drill-Down</strong></em></p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/db38fbab-ca18-4582-8f4b-277a1503b8d2.png" alt="" style="display:block;margin:0 auto" />

<h3>Finished Goods Impact Analysis</h3>
<p>Scrolling down the page, the dashboard lists every Finished Good impacted by the recalled RM. For each FG, it highlights whether a substitute (alternate) raw material exists.</p>
<ul>
<li><strong>Cells highlighted in red</strong> indicate the FG has less than three backup substitutes with enough on-hand inventory to replace the recalled component. This enables a quick decision: prioritize finding an alternate RM or put future orders for that FG on hold.</li>
</ul>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768872086176/70ade7d8-1094-4d7f-80ad-7a0072c102fc.jpeg" alt="" style="display:block;margin:0 auto" />

<h3><strong>FG Workbench</strong></h3>
<p>From the one-page summary, clicking the <strong>FG Workbench</strong> button opens a detailed view of a specific Finished Good. Here you can see its real-time status at a glance - open Sales Orders, active Work Orders and on-hand inventory by subinventory.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/9f508ce1-54cb-4156-babf-06c2028c4101.png" alt="" style="display:block;margin:0 auto" />

<p>But the real power is in the BOM drill-down. Click the <strong>RM BOM icon</strong> next to any FG and a pop-up displays all active BOMs for that Finished Good, along with the real-time on-hand quantities of each component per BOM such as how many units of the RM are on open Jobs and POs, as well as how many are in stock. You can also filter BOMs by status to narrow your view.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/27655fec-f165-4215-b6bf-5835213e10ed.png" alt="" style="display:block;margin:0 auto" />

<p>From here, if you want to deep-dive into a specific raw material, click the <strong>RM Workbench</strong> button.</p>
<h3><strong>Raw Materials Workbench</strong></h3>
<p>The RM Workbench provides a comprehensive, real-time view of the RM:</p>
<ul>
<li><p>Captures all transactions for the RM</p>
</li>
<li><p>Identifies every FG made with the RM</p>
</li>
<li><p>Flags any at-risk FGs if the RM were recalled</p>
</li>
<li><p>Displays related and alternate RMs along with their current on-hand inventory and projected availability based on open demand</p>
</li>
</ul>
<p><em><strong>How do we identify substitute RMs?</strong></em> By leveraging the fact that multiple BOM versions often exist for the same FG, each referencing a different RM. By comparing BOM definitions, we can surface the substitute items without having to perform a manual search.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/6ce9b87a-3342-4217-a79e-0855d9e1b121.png" alt="" style="display:block;margin:0 auto" />

<h2>How We Built It</h2>
<p>Building this solution came down to two things:</p>
<ol>
<li><p>Mapping the business logic to the ERP data model</p>
</li>
<li><p>Reusing views and functions and leveraging APEX Collections for performance and maintainability</p>
</li>
</ol>
<p><strong>1. Mapped Business Logic to the ERP</strong></p>
<p>Before writing a single line of SQL, we mapped out the full business algorithm. For a potential recalled RM, the business logic flows like this:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6271c8e2d64dcf11c4fb607f/30ad1a46-7a2b-4248-b4bd-815b0d824564.svg" alt="" style="display:block;margin:0 auto" />

<p><strong>Lookback Period</strong> is a user-selected parameter (1, 2, or 5 years) that controls how far back the queries reach across WOs, SOs, PO receipts, and inventory transactions.</p>
<div>
<div>💡</div>
<div>Note: these queries reference Oracle ERP base tables across OM, INV, PO, and WSH (Shipping). If you don't have deep familiarity with these tables, budget extra time for testing. Even with 30+ years of Oracle techno-functional experience, we encountered tables with fields that <em>appeared</em> to contain the data we needed but didn't , e.g., serial numbers being a prime example. You have to test exhaustively against real scenarios to confirm the right table is returning the right data.</div>
</div>

<p><strong>2. We Built for Reuse and Performance</strong></p>
<p>We utilized three patterns to improve reusability and performance:</p>
<ol>
<li><p><strong>Database Views</strong> - complex queries were written once and referenced across multiple pages and reports. When a business rule changes, you only update it in one place. (For a deeper dive, check out <a href="https://apps.cloudnueva.com/ords/r/apps/apex_blogs/home">Jon Dixon's</a> post on the <a href="https://blog.cloudnueva.com/importance-of-using-views-in-apex">importance of using DB views in APEX</a>.)</p>
</li>
<li><p><strong>PL/SQL Functions</strong> - Instead of duplicating the same calculations and logic across multiple queries and views, we wrote the SQL once as a function and called it wherever needed.</p>
</li>
<li><p><strong>APEX Collections</strong> - used to stage and share data across pages within a session, reducing need to re-run expensive queries on every page load.</p>
</li>
</ol>
<h2>Could AI Have Built This?</h2>
<p>Honestly, not yet. And here's why.</p>
<p>The hard part of this solution wasn't writing the SQL. It was knowing <em>which tables and columns</em> to pull from in the first place. An Oracle ERP schema can have thousands of tables. Even seasoned developers spend significant time hunting for the right table - the one that actually populates the field you need, not just the one that <em><strong>has</strong></em> the field.</p>
<p>In one test case, we were tracking a serial number through the shipment tables. The table we initially queried had a serial number column, but it never populated. We could see the serial number in the ERP UI, so we knew it was captured somewhere. It just took several iterations to find the right table.</p>
<p>AI faces the same challenge. Without knowing which column from which table to reference, a generated query may look correct but return inaccurate results. The validation burden doesn't go away, it just shifts. You still need someone who understands the business scenarios, knows what "correct" looks like, and can test exhaustively to prove the solution right.</p>
<p><strong>One more thought worth noting:</strong> the reason this solution works is because the underlying data <em><strong>exists</strong></em> to query in the first place. Years of consistently capturing transactions in the ERP (POs, WOs, SOs, shipments, serial numbers, etc.), built the data foundation that makes real-time decision-making possible.</p>
<p>As Accenture CEO Julie Sweet noted recently:</p>
<blockquote>
<p>“over 90% of data clean-up that companies have, when you look across the globe, is still to come.” Julie Sweet, Accenture CEO, Jan 20, 2026.</p>
</blockquote>
<p>The companies investing in their data foundation today are the ones who will be able to act fast when it matters most. Do not be part of this 90%.</p>
<h2>Conclusion</h2>
<p>The queries are straightforward. What's hard, and what I hope you took away from this post, is knowing <em>which</em> tables in the ERP database hold the data you need, and that knowledge only comes from experience and exhaustive, iterative testing. Even our developer, with 30+ years of Oracle ERP expertise, had to try multiple tables before finding ones that actually returned the serial numbers and transaction details the business needed.</p>
<p>What used to take days of manual SQL exports, Excel manipulation and cross-referencing now takes minutes on a single APEX dashboard. Decision-makers can assess the full impact of a recalled raw material across Procurement, Inventory, Production, Sales, Shipping and their Customer Install Base.</p>
<p>If your enterprise handles raw materials, components or any product with a supply chain, I hope I have inspired you to build a similar impact analysis application.</p>
<p><em>As always, reach out and let me know how it goes. I'd love to hear about your use case and help.</em></p>
]]></content:encoded></item><item><title><![CDATA[Speed versus Scale]]></title><description><![CDATA[The tagline across many AI systems and low-code application platforms goes something like this, “transform your spreadsheet into a web app in minutes!”. This approach is perfect for one-time usage and events which only require basic CRUD operations t...]]></description><link>https://sandra-suarez.com/speed-versus-scale</link><guid isPermaLink="true">https://sandra-suarez.com/speed-versus-scale</guid><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[ERP implementation]]></category><category><![CDATA[ERP Development]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[#DataModelling]]></category><dc:creator><![CDATA[sssuarez]]></dc:creator><pubDate>Thu, 20 Nov 2025 08:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1763439094272/26b96d26-7591-4e09-b394-28c0fada4987.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The tagline across many AI systems and low-code application platforms goes something like this, “<em>transform your spreadsheet into a web app in minutes!</em>”. This approach is perfect for one-time usage and events which only require basic CRUD operations to be supported. But when a column’s logic needs to be enhanced or the scope of the application grows, you need a more adaptable approach.</p>
<h2 id="heading-3-key-takeaways">3 Key Takeaways ✍️</h2>
<p>In case you are pressed for time, here’s how I approach designing APEX apps for longevity:</p>
<ol>
<li><p>Start with a Robust Data Model</p>
</li>
<li><p>Leverage Database Views</p>
</li>
<li><p>Build Configurability into Key Variables</p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">NOTE: Data modeling is essential for building scalable applications, yet it's surprisingly under-discussed in the Oracle APEX community. I'm sharing my approach here—not as an expert, but as someone who's learned through trial and error. If data modeling is your strength, your tips and best practices would be invaluable.</div>
</div>

<h2 id="heading-use-case">Use Case</h2>
<p>In a previous <a target="_blank" href="https://sandra-suarez.com/why-a-systems-assessment-can-make-or-break-your-erp-joelkallmanday">blog</a> I described the situation where my client, with over 600 legacy systems in place, was launching an ERP transformation project. We needed an artifact to capture our analysis of how the new ERP would impact each system -would the legacy app now be replaced, retired, updated or upgraded?</p>
<p>Most consulting companies, including the Big 4, use spreadsheets to capture their analysis, and our team did the same.</p>
<h3 id="heading-please-say-to-spreadsheets-for-any-system-of-record-work">Please Say ⛔ To Spreadsheets for any System of Record Work</h3>
<p>Quickly, we ran into the issues described in Key Takeaway Point # 2 of my previous <a target="_blank" href="https://sandra-suarez.com/why-a-systems-assessment-can-make-or-break-your-erp-joelkallmanday#heading-3-key-takeaways">blog</a> on building a Systems Assessment Application. No worries - <a target="_blank" href="https://apex.oracle.com/en/"><strong>Oracle APEX</strong></a> to the rescue. In less than 5 minutes, I built an APEX app based on the project’s spreadsheet implementing the <strong>Speedy Approach</strong> below. The team crowned me hero for the day 👑.</p>
<p><strong><em>Then</em></strong>, came the request for additional features. Oh, I wished I had taken the more <strong>Scalable approach</strong>, described further below.</p>
<h2 id="heading-the-speedy-approach">The Speedy Approach</h2>
<p>This is a perfect path for one-time use cases. Simply allow APEX to convert your Excel sheet to a web app (<a target="_blank" href="https://apex.oracle.com/en/learn/build-your-first-app/">here's how</a>).</p>
<p>Within four minutes, APEX created four pages automatically for me:</p>
<ol>
<li><p><strong>Home Page</strong></p>
</li>
<li><p><strong>Dashboard</strong> - displays key metrics and trends at a glance</p>
</li>
<li><p><strong>SysAssessment Search</strong> - to filter and search to my heart’s content</p>
</li>
<li><p><strong>SysAssessment Report</strong> - an Excel-like report view which allows me to create new and edit existing records.</p>
</li>
</ol>
<blockquote>
<p>Home Page is illustrated below. Refer to my <a target="_blank" href="https://sandra-suarez.com/why-a-systems-assessment-can-make-or-break-your-erp-joelkallmanday">previous blog</a> to view additional pages from the app.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762307948854/6dad2f65-407a-4492-a5f9-a2ca81b703da.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-quick-tip">☝🏼Quick Tip</h3>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">When bringing in your Excel sheet to APEX, do yourself the favor of renaming your columns during the <a target="_self" href="https://apex.oracle.com/en/learn/build-your-first-app/">“Load Data” step of building your web app</a>. APEX defaults your column names directly from your spreadsheet, which may represent user-friendly, long-winded names and not practical as table column names.</div>
</div>

<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762301850107/7b71e4d6-c512-41e2-bcf4-1cf3fc20403d.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-quick-tip-1">☝🏼Quick Tip</h3>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Always start from a spreadsheet when first starting out with Oracle APEX. Design your columns, filters, logic, pivots and charts in Excel first. With practice, you’ll learn how to design and build them directly in APEX.</div>
</div>

<h2 id="heading-a-more-future-proof-approach">A More Future-Proof Approach</h2>
<p>It’s rare for an APEX app to remain static, particularly in the enterprise. As soon as usage grows, users start asking for new features and enhancements. That’s why an app needs to be designed to evolve.</p>
<p>Over time, I’ve learned to build every app with three foundational pillars that make it more future-ready and adaptable. Here’s how I approach designing APEX apps for longevity:</p>
<ol>
<li><p>Start with a Robust Data Model</p>
</li>
<li><p>Leverage Database Views</p>
</li>
<li><p>Build Configurability into Key Variables</p>
</li>
</ol>
<ol>
<li><h2 id="heading-start-with-a-robust-data-model">Start with a Robust Data Model</h2>
</li>
</ol>
<p>Do not model data until you can answer “<em>I know what each record represents</em>.” Model <strong><em>why</em></strong> the data is being collected, not just <strong><em>what</em>.</strong> For my use case (the systems assessment app above), the <strong><em>why</em></strong> is clear:</p>
<blockquote>
<p><em>from</em> <a target="_blank" href="https://sandra-suarez.com/why-a-systems-assessment-can-make-or-break-your-erp-joelkallmanday"><em>my previous blog’s</em></a> <em>conclusion:</em> a system assessment reveals the changes that need to be made in your environment to make the most out of the new ERP. It produces a Decision Matrix highlighting the systems that need to be upgraded, retired or replaced and applications that need to remain to fill gaps the ERP cannot address.</p>
</blockquote>
<p>Next, think through what data elements to segment the application by. I knew I wanted to partition by:</p>
<ol>
<li><p><strong>Client</strong> <em>-</em> as a consultant, I want the flexibility to reuse this application across multiple clients; multi-tenancy to allow to filter by customer or lines of business within a client</p>
</li>
<li><p><strong>Event</strong> - I want the ability to run multiple assessments at the same client site, not just one, e.g., 2024 Assessment, TEST, Simulation v1, Simulation v2, etc.</p>
</li>
</ol>
<p>With these two in mind, <mark>here’s my 2-minute data model:</mark></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763007431876/08334f0e-bad4-40c0-8dc7-a41e147eda6a.png" alt class="image--center mx-auto" /></p>
<p>After creating my own ERD, I thought I would ask AI to give it a try. See my attempts below with both GPT-5.1 and Claude’s 4.5.</p>
<p>👇🏼 🤖<mark>Here’s GPT-5.1’s 2-minute data model:</mark></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763007459903/7a211040-efd5-4d0c-8943-e7cea410848f.png" alt class="image--center mx-auto" /></p>
<p>👇🔥<mark>And… here’s Claude’s 2-minute data model:</mark></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763007504062/370f41a2-2946-424e-ad01-033458898e71.png" alt class="image--center mx-auto" /></p>
<p><strong><mark>This is the prompt I used for both AI systems:</mark></strong></p>
<blockquote>
<p><code>You are a data model design expert for Oracle APEX enterprise applications. Review the attached spreadsheet showing a systems assessment—a company exercise that produces a Decision Matrix for legacy IT systems before the start of an ERP implementation.</code></p>
<p><code>A systems assessment evaluates legacy applications across three dimensions:</code></p>
<ol>
<li><p><code>ERP Compatibility: Redundancy analysis, integration capabilities, data touchpoints</code></p>
</li>
<li><p><code>Risk Assessment: Compliance, security, vendor support status</code></p>
</li>
<li><p><code>Sustainability: Integration-readiness, scalability, total cost of ownership</code></p>
</li>
</ol>
<p><code>Deliverables:</code></p>
<ol>
<li><p><code>A multi-tenant data model in Mermaid ERD syntax</code></p>
</li>
<li><p><code>SQL DDL scripts for Oracle APEX</code></p>
</li>
<li><p><code>Sample CSV data (3 clients, 2 assessment events each, 450 systems per event)</code></p>
</li>
</ol>
<p><code>The data model should support these goals:</code></p>
<ol>
<li><p><code>Support multiple clients, each with multiple assessment events.</code></p>
</li>
<li><p><code>Each client is a tenant. Tenants cannot see each other’s data.</code></p>
</li>
<li><p><code>Allow clients to create, rename or retire assessment criteria without schema changes.</code></p>
</li>
<li><p><code>Allow dynamic rating scales (e.g., Yes/No, 1–5, 0/0.25/0.5/1) by criteria.</code></p>
</li>
<li><p><code>Track every rating, including rater, rating value, scale version, timestamp, and comments.</code></p>
</li>
<li><p><code>Maintain full lineage and auditability.</code></p>
</li>
<li><p><code>Allow reporting across events, clients, and systems.</code></p>
</li>
<li><p><code>Create and maintain multiple events of a systems assessment by client.</code></p>
</li>
</ol>
</blockquote>
<p><strong>A couple of observations:</strong></p>
<ul>
<li><p>Each AI system produced a more comprehensive data model in two minutes than I ever could.</p>
</li>
<li><p>Each data model solves for the relationships between the rating scales, values, ratings and weights. Again, this is something that would have taken me numerous iterations to solve.</p>
</li>
</ul>
<h3 id="heading-so-where-could-this-go-wrong"><strong><em>So, where could this go wrong?</em></strong></h3>
<p>Solely relying on AI-generated data models can be risky because they don’t understand your business context, infrastructure or edge cases. They may design poor indexes, over-normalized tables and not account for performance. Worse, I’ve seen AI miss critical security considerations, like allowing client’s to see each other’s data.</p>
<p><strong><mark>Bottom line:</mark></strong> Treat the AI-generated data model as a high-quality first draft. Know that it will require a high level of validation and iteration to finalize. Only you and your domain experts can validate whether it is a true fit for your environment.</p>
<blockquote>
<p>NOTE: It took eight iterations to arrive at my final prompt. With the release of GPT-5.1 and its new <a target="_blank" href="https://cookbook.openai.com/examples/gpt-5/gpt-5-1_prompting_guide">5.1 Prompting Guide</a>, which emphasizes that this latest version follows instructions more literally, it’s essential that prompts do not contain any conflicting instructions, else, the AI will try to resolve them.</p>
</blockquote>
<h3 id="heading-mitigating-data-model-risks"><strong><em>Mitigating data model risks</em></strong></h3>
<p>Here’s what I do to validate my application’s data model:</p>
<ol>
<li><p><strong>Go deep on the requirements.</strong> Drill down two to three levels deep on each one. Challenge every requirement: Does it always apply? What about in x situation? What business conditions could make it obsolete?</p>
</li>
<li><p><strong>Capture real use cases.</strong> Include high-risk and exception scenarios. I test every business rule against edge cases like nulls, duplicates and boundary conditions.</p>
</li>
<li><p><strong>Performance test</strong>. Load test with high volume and concurrent users.</p>
</li>
<li><p><strong>Multi-Tenant Isolation</strong>. Verify tenants cannot access each other’s data.</p>
</li>
<li><p><strong>Have a DBA review the schema.</strong> For example, my project’s DBA warned that the criteria / ratings design suggested by the two AI systems above, will likely not scale to thousands of systems. He recommended materialized views or de-normalization for better performance.</p>
</li>
</ol>
<p>Validation is grueling work. Your years of experience have built an intuition for spotting errors. Your client is paying exactly for this expertise. Push yourself hard here. It pays dividends in time and rework saved down the road.</p>
<hr />
<ol start="2">
<li><h2 id="heading-leverage-database-views">Leverage Database Views</h2>
</li>
</ol>
<p>Different APEX pages and reports interact with the data in your app in different ways. Instead of writing a complex query in every APEX page, you create a view once and then just reference it where needed. The view handles all the complexity behind the scenes. For example,</p>
<ul>
<li><p><strong>Maintain less code</strong> - With a view, you can write complex calculations and combine data from multiple tables once - then reference the view multiple times across your app. When a business requirement changes, make the change in the view rather than having to make the same update in 20 different pages.</p>
</li>
<li><p><strong>Store business / security rules in one place</strong> - Instead of repeating the same filters and access rules on every APEX page, build them once into your view. All pages automatically enforce the rules, and when you need to update the security, you only have to change it in one place.</p>
</li>
<li><p><strong>Compute-On-The-Fly</strong> - You can introduce creative logic in a view so you do not have to add physical columns to your tables. Build the logic once, apply everywhere. This also helps keep your base tables clean and normalized.</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Check out Jon Dixon’s recent <a target="_self" href="https://blog.cloudnueva.com/importance-of-using-views-in-apex">blog</a> on the importance of using DB views for your apps.</div>
</div>

<ol start="3">
<li><h2 id="heading-build-configurability-into-key-variables">Build Configurability into Key Variables</h2>
</li>
</ol>
<p>Instead of hard-coding variables, turn them into Lookup tables so they can be updated without having to update code.</p>
<p>For example, the screenshot below shows how variables that would typically be hard-coded were converted into Lookups for a Document Generator solution. The URLs, object store bucket names and file paths are now configurable. If the client wants to change the object store bucket the Document Generator uses, they simply update the Lookup value - no code change required.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763424846194/d716ff67-bfd5-41d3-a2b2-fb1205bde8f2.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Building scalable Oracle APEX apps requires moving beyond the quick “spreadsheet-to-app” conversions. Investing the time upfront in designing a well-validated data model, using views to centralize security and business logic and storing key variables in lookup tables instead of hard-coding them, you enable your applications to scale and adapt as your business evolves. Your future self will thank you :)</p>
]]></content:encoded></item><item><title><![CDATA[Why a Systems Assessment Can Make or Break Your ERP #JoelKallmanDay]]></title><description><![CDATA[Introduction
A systems assessment exposes what changes need to be made to get the most out of your new ERP. It highlights what existing systems can now be replaced or retired and which need to remain to fill gaps the ERP cannot address.
This effort i...]]></description><link>https://sandra-suarez.com/why-a-systems-assessment-can-make-or-break-your-erp-joelkallmanday</link><guid isPermaLink="true">https://sandra-suarez.com/why-a-systems-assessment-can-make-or-break-your-erp-joelkallmanday</guid><category><![CDATA[ERP Software]]></category><category><![CDATA[ERP]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[IT]]></category><category><![CDATA[IT Services]]></category><dc:creator><![CDATA[sssuarez]]></dc:creator><pubDate>Wed, 15 Oct 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1728262160626/96fe6dff-a46d-45af-8a2e-dd9eed41f468.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>A systems assessment exposes what changes need to be made to get the most out of your new ERP. It highlights what existing systems can now be replaced or retired and which need to remain to fill gaps the ERP cannot address.</p>
<p>This effort is often underestimated. Consider the following:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760502407885/3623ff7d-0d65-4a69-afac-f52ab2d08ff8.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>A <a target="_blank" href="https://www.mulesoft.com/lp/reports/connectivity-benchmark">2025 survey by MuleSoft</a> revealed that companies use an average of <strong>over 900 applications</strong> across the enterprise.</p>
</blockquote>
<p>This figure includes homegrown, commercial-off-the-shelf (COTS), Mainframe, .NET, On-Prem, Cloud and SaaS applications and interfaces. Although the survey only included large companies with over 1000 employees, it’s still a staggering number.</p>
<p><strong>But it’s not far-fetched.</strong> Here’s a real world example.</p>
<p>A recent client with <strong>over 600 systems in place</strong>, was comparing SAP versus Oracle Fusion ERP. As part of the evaluation, we analyzed how each ERP would impact the system landscape. The ecosystem was full of duplicity. For example, the company had eight distinct, siloed ERPs, one for each line of business. Each ERP performed similar functions, resulting in an eight-fold increase in integrations, licensing costs, and maintenance.</p>
<p>Additionally, 20% of systems were homegrown or on a Mainframe stack. Other systems, acquired through past mergers, were not well understood or considered too fragile to move or automate, impeding the company’s ability to scale and support new capabilities. The application landscape became too large to manage efficiently.</p>
<p>I highlight my client’s experience to show that a systems assessment not only determines what systems are impacted by the new ERP, but also exposes the overall health of your ecosystem. In total, it can deliver:</p>
<ol>
<li><p><strong>ERP Compatibility Assessment</strong> - identifies redundant systems or those with overlapping functions to the new ERP. If a system cannot be replaced by the ERP, can it integrate with it, and if so, what are the master data and transaction touch-points?</p>
</li>
<li><p><strong>Risk Assessment</strong> - evaluates the health of a system, e.g., is it up-to-date, regulation-compliant, secure and supported?</p>
</li>
<li><p><strong>Sustainability Assessment</strong> - evaluates the system’s test of time, e.g., is it integration-ready, configurable, maintainable, performant, scalable, affordable?</p>
</li>
</ol>
<blockquote>
<p>A <em>systems assessment</em> will produce an actionable Decision Matrix of what systems needs to be integrated, retired or replaced.</p>
</blockquote>
<h2 id="heading-3-key-takeaways">3 Key Takeaways ✍️</h2>
<p>In case you are pressed for time, here are three key points I hope you walk away with:</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>1. Don’t solely rely on a </strong><a target="_blank" href="https://en.wikipedia.org/wiki/Configuration_management_database"><strong>CMDB</strong></a><strong> or other network discovery tool. These tools miss manual workarounds.</strong></div>
</div>

<p>These tools will miss:</p>
<ol>
<li><p>Work performed in Spreadsheets - all downloaded and manually-tracked spreadsheets used to perform work.</p>
</li>
<li><p>Work performed by Human APIs - manual data entry between systems. Not all systems are integrated. Per the <a target="_blank" href="https://www.mulesoft.com/lp/reports/connectivity-benchmark">MuleSoft survey above</a>, only 28% of systems are integrated, across large enterprises.</p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>2. Do not use a spreadsheet to perform the systems assessment.</strong></div>
</div>

<p>There are too many pitfalls when tracking entries and changes across hundreds of columns and rows. Which one of us has not experienced:</p>
<ul>
<li><p>“Who has the latest version?”; “Can you please check it back in?”</p>
</li>
<li><p>File corruption or loss of data.</p>
</li>
<li><p>Duplicate versions after someone forgets to check in their edits.</p>
</li>
<li><p>Not everyone is familiar with VLOOKUPs and can accidentally break them</p>
</li>
<li><p>Typos, leading to inaccurate conclusions. Did you know that manually-typed data has a 2-5% error rate?</p>
</li>
</ul>
<p>Instead, <strong>Use</strong> <a target="_blank" href="https://apex.oracle.com/en/"><strong>Oracle APEX</strong></a> <strong>or another low code tool to track and maintain this crucial artifact.</strong> 👉👉 <strong><em>NOTE:</em></strong> <em>this post is long so I wrote another post illustrating how I used Oracle APEX to create a systems assessment app</em> <a target="_blank" href="https://sandra-suarez.com/speed-versus-scale"><em>here</em></a><em>.</em></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>3. Do not skip this assessment. Even a partial assessment can deliver huge insights.</strong></div>
</div>

<p>Yes, it’s hard to start, hard to complete and time-intensive. It requires access to people who understand the dependencies and complexities of each system and demands meticulous documentation.</p>
<p>Many companies get stuck in analysis paralysis, while others don’t know where or how to start. Perfection is the enemy here - even an <strong>80% completion rate is a huge win</strong> given the limited information available to most teams.</p>
<p>Start with a small subset of systems and a few parameters (see the Criteria section below for a sample list).</p>
<h2 id="heading-how-we-end-up-with-so-many-systems">How We End Up With So Many Systems</h2>
<p>How do companies end up with hundreds of systems? Here’s a list of all the reasons I’ve collected over the years:</p>
<ol>
<li><p>Mergers and acquisitions play a big part, where systems from newly-absorbed companies are not integrated into the existing ecosystem.</p>
</li>
<li><p>New systems are introduced because existing ones cannot accommodate the needs of a new line of business</p>
</li>
<li><p><strong><em>“We’re stuck on an old version because upgrading customizations is costly and disruptive.”</em></strong></p>
</li>
<li><p>Technical debt. Typically, when a company transitions to a new system, the old legacy system is kept running.</p>
<p> 👉 <strong><em>Here’s why:</em></strong></p>
<ol>
<li><p>Other legacy systems rely on the marked-for-retirement system. Either the legacy systems do not have the capability to integrate with new systems or it's not worth the cost or risk to integrate, so the marked-for-retirement system remains.</p>
</li>
<li><p>Mainframe and custom code apps. Often, no one left knows how these systems work. The adage, “<strong><em>if it’s not broken, do not touch it</em></strong>”, applies here.</p>
</li>
<li><p>And the most frequent cited reason: <strong><em>"We've relied on it for so long, what if we need it for something? Let's just wait a bit longer and we'll retire it in a few months".</em></strong></p>
<p> Those few months turn into years. A new team comes in and has no idea what that system was ever used for, but again, afraid to touch it, so it remains in perpetuity.</p>
</li>
</ol>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721245493427/a2ac2d6c-e4aa-4ef5-80c6-ad6d69e1b17e.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-what-you-can-expect-from-an-assessment">What You Can Expect From An Assessment</h2>
<p>An assessment exercise is one of those where you will get out what you put in. When complete, your assessment can deliver:</p>
<ol>
<li><p>a complete, up-to-date view of the company’s current tech assets</p>
</li>
<li><p>An unbiased assessment (a Decision Matrix) of what apps need to be upgraded, integrated, replaced, consolidated or retired</p>
<ol>
<li><p>A listing of what can and should be replaced by the ERP</p>
</li>
<li><p>A listing of what needs to integrate with the ERP</p>
</li>
<li><p>A listing of systems that pose the highest risk to your ecosystem</p>
</li>
</ol>
</li>
<li><p>With this Decision Matrix in place, you can:</p>
<ol>
<li><p>design a multi-phase roadmap, outlining which systems to tackle first</p>
</li>
<li><p>estimate total implementation, integration, decommissioning, licensing and maintenance costs</p>
</li>
<li><p>estimate total cost savings due to a reduced footprint (lower licensing and capital and operating expenses due to less legacy upkeep)</p>
</li>
</ol>
</li>
<li><p>Finally, the executive team will be interested in aggregated summaries, analyses and recommendations including:</p>
<ol>
<li><p><strong>A risk assessment <em>analysis</em></strong> - systems that pose the highest risk to your ecosystem, with mitigation recommendations</p>
</li>
<li><p><strong>A technical debt <em>analysis</em></strong> - a listing of technical debt that poses the highest impact to your program, with recommendations on how to mitigate and manage.</p>
</li>
<li><p><strong>Summary of Findings</strong> - key observations from engineer and support team interviews, such as:</p>
<ol>
<li><p><em>“We have a dependency on key resources for technology or architecture skills:</em></p>
</li>
<li><p><em>“We lack process and standards relating to patch levels”</em></p>
</li>
<li><p><em>“We lack password and access management - some admin passwords are still ‘password’, shared with many employees and contractors and never been changed.”</em></p>
</li>
<li><p><em>“Backups and DR never attempted or successfully tested for over 40% systems”</em></p>
</li>
<li><p><em>“We lack a robust Helpdesk ticketing system; have over 65% open and unresolved tickets.”</em></p>
</li>
</ol>
</li>
<li><p><strong>Recommendations &amp; Mitigations</strong> - represents mitigations to findings above, such as:</p>
<ol>
<li><p><em>“Establish Privileged Access Management. Enforce password updates every 90 days, enable multi-factor authentication for critical systems.”</em></p>
</li>
<li><p><em>“Formalize a Disaster Recovery Program. Establish testing plan by system priority.”</em></p>
</li>
</ol>
</li>
</ol>
</li>
</ol>
<blockquote>
<p>👉 Armed with these insights, the next step is to understand how the ERP and system assessments connect - and why one should come before the other.</p>
</blockquote>
<h2 id="heading-an-essential-prerequisite">An Essential Prerequisite</h2>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Perform the ERP Map &amp; Gap Assessment <mark>before</mark> the Systems Assessment.</strong></div>
</div>

<p><strong>Here’s why:</strong> you have to understand what you need and why - that’s the purpose of the ERP assessment. It maps your business processes and requirements against what the ERP can and cannot do.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760477958251/e41746c7-34cf-4a8b-a16c-b1d869e4119b.png" alt class="image--center mx-auto" /></p>
<p>With the ERP assessment in place, you can move on to the systems assessment to evaluate which systems can truly be retired versus which ones need to remain. Those that need to remain are kept because:</p>
<ol>
<li><p>they fill gaps the ERP cannot address or,</p>
</li>
<li><p>another essential system depends on them</p>
</li>
</ol>
<ul>
<li>To expand on point 2 - If the <strong>ERP assessment</strong> recommends replacing all eight existing legacy ERPs, the <strong>system assessment</strong> verifies whether this is feasible. For example, if one essential legacy system, outside the ERP project scope, depends on two of the eight ERPs, those ERPs cannot be retired until the dependency is resolved.</li>
</ul>
<blockquote>
<p>💰💰💰<strong>This is why system assessments pay off. It is best to identify dependencies ASAP so that integration, licensing and other costs are known in the beginning of the program.</strong></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760478002129/3233c94a-ebe8-45d3-8cb4-3d472650f48c.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-how-to-begin">How To Begin 🛠</h2>
<ol>
<li><p><strong>Take inventory of all systems.</strong> Include not just applications but also spreadsheets used for business work, interfaces, APIs, and human-API activities.</p>
</li>
<li><p><strong>Determine how you will assess each system.</strong> Consider criteria such as security, compliance, scalability, reliability and performance. <strong><em>I’ve provided a tabular list of the most common criteria below</em></strong> 👇</p>
</li>
<li><p><strong>Apply weight factors.</strong> Weighting helps reflect relative importance. For example, if ‘HIPAA compliant” is three times more important as “IPv6 readiness”, a simple ranked list doesn't convey this importance, but a weighted list (e.g., HIPAA = 6, IPv6 = 2) does.</p>
</li>
<li><p><strong>Rate each system.</strong> Assessments are a team effort. You can divide up the effort by:</p>
<ol>
<li><p>Expertise: security teams assess security criteria, operations teams assess reliability and performance, etc.</p>
</li>
<li><p>Comprehensive Review: Every team member rates all systems, then discusses variances. This second approach takes longer but can bring about the most information and learning.</p>
</li>
</ol>
</li>
<li><p><strong>Analyze, summarize and present</strong>. With each system rated, your tool of choice can help you analyze, summarize and present the results. My tool of choice is <a target="_blank" href="https://apex.oracle.com/en/">Oracle APEX</a>, as illustrated on the screenshots below. I’ve provided a screenshot of a spreadsheet for comparison purposes.</p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">👉 This APEX App took 4 minutes to produce. I’ve provided instructions on how to create the APEX app <a target="_self" href="https://sandra-suarez.com/speed-versus-scale">here</a>.</div>
</div>

<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728256941454/4ab855aa-8c54-440e-82a9-7c02cd94784b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728253444025/e585be13-84c6-4f92-866e-d46d469a9ce7.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728256794256/7acdc5c5-2d67-45a4-884d-def3b471f396.gif" alt class="image--center mx-auto" /></p>
<p><strong>Spreadsheet version of the app above.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728242945301/fb9031f9-c696-450d-a1b2-ddef692e9f25.png" alt class="image--center mx-auto" /></p>
<p>You can see I have categorized my 20 parameters by ERP compatibility, risk and sustainability considerations.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728256451228/2e575687-9fa1-4761-9256-79ff4a7f4afd.gif" alt class="image--center mx-auto" /></p>
<p>The filters above and the charts below auto-generated by the Oracle APEX tool when I uploaded my spreadsheet to the APEX tool:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728256698067/69caa2a3-5279-482a-82a1-f3db80271285.gif" alt class="image--center mx-auto" /></p>
<p>For the purpose of this exercise, I used the following ratings for each assessment:</p>
<ul>
<li><p><strong>ERP Map &amp; Gap Assessment</strong></p>
<ul>
<li><p><strong>Duplicate</strong> - system’s functionality can be replaced by the new ERP</p>
</li>
<li><p><strong>Obsolete</strong> - functionality no longer relevant</p>
</li>
<li><p><strong>Fills Gap</strong> - functionality the ERP does not cover</p>
</li>
</ul>
</li>
<li><p><strong>Final Disposition Assessment</strong></p>
<ul>
<li><p><strong>Retire</strong> - duplicate, high-risk, or obsolete; dependencies cleared.</p>
</li>
<li><p><strong>Retain</strong>- fills a gap and poses low security risk</p>
</li>
<li><p><strong>Upgrade</strong> - fills a gap but poses high security risk or low sustainability. Recommend to upgrade or replace.</p>
</li>
</ul>
</li>
</ul>
<p>Finally, Oracle APEX automatically provides me the ability to create new and edit my existing records as my assessment evolves:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728257449284/b8d40d59-b87a-48ac-aaf3-03514471d69f.gif" alt class="image--center mx-auto" /></p>
<blockquote>
<p>Once your process is set, the next step is to agree on <em>what</em> you’ll measure — the assessment criteria.</p>
</blockquote>
<h2 id="heading-assessment-criteria">Assessment Criteria</h2>
<p>An important task as a team is to finalize the guiding principles to perform the assessment. Below is a listing of the most common parameters to evaluate systems. Not all are relevant to your enterprise so prioritize accordingly:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Parameters</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Scalability</strong></td><td>Can the system scale as your business grows — supporting higher transaction volumes, more users, new business models, and additional regions?</td></tr>
<tr>
<td><strong>ERP Compatibility</strong></td><td>Confirm this system can integrate with the new ERP</td></tr>
<tr>
<td><strong>Dependent On</strong></td><td>List system(s) or interfaces this system relies on.</td></tr>
<tr>
<td><strong>Depended By</strong></td><td>List system(s), interfaces or key reports that rely on this system. Specify what functions, feature or data elements.</td></tr>
<tr>
<td><strong>Data</strong></td><td>Assess data migration complexity and risks (loss, corruption, or transformation). Evaluate current data quality and the effort required to clean or prepare data for migration.</td></tr>
<tr>
<td><strong>Compliance</strong></td><td>Evaluate compliance with your company’s security standards and industry regulations (e.g., SOX, GDPR, HIPAA). Confirm the system supports auditing, reporting, and compliance tracking.</td></tr>
<tr>
<td><strong>DR &amp; HA (Storage &amp; Backup)</strong></td><td>Rate the robustness of backup and recovery processes. Has a backup been successfully tested recently? Can the system recover quickly from an incident?</td></tr>
<tr>
<td><strong>Performance</strong></td><td>Does the system experience frequent downtime, slow performance, or inability to handle current workloads?</td></tr>
<tr>
<td><strong>Reliability</strong></td><td>Does system experience frequent failures, crashes, or instability that impact business operations.</td></tr>
<tr>
<td><strong>Up-To-Date</strong></td><td>Is system on latest version and latest patch set?</td></tr>
<tr>
<td><strong>Obsolete</strong></td><td>Is system receiving updates, patches, or support from the vendor?</td></tr>
<tr>
<td><strong>Security Risk</strong></td><td>Assess the strength of data protection features, including encryption, access controls, role-based authorization (principle of least privilege), and single sign-on.</td></tr>
<tr>
<td><strong>Integration</strong></td><td>Evaluate the availability and robustness of APIs and other integration tools. Can it integrate with modern systems and technologies?</td></tr>
<tr>
<td><strong>Sustainability</strong></td><td>Consider maintainability, configurability, affordability, and long-term viability of the system.</td></tr>
<tr>
<td><strong>Help Desk Requests</strong></td><td>Evaluate ticket counts, ticket type (bugs, feature enhancements), and status (resolved, open) in your Help desk application to understand what systems are high maintenance, have gaps, etc.</td></tr>
<tr>
<td><strong>Talent Risk</strong></td><td>Rate risk in finding talent to upkeep the system.</td></tr>
</tbody>
</table>
</div><hr />
<blockquote>
<p>Once your criteria are finalized, you can begin scoring each system to reveal where modernization and/or retirement efforts will yield the biggest impact.</p>
</blockquote>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In summary, a global system assessment reveals the changes that need to be made in your environment to make the most out of the new ERP. It produces a Decision Matrix highlighting the systems that need to be upgraded, retired or replaced and applications that need to remain to fill gaps the ERP cannot address.</p>
<p>With this list of what systems need to stay or go, you can then estimate your integration, consolidation, decommissioning, licensing and maintenance costs for your ERP project and produce a multi-phase roadmap of which systems to tackle first.</p>
<p>The effort is significant but you only have to do the bulk entry of it once if you use a low-code tool like <a target="_blank" href="https://apex.oracle.com/en/">Oracle APEX</a> to maintain a dynamic, continuously updated system inventory.</p>
<blockquote>
<p>Every great ERP transformation starts with clarity. Your systems assessment is that first step. <strong>Good luck, and enjoy the discovery process! As always, reach out and let me know how it goes.</strong></p>
</blockquote>
<hr />
]]></content:encoded></item><item><title><![CDATA[Essential ERP Tool for Analysis and Issue Resolution]]></title><description><![CDATA[Overview
As an ERP consultant, I frequently need to troubleshoot why something is not working in the ERP or other enterprise system.
Many times, I need access to a system's setups or I need to compare settings between objects or environments. Instead...]]></description><link>https://sandra-suarez.com/essential-erp-tool</link><guid isPermaLink="true">https://sandra-suarez.com/essential-erp-tool</guid><category><![CDATA[ERP]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[orclapex]]></category><dc:creator><![CDATA[sssuarez]]></dc:creator><pubDate>Thu, 27 Jun 2024 03:27:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/CrhsIRY3JWY/upload/bf41e30ab2040a184b552b10af915d7e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-overview">Overview</h3>
<p>As an ERP consultant, I frequently need to troubleshoot why something is not working in the ERP or other enterprise system.</p>
<p>Many times, I need access to a system's setups or I need to compare settings between objects or environments. Instead of having to take screenshots across multiple pages or environments, I use my low-code development tool, Oracle APEX, to quickly gather all the data in one place.</p>
<p>Take this recent example where I was guiding my client through an ERP upgrade from Oracle EBS (E-Business Suite) to Oracle Fusion Cloud. My client had 40+ Item Templates and needed guidance on how to best consolidate the 40+ templates to an essential few. When you realize that each template contains 300+ attributes, you are comparing a matrix with over 12,000 values. A typical ERP form is unable to display all 300+ attributes in one page, so it forces you to scroll down 18-20 times to get to the last attribute, <strong><em>per template</em>.</strong></p>
<p><strong>Scrolling through the hundreds of attributes in Oracle Cloud Fusion</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718908372405/541f6440-4120-4dab-a052-61b2476e0ccf.gif" alt class="image--center mx-auto" /></p>
<p><strong>Scrolling through the hundreds of attributes in Oracle EBS</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718908332914/ac44f1be-6eb4-4122-83aa-48a5fa1500ab.gif" alt class="image--center mx-auto" /></p>
<p><strong>There is a better way.</strong></p>
<h3 id="heading-better-ways-to-see-your-data">Better Ways To See Your Data</h3>
<p>As you can see from the GIFs above, I need a more effective way to display and analyze my 12,000+ data points. Here is my workflow to quickly transform my data:</p>
<ol>
<li><p>Extract data from the enterprise system</p>
</li>
<li><p>Download the data to Excel or csv</p>
</li>
<li><p>Upload file to Oracle APEX</p>
</li>
<li><p>Explore and analyze in APEX</p>
</li>
</ol>
<h3 id="heading-extract-data-from-the-enterprise-system">Extract data from the enterprise system</h3>
<p>I leverage <strong>SQL Developer</strong> for querying Oracle EBS records and <strong>BI Publisher</strong> for querying from Oracle Fusion. I find these tools offer the most efficient way of extracting setups and other necessary data from either ERP system.</p>
<p><strong>My Data using the BI Publisher Tool in Oracle Fusion</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718909372713/45c1712f-f112-4eea-87a8-518b1e97d009.jpeg" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718909384073/db57191f-4dc2-4935-a9e0-99c55dec850d.jpeg" alt class="image--center mx-auto" /></p>
<p><strong>My Data using SQL Developer for Oracle EBS</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718909273531/7a7b6c02-0837-4fd3-81c4-da94fdcb8b4f.gif" alt class="image--center mx-auto" /></p>
<p>As you can see, these formats do not offer an optimal way of studying my data points.</p>
<h3 id="heading-download-data-to-excel">Download data to Excel</h3>
<p>Excel is a close second when it comes to analyzing data. I can filter, pivot and transform data to my heart's delight.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718922057406/ea7cfc37-6041-47a7-8e75-733febf2fde2.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-upload-data-to-oracle-apex">Upload Data to Oracle APEX</h3>
<p>But look how much easier and funner (is this a word?) APEX makes this task for me. End users find this format simpler and more pleasant to work with. Compare the following two GIFs with the first two on this post - no comparison really.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718938946388/9285c3e7-9d47-4d12-999e-ec2baf524a25.gif" alt class="image--center mx-auto" /></p>
<p>This app took me two minutes to create, with just the upload of my file (<a target="_blank" href="https://apex.oracle.com/en/learn/build-your-first-app/">here's how</a>).</p>
<p>Notice the Faceted Search feature displayed on the left hand side of the page. APEX automatically detects the 'categories' in my file and builds the feature for me. The Search box feature is also automatically built-in, as displayed below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718939127767/ea98458c-937c-497c-b184-d8b5fc049e88.gif" alt class="image--center mx-auto" /></p>
<p>This <a target="_blank" href="https://blogs.oracle.com/apex/post/faceted-search-enhancements-in-apex-202">post</a> on Faceted Search by Monica, from the APEX Development team, shows how APEX automatically builds dashboards and charts for each of your facets too.</p>
<p>These UIs makes a powerful statement when you're presenting in a meeting. The client loved this view of their setups so much they asked us to make it a permanent, real-time page in their Production environment. To transform this to a long-term solution, we built an integration to integrate the template data in ERP with APEX. This allowed us to provide additional features such as 1) dynamically adding templates when new ones were created in the ERP and 2) allow users to filter by template. See below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719454272146/a951e3ba-abc5-4d75-8e94-14410eae84d5.png" alt class="image--center mx-auto" /></p>
<p>Consequently, we ended up transforming other settings, setups, and similar pages to APEX as well.</p>
<blockquote>
<p>Introduce APEX for one task, and you'll be asked to apply it everywhere in the company :)</p>
</blockquote>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Even if your client does not have Oracle APEX enabled in their Oracle database, you can still use a free version of APEX. Upload the file to a free APEX workspace available on <a target="_blank" href="https://apex.oracle.com/en/learn/getting-started/">apex.oracle.com</a> or upload the file to your own environment on the <a target="_blank" href="https://apex.oracle.com/en/learn/getting-started/">OCI Free Tier</a>.</div>
</div>

<p>And...</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">If you're new to APEX, follow the instructions on this <a target="_blank" href="https://apex.oracle.com/en/learn/build-your-first-app/">APEX link</a> to quickly create an APEX app from a spreadsheet. It's seven easy steps! Really!</div>
</div>

<h3 id="heading-explore-amp-analyze-with-oracle-apex-other-tools">Explore &amp; Analyze with Oracle APEX + Other Tools</h3>
<p>APEX is a terrific starting point for visualization and analysis of large amounts of data. I complement it with advanced SQL queries to compare data across columns and identify patterns.</p>
<p>As a fun exercise, I uploaded my file up to ChatGPT to see if it could find similarities across templates. Here's what it returned:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718937154852/610a1007-62cf-4ef1-ae23-273b86b43e77.png" alt class="image--center mx-auto" /></p>
<p>And...</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718937169436/bde4ba9c-5609-4c2e-94fd-c9a076075e73.png" alt class="image--center mx-auto" /></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Note: I found ChatGPT's results to be about 90% accurate, so it is important to conduct your own thorough review.</div>
</div>

<p>These pointers from ChatGPT are excellent starting points for any analysis. In order to consolidate the templates from 40 to a few, however, requires in-depth understanding of the dependencies <em>AND</em> inter-dependencies between the 300 attributes as well as their impact to other setups across the ERP. Mapping the features and functions of these attributes with the ultimately business goals of the client, is what allows me to eventually narrow down the number from 40 to five. AI can't do this for us..<strong><em>.yet</em></strong>.</p>
<h3 id="heading-summary">Summary</h3>
<p>Transforming settings, setups and similar pages are one of my favorite use cases for using Oracle APEX to simplify the view of data. With APEX's easy file upload, I can transform any file into a modern, UI-friendly web page in just seven steps and under two minutes. And its automatic faceted search capability accelerates my data analysis because I can focus on identifying patterns, similarities, and variances in my data instead of building and coding an app.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">⚠</div>
<div data-node-type="callout-text">A word of caution: introduce APEX to one part of your enterprise, and it soon becomes the requested go-to-solution for everything :)</div>
</div>

<p>I hope this post encourages you to use Oracle APEX to debug and troubleshoot your next issue. It makes me look good in front of clients, every time. :).</p>
]]></content:encoded></item><item><title><![CDATA[Modernize Order To Cash without replacing your ERP]]></title><description><![CDATA[If you've been looking for confirmation whether it's possible to successfully modernize your order to cash and supply chain applications without having to customize, upgrade or replace your ERP, this post is for you. The solution below is the most so...]]></description><link>https://sandra-suarez.com/modernize-order-to-cash-without-replacing-your-erp</link><guid isPermaLink="true">https://sandra-suarez.com/modernize-order-to-cash-without-replacing-your-erp</guid><category><![CDATA[ERP]]></category><category><![CDATA[orclapex]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Supply Chain Management]]></category><category><![CDATA[Low Code]]></category><dc:creator><![CDATA[sssuarez]]></dc:creator><pubDate>Thu, 06 Jun 2024 23:48:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1717635892053/781fa1c5-8933-4c88-a02c-90f87d7c506a.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've been looking for confirmation whether it's possible to successfully modernize your order to cash and supply chain applications without having to customize, upgrade or replace your ERP, this post is for you. The solution below is the most sought-after demo by our customers. Why? Because it proves that a multi-billion dollar enterprise can run its end-to-end, high volume Order To Cash operations on a low-code platform, in sync with its legacy ERP.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Although the solution described revolves around the Oracle ecosystem, Oracle ERP and Oracle APEX, the principles apply with any ERP (SAP, Microsoft Dynamics, Net Suite, etc.).</div>
</div>

<p>Here's what I'll cover:</p>
<ol>
<li><p>Why is Order To Cash so hard?</p>
</li>
<li><p>My customer's problem statement</p>
</li>
<li><p>Oracle APEX to the rescue</p>
</li>
<li><p>Approach and design principles</p>
</li>
<li><p>Tools and Integrations</p>
</li>
<li><p>Results</p>
</li>
</ol>
<h2 id="heading-why-is-order-to-cash-so-hard">Why is Order To Cash so hard?</h2>
<p>Order To Cash, typically abbreviated as OTC or O2C, spans multiple functions including sales, credit, demand planning, inventory, warehousing, shipping, finance, collections and customer support. The numerous hand-offs, dependencies and exceptions situated across departments make automation and efficiencies difficult to achieve. And the more product lines, revenue models and fulfillment channels introduced, the more moving parts are put in motion, further compounding the problem of reaching cross-functional alignment and efficiencies.</p>
<p>Per a recent <a target="_blank" href="https://www.bcg.com/publications/2020/order-to-cash-platforms-are-the-future">Boston Consulting Group article</a>,</p>
<blockquote>
<p>"Our analysis of O2C in a sample of manufacturing and service companies found that it comprised as many as 27 sub-processes across seven different functions. That’s why O2C often falls between the cracks or is regarded as being too complicated to re-engineer."</p>
</blockquote>
<p>No two companies perform O2C in the same way, making it almost impossible for ERPs and other systems to provide standardized offerings.</p>
<blockquote>
<p>"In the two decades I have spent leading O2C ERP transformation programs at companies, all have used ERPs to automate the backend financial processes. And, all of them relied on custom applications and manual processes when it came to order-to-cash.” - <a target="_blank" href="https://www.forbes.com/sites/forbestechcouncil/people/nishantnair1/">Nishant Nair</a>, CEO of <a target="_blank" href="https://www.recvue.com">RecVue</a> (<a target="_blank" href="https://www.forbes.com/sites/forbestechcouncil/2021/05/13/what-to-look-for-in-order-to-cash-technology/?sh=59d14bdb323b">Forbes article</a>)</p>
</blockquote>
<p>This variability across companies and industries presents <strong>an optimal opportunity for a low-code development platform such as Oracle Application Express (</strong><a target="_blank" href="https://apex.oracle.com/en/"><strong>APEX</strong></a><strong>)</strong> to meet a company's O2C needs. APEX offers the flexibility to build only the features you need today, with the malleability to enhance and adapt them for the future.</p>
<h2 id="heading-my-customers-problem-statement">My Customer's Problem Statement</h2>
<p>My client needed the ability to fast-track the order to cash operations for a company they had just acquired.</p>
<p>The acquired company objected to using an ERP to run its operations because it perceived ERP as too slow and complex and required too many windows and clicks. They believed an ERP could not compete in speed, performance, or efficiency with the QuickBooks solution they had configured to meet their exact needs.</p>
<p>So we were tasked with moving them away from QuickBooks to a solution that would not only meet the acquired company's expectations of speed and ease of use, but also seamlessly integrate with the existing ERP, ensuring a smooth and efficient transition.</p>
<p>The reluctance to move away from what they had in place today was so strong, I had to <strong><em>gamify</em></strong> the situation with a challenge. I proposed to the head of the acquired company that if the demo of our solution did not beat their current system in speed, performance and enhanced features, they didn't have to move. "<strong>Game on!</strong>", he proclaimed. The challenge was on!</p>
<h2 id="heading-oracle-apex-to-the-rescue">Oracle APEX to the rescue</h2>
<p>The initial aim was to deliver a solution entirely within Oracle ERP. However, if the solution proved unfeasible, our backup plan was to construct a custom web app with integrations to the parent company’s Oracle ERP.</p>
<p>They were right—ERP was slow and drawn out. Compared to their existing solution, it required many more forms, fields, pop-ups, and clicks to operate O2C end-to-end, and it took three times as long. ERP was a no-sell. A custom app was going to be the best route forward.</p>
<p>Good news—Oracle APEX is quick for standing up an application. Within a week, we had a working demo. Oracle APEX to the rescue!</p>
<h2 id="heading-approach-and-design-principles">Approach and Design Principles</h2>
<p>An important design principle for custom enterprise apps is to <strong><em>design the custom app in lock-step with EBS the entire way</em></strong>. We referenced customers, suppliers, and items from the ERP and took advantage of standard ERP APIs to decrement inventory and generate invoices.</p>
<blockquote>
<p>Table 1: Data Objects &amp; Transactions Leveraged in the ERP</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717625512078/dd62db6a-9b67-4787-b8ee-992cc4db0f50.png" alt class="image--center mx-auto" /></p>
<p>All these links minimized duplicity and ensured Oracle ERP remained the source of truth for master data and transactions.</p>
<p>Note - there is more to an ERP than just data and transactions. One of the primary reasons to have an ERP is to take advantage of its <strong>business rules and recommendation engines.</strong> These engines are powerful - they automate decision-making and enforce policies and procedures. We synced APEX with three key Oracle ERP robust engines:</p>
<blockquote>
<p><strong>Table 2: ERP Business Rule &amp; Recommendation Engines</strong></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717625725541/fc918af3-082d-4a46-a561-cc5d3d4758c9.png" alt="A table showing 3 ERP Business Rule and Recommendation Engines including a Credit Check Engine and ATP and Scheduling Engine." class="image--center mx-auto" /></p>
<p>Having said all the above, it does not always make sense to originate all objects from the ERP. Our design tenets guide us to prioritize the user experience, simplicity, and longevity of the APEX apps we build. Thus, we created and maintained sales orders, pricing rules, work orders, and shipments, fully confined within the low-code app.</p>
<blockquote>
<p><strong>Table 3: Entities and Transactions Unique to APEX</strong></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717626028470/728fc89c-3618-4637-81d7-68a6fb001365.png" alt class="image--center mx-auto" /></p>
<p>Designing in lock-step with ERP can also mean complementing the ERP in a modular approach. As the list above shows, we built these four "modules" to house the transactions completely outside the ERP. The flexibility of our APEX platform allows us to amend or replace these 'modules' as future requirements dictate.</p>
<hr />
<p>As mentioned earlier, a second design principle is <strong><em>designing for longevity</em></strong>. It's essential to avoid hard-coding whenever possible. Instead, consider storing variables in ERP constructs like ERP profile options and lookups or opt for the creation of custom tables managed by APEX pages. This approach avoids the pitfalls of hard coding and allows business users to update the variables themselves instead of relying on a code update.</p>
<hr />
<p>There are many other design principles for building enterprise apps, but I'll end with a third one: <strong><em>optimizing the user experience</em>.</strong> To optimize the UI experience, we designed the most frequently used functions to be accessible from one place—an OTC workbench. It provided buttons for saving, booking, generating a work order, printing paperwork, shipping, and invoicing all on one page. No more having to go to multiple pages to perform or access a function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717636426987/e63ae1bc-dfce-4e5d-873e-dd0fb136d121.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717631107175/0e4eb9b3-bfae-4b2c-b020-ced3bb8b7aca.png" alt class="image--center mx-auto" /></p>
<p>Every potential click was evaluated and optimized. We utilized defaulting-rule logic wherever possible and placed the fields in the exact sequence they needed. we ensured users never had to lift their hand to move a mouse; every section and button could be activated with keyboard clicks, eliminating steps and clicks along the way.</p>
<p>One key win was automating seven procedures, all with the click of one button.  We called it “Rocket Ship”. See table below for the seven procedures it automates for end users.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717631094286/07e214ca-e85c-48dc-999e-64e313f995cd.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>Table 4: Procedures the Rocket Ship automates for end users</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717628968617/7c292f39-99df-4f3a-8072-dfb63077d57f.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-tools-amp-integrations-used">Tools &amp; Integrations Used</h2>
<p>No enterprise app worth its weight stands alone. Here's a list of key integrations we built:</p>
<blockquote>
<p>Table 5: Integrations with our low-code APEX application</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717628517714/ce47710a-da37-46d4-b337-3c0ac577097e.png" alt="Table showing integrations with Oracle APEX including APEX Office Print and AWS S3. " class="image--center mx-auto" /></p>
<p>Integration between APEX and Oracle ERP is easy. If you're on an Oracle ERP EBS version, both APEX and ERP are in the same database, so it’s as simple as a SQL query or PL/SQL call to the specific table and column in the database - no API or Web Service configuration required. If you're on Oracle Fusion Cloud ERP, it's hosted by Oracle, so you'll need to stand up another Oracle database to host APEX. For examples of where to host, see <a target="_blank" href="https://www.oracle.com/application-development/apex/">Oracle APEX Service</a> or the <a target="_blank" href="https://www.oracle.com/autonomous-database/">Autonomous Database Service on OCI</a>.</p>
<h2 id="heading-resultshttpswwworaclecomautonomous-database"><a target="_blank" href="https://www.oracle.com/autonomous-database/">Results</a></h2>
<p>It took two of us (me and a developer) less than six months, start to finish, to gather requirements, prototype, design, build, iterate, iterate, and iterate and then launch to Production. This included full integration of the app's inventory and revenue transactions with Oracle Financials. The build was the easy part. The bulk of the time was spent educating my client on the features of ERP they could now take advantage of and redrawing their business process for optimal efficiency.</p>
<p>Automation and optimization of the user experience reduced order processing overhead by 80% compared to their legacy Quickbooks application.</p>
<p>And the 'Rocket Ship' button enabled no-touch order processing for 30% of orders. That's over seven clicks per order. if you extrapolate that over all its plants, that’s a savings of over 1/2 million clicks per year. Not to mention the context- switching each user saves - users only have to attend to an order once.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🎲</div>
<div data-node-type="callout-text"><strong><em>And the bet with the Head of the acquired company - Oracle APEX kicked butt!</em></strong></div>
</div>

<p>APEX came out ahead of Quickbooks in terms of speed, scale, performance, accuracy and enhanced features to their legacy system.</p>
<h1 id="heading-summary">Summary</h1>
<p>OTC is universal. Every company that sells a product or service engages in O2C operations, and each company's O2C workflows are unique. The variables, hand-offs, and exceptions involved in O2C demand a tailored solution for most.</p>
<p>The flexibility, security, and performance provided by Oracle APEX and its pre-built integrations with Oracle ERPs allow you to make the most of your ERP investment.</p>
<p><em>This post could have easily been 10,000 words—there is so much I didn't get to cover when enhancing an ERP with an app that spans multiple departments and processes. Optimizing ERPs is my passion—reach out if you'd like more information regarding this use case or if you'd like to bounce ideas about how this could work in your environment.</em></p>
]]></content:encoded></item><item><title><![CDATA[Eliminate duplicates in  your ERP with a 'fuzzy match' algorithm]]></title><description><![CDATA[The solution below has proven successful at multiple Oracle ERP clients, so I am sharing it here in the hopes it inspires and helps others in a similar situation. Read on to learn how we:

eliminated customer duplicates with the introduction of an "a...]]></description><link>https://sandra-suarez.com/duplicate-records-with-fuzzy-match-algorithm</link><guid isPermaLink="true">https://sandra-suarez.com/duplicate-records-with-fuzzy-match-algorithm</guid><category><![CDATA[ERP]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[orclapex]]></category><category><![CDATA[algorithms]]></category><category><![CDATA[user experience]]></category><dc:creator><![CDATA[sssuarez]]></dc:creator><pubDate>Fri, 18 Nov 2022 21:19:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1667857610271/BeS17E1zr.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The solution below has proven successful at multiple Oracle ERP clients, so I am sharing it here in the hopes it inspires and helps others in a similar situation. Read on to learn how we:</p>
<ol>
<li><p>eliminated customer duplicates with the introduction of an "approximate string matching" algorithm</p>
</li>
<li><p>simplified the customer-creation process by reducing the number of forms and clicks required by over 65% with the introduction of an Oracle APEX web app</p>
</li>
</ol>
<h2 id="heading-the-problem-statement">The Problem Statement</h2>
<p>A client ended up with many duplicate customer records, so many that they were running the Oracle ERP Customer Merge program every quarter. In merger and acquisition environments, it is common for the acquirer and acquired companies to share the same vendors and customers. This was certainly the case with a client. But how does the ERP, the source of record, end up with duplicate customers? Here's how:</p>
<ol>
<li>Oracle EBS does not enforce uniqueness in the customer name. For example, users were able to create "Cannon Industries" twice, each with a different customer account number:</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668120935826/w-h42BW_S.png" alt="CANNON.png" /></p>
<ol start="2">
<li>It also does not auto-enforce naming standards. For example, “Golfsmith Inc” versus "Golfsmith Inc.“ with a period versus "Golfsmith Incorporated" can all be created. In the screenshot below, the three entries below for "Southeastern Metal Products" represent the same customer and address, but to the ERP system, they represent three distinct customers:</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668113927159/ieXLjwAqE.png" alt="SEMETAL.png" /></p>
<ol start="3">
<li><p>The Oracle Customer form does provide the ability to search for a customer. However, it is optional, meaning the user can bypass the search and proceed directly to creating a duplicate customer without any alert or notification.</p>
</li>
<li><p>Even if the user were to perform a search, the search is not effective. For instance:</p>
<ul>
<li><p>"Golfsmyth" with a "y" does not return existing customer “Golfsmith” with an "i"</p>
</li>
<li><p>"Golfsmith Inc" would not return existing customer "Golfsmith Incorporated" unless the user knew or remembered to search with a % wildcard operator after the word "Inc".</p>
</li>
</ul>
</li>
</ol>
<p>Notice the customer entries for "All Metals Fabricating" below. When creating a sales order, which one should an end user choose? Randomly choosing one over the other will split the customer revenue across the two records.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668121310404/53CNZh87S.png" alt="ALLMETALS.png" /></p>
<ol start="5">
<li>Sitting down with end users revealed another obstacle. Users indicated the Customer form is overwhelming. They claimed that "editing a customer involves many nested tables and it’s easy to get lost. It feels safer to create a new customer than to edit an existing one".</li>
</ol>
<p>Note the screenshot below - the customer "National Switchgear" has four active customer accounts in the ERP. Which one should the end user choose to transact with or update?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668121402666/MwYX41gw9.png" alt="NATIONAL.png" /></p>
<p>Conclusion: the complexity of the existing Customers Form and the shortcomings of the search feature to identify exact and near-duplicates all contributed to bloated Customer Masters across many clients.</p>
<h2 id="heading-the-approach">The Approach</h2>
<p>Addressing the five root causes above required a two-prong approach:</p>
<ol>
<li><p>identify and display exact and near duplicates to the end user</p>
</li>
<li><p>simplify the view, edit and customer creation process in the existing Customer Master forms to address the fear and reluctance experienced by end users</p>
</li>
</ol>
<h3 id="heading-fuzzy-match">Fuzzy Match</h3>
<p>Oracle ERP documentation and Oracle Support websites offer methods to resolve duplicates, not prevent them, so we needed to think outside the box.</p>
<blockquote>
<p><strong>Note:</strong> Oracle EBS may offer near-duplicate search functionality with the license, use and configuration of the Data Quality Management and/or Customer Data Hub modules. These modules are not common; thus, this solution is applicable and popular with many Oracle EBS customers.</p>
<p>Oracle Cloud ERP also offers near-duplicate search functionality for customer search, but it may require additional licensing and tools such as Enterprise Data Quality, etc.</p>
</blockquote>
<p>An Oracle search to resolve data duplicates lands on a <a target="_blank" href="https://blogs.oracle.com/search.html?q=UTL_MATCH">blog</a> by Richard Williams describing three helpful algorithms supported by the Oracle DB:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668705026313/6jZwD0PF6.png" alt="oracle blog.png" /></p>
<p>A <a target="_blank" href="https://stackoverflow.com/questions/9398794/advanced-string-comparisons-in-oracle-sql/9398925#9398925">Stack Overflow Page</a> also describes “duplicate records that are similar but aren’t exact matches”.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667875874534/XXdWQOlvZ.png" alt="stackoverflowresult.png" /></p>
<p>They both describe a Jaro-Winkler algorithm, which was developed by the US Census Department. The algorithm returns a matching score when performing a search between 0 and 100: 0 meaning no match, and 100 meaning a perfect match. It is considered a "Fuzzy search" algorithm because it finds patterns in strings (approximate string matching) for entries that are approximately similar but are not precisely the same - Bingo for our use case!</p>
<p>The Jaro-Winkler algorithm is implemented as a <a target="_blank" href="https://docs.oracle.com/en/database/oracle/oracle-database/21/arpls/UTL_MATCH.html#GUID-7F579819-995A-4E92-862A-3E9ED13AA236">PL/SQL function</a> in the Oracle Database:</p>
<pre><code class="lang-plaintext">UTL_MATCH.JARO_WINKLER_SIMILARITY (
   s1  IN  VARCHAR2, 
   s2  IN  VARCHAR2) 
 RETURN PLS_INTEGER;
</code></pre>
<p>Running the function in our <a target="_blank" href="https://www.oracle.com/cloud/free/">Oracle APEX test environment</a> resulted in the following match scores when entering "GOLFSMITH" as a potential customer:</p>
<ul>
<li><p>match score of 88% when compared to "Golfsmith Incorporated"</p>
</li>
<li><p>match score of 90% when compared to "Golfsmyth Inc." with a "Y"</p>
</li>
<li><p>match score of 92% when compared to "Golf Smith", spelled out as two words</p>
</li>
<li><p>and of course, a match score of 100% when compared to existing customer "Golfsmith"</p>
</li>
</ul>
<p>See results in screenshot below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668125908976/p9EVUNGb1.png" alt="GS Results.png" /></p>
<p>This approach elegantly addresses exact as well as near-duplicate conditions. It highlights instances of misspelled words, abbreviations, punctuation, etc. - something very hard to do with our customers' current functionality.</p>
<p>Here's a snippet of the exact code deployed to get the results above:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668126877786/69V3aGB6j.png" alt="codesnippet.png" /></p>
<p>Here are a few things to call out:</p>
<ul>
<li><p>Line 10: Here is where I call out the algorithm and assign it a column name of "MATCH_SCORE". UPPER function transforms both fields, the entered value and the value in the customer name column to uppercase to eliminate any potential case sensitivity.</p>
</li>
<li><p>Line 20 - 24: I wanted match score results greater than 75 to be highlighted in blue, and thus, created a "HIGH_MATCH" function to do just that. The immediate screenshot below shows the CSS that turns match scores over 75 to blue. The CSS is captured in the Page section of the APEX web form.</p>
</li>
<li><p>Line 26: This line restricts results to display only those with a match score &gt;= 65.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668129283894/-Eg7fskVF.png" alt="Inline Highlight.png" /></p>
<h3 id="heading-simplifying-the-customer-create-form">Simplifying the Customer Create Form</h3>
<p>We concluded that replacing the multi-nested Oracle Customer forms with a one-page Oracle APEX web app would be safer and simpler. Here's how we went about it:</p>
<ul>
<li><p>we gathered data and feedback from end users from multiple sites</p>
</li>
<li><p>we sat with users to observe each keyboard click, decision, pause and hesitation</p>
</li>
<li><p>we recorded user screens to further study every click, response and movement</p>
</li>
</ul>
<p>This trove of data allowed us to design the APEX web app in such a way that:</p>
<ul>
<li><p>every field was placed in the exact sequence needed.</p>
</li>
<li><p>every section, field and button could be activated with a keyboard click. Users would never have to lift their hand to move a mouse.</p>
</li>
<li><p>every potential click was evaluated and optimized. We used Dynamic Actions in Oracle APEX to control the tab order between fields.</p>
</li>
</ul>
<p>In all, we optimized the customer creation page to just 10 essential fields. We replaced the multi-page, multi-nested, 60+ fields on the Oracle ERP Customers forms with a lightweight, fit-for-purpose Oracle APEX web page.</p>
<p>There are two additional design principles we incorporated:</p>
<ol>
<li>Design the Oracle APEX web apps in lock-step with EBS.</li>
</ol>
<p>Using Oracle APEX, we utilized the Oracle EBS TCA public PL/SQL APIs to create and update customers. And because APEX is in the same database as Oracle EBS, we could query customer data directly from the customer tables. This integration minimized duplicity and ensured Oracle ERP remains the source of truth for all Customer records.</p>
<p>We also took advantage of EBS features such as lookups and address-style and tax-code formats so we didn't have to maintain them in two different places.</p>
<ol start="2">
<li>Second design principle: when we built the web app, we built the customer creation process as a workflow to drive user behavior.</li>
</ol>
<ul>
<li><p>In the new APEX app, Customer Search was no longer optional. To create a new customer, users must type the customer name in a field and press submit. The algorithm would then return a listing of possible matches, along with a match score.</p>
</li>
<li><p>Each possible customer match was a link that, when clicked, displayed customer details via a pop-up with essential fields users rely on to determine if this is the customer they need</p>
</li>
<li><p>Suppose the customer is indeed the one the user needs. In this case, the user is allowed to perform edits as needed or, with the click of a button, automatically be navigated to the sales order form with that customer already populated on a new order</p>
</li>
<li><p>Otherwise, if the customer is not found, the user would select a button we named "Customer Not Found, Proceed With New Customer". By naming the button in this way, we force the user to review potential duplicates and acknowledge that a duplicate does not exist.</p>
</li>
</ul>
<h2 id="heading-the-results">The Results</h2>
<h3 id="heading-performance">Performance</h3>
<p>In Production EBS environments with up to 10,000 customers, it took no more than two seconds for the Jaro-Winkler algorithm to return search results. That's pretty impressive, considering the algorithm calculates and returns a match score for every customer record in the Customer Master.</p>
<p>If a client ever had over 100,000 customers, one could tailor the solution by introducing filters to limit the search to only customers of a specific profile class, country, or other classification. Such a filter would take careful consideration because you could end up filtering out a duplicate classified incorrectly. I'll share in my next blog tactics to improve performance and match score results by using filters, removing common business terms such as "The", "Inc.", "Incorporated", "LLC", and "Limited" from the search and introducing additional algorithms.</p>
<p>For example, Oracle DB also supports sound and phonetics-based matching via the SOUNDEX function. In our case, we are solving for misspellings and lack of auto-enforced standards such as "Inc." versus "Incorporated", and thus, "approximate string matching" addressed our use case well enough. However, laying such an algorithm on top of Jaro-Winkler should, in theory, improve the match score.</p>
<h3 id="heading-business-impact">Business Impact</h3>
<ol>
<li>Benefits of a clean Customer Master compound over time every time. Take a look at these wins:</li>
</ol>
<ul>
<li><p>Within months, duplicates trended to zero. Not having customers represented across multiple accounts improves the accuracy for each of the following:</p>
<ul>
<li><p>Customer credit check - results in the improved vetting of customer creditworthiness</p>
</li>
<li><p>Customer sales - improves accuracy for trends and forecasting projections</p>
</li>
<li><p>Customer service - reps no longer have to guess which of the multiple accounts assigned to a customer to tag for a particular issue.</p>
</li>
<li><p>Customer marketing - improves reach for marketing campaigns and loyalty programs</p>
</li>
<li><p>Customer reporting - results in more accurate reporting for gross profit and operating margins</p>
</li>
<li><p>Customer sales rep compensation - results in more accurate calculations</p>
</li>
</ul>
</li>
</ul>
<ol start="2">
<li><p>The solution reduced the number of steps and clicks for creating and managing customers by over 65%. Per users, the solution also reduced anxiety as they could now rely on quantifiable search results.</p>
</li>
<li><p>And this one is my favorite: the solution was initially rolled out to just one division in the company. Word spread of this solution's success and we were asked to extend it to other divisions. There is no better measure of success than a repeat customer :)</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The business impact spelled out above highlights the detrimental impact if your data, particularly your customer master, is not clean. This impact would also apply to vendors, products, raw materials, user logins, etc.</p>
<p>The beauty of this solution is that it not only replaces a reactive workaround (running the Customer Merge Process to address duplicates), it gets down to the root cause and addresses it.</p>
<p>Many methods, tools and algorithms are available to help tackle data duplicates in the enterprise. I hope the approach above inspires you with ideas and action to prevent duplicates in your environments too.</p>
]]></content:encoded></item><item><title><![CDATA[Generate Data Fast with Oracle APEX Data Generator]]></title><description><![CDATA[Introduction
A high-quality application relies on thorough testing.   Generating sample data fast is vital for keeping up with today's world of Agile and condensed timelines.  Traditional methods for generating data have too many downfalls: manual ma...]]></description><link>https://sandra-suarez.com/apex-data-generator</link><guid isPermaLink="true">https://sandra-suarez.com/apex-data-generator</guid><category><![CDATA[orclapex]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[ERP]]></category><category><![CDATA[data]]></category><dc:creator><![CDATA[sssuarez]]></dc:creator><pubDate>Fri, 29 Jul 2022 19:14:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1659116029694/jFwXzkahQ.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>A high-quality application relies on thorough testing.   Generating sample data <em>fast</em> is vital for keeping up with today's world of Agile and condensed timelines.  Traditional methods for generating data have too many downfalls: manual manipulation of production data is slow and error-prone and 3rd party tools, require a fee-based model or if free, a compromise in features and support. </p>
<p>Enter <strong>Oracle APEX Data Generator (OADG)</strong>, a SQL Workshop utility tool available in Release 22.1 (May 2022).  It generates large volumes of data for you, in the millions, in multiple formats (CSV, JSON, SQL) utilizing a vast library of data types.  Its simple UI and workflow, along with its price (it's free!), make it an all-around winner over the multitude of alternatives out there.</p>
<p>Continue reading to discover why I think OADG is great, why you should use it over other options and how to set up and use it.  I've also thrown a section on hints and tips I picked up along the way along with features I would ❤️ to see in the future.  </p>
<h2 id="heading-why-its-great">Why It’s Great</h2>
<p>The new tool is feature-rich, compared to the alternatives, both free and paid.  And it's just in its first version.  Its features include:</p>
<ul>
<li>Generates data in multiple formats (JSON, CSV, SQL)</li>
<li>If you prefer, it inserts data directly into your existing table(s)</li>
<li>Generates a million rows of sample data, with and without complex formulas, within 5 minutes</li>
<li>Supports functions available in SQL for data transformations and derivations such as:<ul>
<li>DB functions, e.g., TRIM, LPAD, RPAD, CASE, CONCAT</li>
<li>DB PL/SQL functions, e.g., DBMS_RANDOM.value</li>
<li>your own custom PL/SQL functions</li>
</ul>
</li>
<li>Supports use  of SQL query results to populate your columns</li>
<li>Supports foreign keys to generate consistent data across your tables and columns </li>
<li>Supports the reuse of previously-defined data definition templates, known as blueprints, so you can generate data over and over again</li>
<li>Provides ability to preview your data while you are building out the definition</li>
<li><p>Provides a vast library of data types to generate sample data including date and time, integers, boolean, products, persons, plants, food, cars, animals, etc.  And for each data type, a series of attributes are available to provide context to your data.  For example, </p>
<ul>
<li><strong>Persons data type</strong> includes attributes such as first name, last name, biological sex, email address, etc.</li>
<li><strong>Airport data type</strong> includes airport type, city, country, latitude, longitude, etc. </li>
<li><strong>Car data type</strong> includes make, model, drivetrain and many others as illustrated in screenshot below: </li>
</ul>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658877845798/4Pa4rYBkU.png" alt="car data type.png" /></p>
<p>APEX makes the sample data types and their respective values available to query via the the <a target="_blank" href="https://docs.oracle.com/en/database/oracle/apex/22.1/aeapi/GET_EXAMPLE-Function.html#GUID-6DD10BBA-BCF7-4826-9953-F33B5F043606">GET_EXAMPLE function</a>.  For example, the query below will generate all cities available for the data type "airport": </p>
<pre><code class="lang-SQL"><span class="hljs-keyword">select</span> * 
<span class="hljs-keyword">from</span> apex_dg_data_gen.get_example
           (p_friendly_name =&gt; <span class="hljs-string">'airport.city'</span>, p_rows =&gt; <span class="hljs-number">100</span>);
</code></pre>
<p>The p_friendly_name variable may be found in the app declaratively:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658941566132/Tv8tPFBxP.png" alt="Friendly_name mapping.png" /></p>
<blockquote>
<p>I downloaded the APEX 22.1 Install and found the script that generates all the data types, attributes and values. You can view all sample data <a target="_blank" href="https://sandrablogs.s3.us-west-2.amazonaws.com/OADG_built_in_sample_data.sql.zip">here</a>. </p>
</blockquote>
<ul>
<li>And if the above data types do not meet your needs, <strong>BYOD</strong> - import your own data and let the OADG transform it as needed.  </li>
</ul>
<h2 id="heading-why-your-team-needs-oadg">Why Your Team Needs OADG</h2>
<p>TLDR - Because it saves time. Testers no longer have to search or wait for data. </p>
<p>Oracle ERP, APEX and other app implementations typically require a combination of the following for testing: </p>
<ul>
<li><strong>Custom Code</strong> - developers build PL/SQL packages to generate large numbers of records for volume testing</li>
<li><strong>Excel Hell </strong>- analysts and end users download a copy of Production records into Excel and then apply a series of formulas and functions by column to generate unique records.  Users then hand-off to developers to load the records into the app or interface.  </li>
<li><strong>3rd-Party Tools</strong> - hundreds of open source (free) and pay-as-you-go tools are available for generating test data.  However, you need to consider factors like supported databases, data generation methods, data types available, cost and support. </li>
</ul>
<p>OADG allows your team to bypass all these concerns, and what's more, it's free, fast and easy to use.  </p>
<p><strong>A quick note on reusing Production Data</strong> - relying on production data introduces risk as this data typically represents 'perfect' data that has already been vetted. To thoroughly test your new app, integration or business logic, your test data needs exceptions, anomalies, negative outliers and other invalid data to rigorously prove out your app and any ETL routines.  </p>
<p>Be a hero and provide them OADG! </p>
<blockquote>
<p>Tip:  Data Generation tools are typically not applicable for ML use cases as you do not want to feed algorithms randomly-generated data.  You need some data correlation across your columns so your algorithm can learn.</p>
</blockquote>
<h2 id="heading-setting-up-andamp-using-oadg">Setting up &amp; using OADG</h2>
<p>The best way to illustrate this feature is through an example.  We'll use a simple Product table with a relational dependency to the Product Categories table:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659111706300/_LdZ1dmSa.png" alt="deptable.png" /></p>
<p>Here's a visual of the workflow for data generation: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658980710520/MLz8SOpba.png" alt="workflow.png" /></p>
<h3 id="heading-1-create-blueprint">1. Create Blueprint</h3>
<p>As depicted in the workflow above, the first step to generating data is to capture the definition of your tables and columns via a Blueprint, a template-like object which stores the settings, transformation rules and data sources for your columns. </p>
<p>OADG provides three methods for creating a blueprint. A wizard-like flow guides you through each method, as screenshot illustrates below.  </p>
<blockquote>
<p>Navigation: SQL Workshop &gt;  Utilities &gt; Data Generator</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658947125235/M8Lxi4ePS.png" alt="createbp2.png" /></p>
<p>There are benefits to each method:</p>
<ol>
<li><p><strong>Use Existing Tables </strong>- this option provides you with two big features: 1) it auto-generates your blueprint based on your table's definition, and 2) if you choose, it will automatically load the generated sample data directly into your existing table. </p>
</li>
<li><p><strong>From Scratch </strong>- this option provides you ultimate flexibility in the sequence of your table(s) and column(s) and will provide you generated data in a CSV, JSON or SQL file.</p>
</li>
<li><p><strong>Import JSON File</strong> - this option serves as my ultimate 'edit' recourse.  I typically generate a blueprint from scratch or from an existing table and if I need to edit the sequence of a table or column, I export it as a JSON, make the edits I need, and then reimport it with this option. </p>
</li>
</ol>
<h3 id="heading-2-define-each-columns-data-source">2. Define each column's data source</h3>
<p>This is where you define the data you want to generate and how to transform it.  Once you have defined your table(s) and column(s) with guidance from the wizard in step 1 above, click on your first column to display its Column and Data Source regions, as illustrated in screenshot below.</p>
<blockquote>
<p>NOTE: I have uploaded my blueprint's JSON <a target="_blank" href="https://sandrablogs.s3.us-west-2.amazonaws.com/PRODUCT+Blueprint.json">here</a> in case you'd like to follow along.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658980749755/iBWYgtn9S.png" alt="columnattributes.png" /></p>
<p>OADG makes available six data sources, providing almost unlimited flexibility for data transformation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658943450483/kXW_vt5uo.png" alt="6 datasources.png" /></p>
<p>Let's see each of these in action below. </p>
<h4 id="heading-1-blueprint">1. Blueprint</h4>
<p>This option allows the relational dependency (foreign-key) between tables.  For my use case, I need to reference the CATEGORY_ID from the PRODUCT_CATEGORY table to the CATEGORY_ID in my PRODUCT table. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658981341538/BVWHtT1bh.png" alt="relational_dep.png" /></p>
<blockquote>
<p>Tip: this option is only displayed if you have if you have more than one table defined in your blueprint.  If you need to reference Table A.Column A's values for your Table B.Column B, ensure you define Table A and its columns before defining Table B in the Blueprint.  This feature is sequence-dependent and will force you to redesign the sequence of your tables if they are not in the right order. </p>
</blockquote>
<h4 id="heading-2-custom-data-source">2. Custom Data Source</h4>
<p>Select this option if the data generator needs to randomly assign values from your own provided data. Simply create a custom data source by selecting the hamburger bar as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659114279483/vNSY8ARIe.png" alt="create data source.png" /></p>
<p>For my example, I uploaded a CSV file with 1000+ retail brands using the Data Workshop utility.  These values will serve as sample data for the BRAND column.  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659114295909/BPO-nU5kk.png" alt="datasource.png" /></p>
<blockquote>
<p>NOTE: The RETAIL_BRANDS.xlsx file I use in this example is available <a target="_blank" href="https://sandrablogs.s3.us-west-2.amazonaws.com/RETAIL_BRANDS.xlsx">here</a>.</p>
</blockquote>
<h4 id="heading-3-built-in">3. Built-In</h4>
<p>This source option allows you to use any of the pre-seeded data types.  I found myself running the "friendly_name" script provided in the "Why It's Great" section above a number of times to get me familiar with the data and its boundless possibilities.  </p>
<p>I chose the Built-In option for five columns: CATEGORY_NAME, PRODUCT_NAME, COST, LAUNCH_DATE and ACTIVE.  Here is a pic of the LAUNCH_DATE and ACTIVE column settings. Check out the convenience the "Date Between Min and Max" data type provides: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659032037164/Jxf44pdJe.png" alt="Built_In.png" /></p>
<p>Other "Date" and "Boolean" options include the following:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659032816710/TQD47zgZO.png" alt="date_boolean.png" /></p>
<h4 id="heading-4-inline">4. Inline</h4>
<p>This is a very handy option for when you have a manageable list of pre-defined values. Instead of having to load your custom data to a table, you simply list out your values in a table provided by this option.  For my use case, I defined four values for the UOM column.  See screenshot below. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659029583185/MCeCghQAE.png" alt="Inline.png" /></p>
<p>Note the "Frequency" column above, which allows me to indicate the occurrence of one value compared to the others in a generated data set.  Neat! </p>
<p>And Note the "Multi Value Options" fields as displayed in the screenshot below.  It allows you to generate multiple values for a column.  For this specific screenshot, I have instructed OADG to assign up to three values for the UOM column with a comma as my delimiter.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659117557792/XSS19iaXx.png" alt="multivalue.png" /></p>
<h4 id="heading-5-sequence">5. Sequence</h4>
<p>As the name applies, this option will generate a numeric sequence for your column.  It lets you specify the starting sequence number as well as the incremental value.  I use this for both my CATEGORY_ID and PRODUCT_ID columns.  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659114461540/SHm1v3RPy.png" alt="sequence.png" /></p>
<h4 id="heading-6-formula">6. Formula</h4>
<p>This one is my favorite because it's powerful and provides so much flexibility.  It allows you to apply just about any function to transform built-in or custom data.  You can apply a substring function to limit size of values, DBMS_RANDOM or CASE to derive values based on dependencies with other columns, as shown in the screenshot below: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659034286296/jhlz90gVx.png" alt="formulas.png" /></p>
<p>Did you catch the Required flag setting on the screenshot above?  If you set a column to not Required, you can indicate the percentage of values you'd like to be set as Null.  </p>
<p>This was a quick overview of the six data sources available. You will spend the bulk of your setup in this section. With such flexibility, you can just about build anything you dream up.  </p>
<h3 id="heading-3-preview-and-correct-as-needed">3. Preview and correct as needed</h3>
<p>The  'Preview' option provides a live preview of the data your blueprint will generate, giving you the opportunity to edit any of your column's definitions before generating your data. Here's a preview of my data. Because I have two tables defined, it provides me two views to review:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659113415882/iyGtMkxek.png" alt="preview_category.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659113425779/p1UTmYyuL.png" alt="preview_product.png" /></p>
<h3 id="heading-4-generate-data-csv-json-sql">4. Generate data (CSV, JSON, SQL)</h3>
<p>Finally, OADG offers three file output formats: CSV, JSON or a SQL script ready for upload directly into your table(s). </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659047284862/Y-tBkPUMq.png" alt="generatedata.png" /></p>
<p>And here are a few pics of my results in each format. 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659050817510/821bgScjf.png" alt="3formats.png" /></p>
<h2 id="heading-performance">Performance</h2>
<p>As you can see, data generation is lightning fast for one million rows with eight columns, three of which had formulas.  These test runs were ran in OCI Cloud free tier. </p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong># Rows</strong></td><td><strong>CSV</strong></td><td><strong>JSON</strong></td></tr>
</thead>
<tbody>
<tr>
<td>10,000</td><td>13 sec</td><td>13 sec</td></tr>
<tr>
<td>100,000</td><td>40 sec</td><td>48 sec</td></tr>
<tr>
<td>1 Million</td><td>5 min</td><td>7 min</td></tr>
</tbody>
</table>
</div><h2 id="heading-heads-up">Heads Up</h2>
<p>Here are a few tips and hints I thought I'd pass along: </p>
<ul>
<li>The sequence field is not updatable.  To re-sequence a column, you will need to delete the column and recreate it in the position you need it within your table.  You can perform this declaratively by right-clicking on the column to delete it and recreate it in the APEX Builder or, an easier option is to re-create the blueprint via JSON.</li>
<li>If column dependencies between tables exist, it is important to sequence the tables correctly in the blueprint design.  For instance, since my PRODUCT table has a dependency on a column in the PRODUCT_CATEGORY table, it is important to sequence the PRODUCT_CATEGORY table in my blueprint first, followed by the PRODUCT table.  In my first run, I defined my tables in the wrong sequence.  Since the sequence field is not updatable, I had to delete both tables to re-create them in the correct sequence.  Alternatively, I could have exported the blueprint design, edited the sequence number in its JSON and then reimport it again. 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657941019182/DtxPAv2nA.png" alt="not_updatable field.png" /></li>
<li>The option to load into existing tables is possible for blueprints created from scratch or based on an existing table. If you built your blueprint from scratch, your blueprint's table name must match the table name in your schema exactly and you must comply with typical table constraints such as ensuring your blueprint includes all required columns, etc. </li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659553933865/PUIUOpTI2.png" alt="insertintotable copy.png" /></p>
<ul>
<li>A blueprint is an all or nothing definition. If you have three tables in your blueprint, it will generate data for all three tables. If for a particular run, you want to create data for just one table, you will need to create a new blueprint because you are unable to temporarily disable the other tables.  NOTE: A 'copy' or 'duplicate' blueprint button does not exist, but you can export your current blueprint, edit the JSON and import it back in.</li>
<li>When designing your column definitions, it appears a column with a formula cannot reference another column with a formula. It appears each column is being evaluated independently. Although it did not throw out an error during my testing, the Preview results in my column were not correct.  </li>
<li>There can be a performance hit if your columns include very complex formulas.  The higher the complexity, the bigger the hit. </li>
<li>Don't skip the APEX Help sections - they provide great examples as they guide through the data generation process. </li>
</ul>
<h2 id="heading-add-ons-i-would-love-to-see">Add-Ons I Would Love To See</h2>
<p>Release 22.1 (May 2022) is the first roll-out of the Data Generator and it is fully-robust as it is.  I can't help but dream up of additional iterations the APEX team could deliver in future versions...</p>
<ul>
<li>Enable For Everyone - As it's currently an APEX Utility Tool, only developers and administrators have access to the data generator.  But business analysts and other end users could benefit too.  As designed now, end users have to request a developer to generate the data for them.  Making it available outside the APEX Builder would allow users to use it without developer intervention.  Alternatively, you could point users to apex.oracle.com so they could upload their own blueprints and custom data.   </li>
<li>Copy Blueprint Button - ideal for when I need a new version of my blueprint.   Currently, I export my existing blueprint, edit it in JSON and re-import with a new name.  This is not hard, but a button would require less clicks. </li>
</ul>
<h2 id="heading-summary">Summary</h2>
<p>Hundreds of fee-based and open-source test data generation tools exist out on the market.  When you consider the factors for selecting a tool such as the data types supported, data generation methods, sample data library, performance and cost, the Oracle APEX Data Generator comes out on top.   Thanks Oracle APEX team.  🙏</p>
]]></content:encoded></item><item><title><![CDATA[Mapping An AWS Route 53 Domain To Your Hashnode Blog]]></title><description><![CDATA[Why Hashnode
Hashnode's biggest selling point for me is that it fully supports my personal domain for free.  This means I get to continue to blog under my own name, sandra-suarez.com, while taking advantage of all the features the platform offers, in...]]></description><link>https://sandra-suarez.com/route53-hashnode-dns</link><guid isPermaLink="true">https://sandra-suarez.com/route53-hashnode-dns</guid><dc:creator><![CDATA[sssuarez]]></dc:creator><pubDate>Sun, 03 Jul 2022 23:31:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1656885340412/AadL-umif.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-why-hashnode">Why Hashnode</h3>
<p>Hashnode's biggest selling point for me is that it fully supports my personal domain for free.  This means I get to continue to blog under my own name, <a target="_blank" href="www.sandra-suarez.com">sandra-suarez.com</a>, while taking advantage of all the <a target="_blank" href="https://legacy.hashnode.com">features</a> the platform offers, including issuing and renewing an SSL certificate for me. No more renewing my Let's Encrypt SSL certificate every quarter :) </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656881528375/ZwRgXn-_L.png" alt="HNCustomDomainSetup.png" /></p>
<h3 id="heading-hashnodes-general-purpose-custom-domain-support">Hashnode's General-Purpose Custom Domain Support</h3>
<p>Hashnode provides <a target="_blank" href="https://support.hashnode.com/docs/mapping-domain/">instructions</a> to map your personal domain to your Hashnode Blog.  They even provide detailed guides for <a target="_blank" href="https://support.hashnode.com/docs/mapping-godaddy">GoDaddy</a>,  <a target="_blank" href="https://support.hashnode.com/docs/mapping-namecheap">NameCheap</a> and <a target="_blank" href="https://support.hashnode.com/docs/mapping-cloudflare">Cloudflare</a> DNS providers.  But not for AWS Route 53.  At least not as of June 2022.  I spent a few hours troubleshooting my setup and I'm sharing my lessons learned.  </p>
<h3 id="heading-why-route-53-is-different">Why Route 53 Is Different</h3>
<p>AWS Route 53 requires the additional setup of a<strong> hosted zone</strong> for your domain, something not required by other DNS providers.  And the existence of such a hosted zone introduces the risk that the name servers at the hosted zone level may not match the name servers at the domain level.  This was my problem. </p>
<h4 id="heading-1-verify-name-servers-match">1. Verify Name Servers Match</h4>
<blockquote>
<p><strong> Problem:</strong>  I had mismatched name servers between my registered domain and my hosted zone. </p>
<p><strong>The Fix:</strong>   Copy the name servers from the hosted zone over to my registered domain.</p>
</blockquote>
<h5 id="heading-a-make-a-copy-of-all-domain-name-servers-in-your-hosted-zone">a. Make a copy of all domain name servers in your hosted zone.</h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656885661415/bSwTPDi77.png" alt="nshostedserver.png" /></p>
<h5 id="heading-b-next-proceed-to-the-registered-domain-section-click-on-the-add-or-edit-name-servers-link-under-the-name-servers-section-and-add-all-servers-you-will-need-to-add-each-one-at-a-time">b. Next, proceed to the registered domain section.  Click on the "Add or Edit Name Servers" link under the name servers section and add all servers.  You will need to add each one at a time.</h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656885702568/bUsYZSyuY.png" alt="nsregdomainserver.png" /></p>
<h5 id="heading-c-after-the-change-you-can-verify-your-dns-propagation-herehttpswwwwhatsmydnsnet-for-me-i-saw-it-start-to-propagate-within-minutes-but-it-took-a-couple-of-hours-for-it-to-propagate-everywhere">c. After the change, you can verify your DNS propagation <a target="_blank" href="https://www.whatsmydns.net">here</a>.  For me, I saw it start to propagate within minutes but it took a couple of hours for it to propagate everywhere.</h5>
<h4 id="heading-2-root-domains-require-an-extra-dns-entry">2. Root Domains Require An Extra DNS Entry</h4>
<p>When setting up your Hashnode blog, you will need to decide whether to point it to your root domain or a sub-domain.  In my case:</p>
<ul>
<li>example of a root domain:  <code>sandra-suarez.com</code></li>
<li>example of a sub-domain: <code>blog.sandra-suarez.com</code></li>
</ul>
<p>My personal site is specifically for blogging so I went the root domain route to keep things simple.  </p>
<blockquote>
<p>Because Route 53 does not support CNAME flattening, setups for a root domain will require an extra DNS entry compared to a sub-domain setup.  </p>
</blockquote>
<p>Hashnode provides a a handy table (see below) indicating whether your DNS provider supports CNAME flattening.  If so, like in the case of Cloudflare, you only need to create a "CNAME" DNS entry.  Route 53, on the other hand, does not support CNAME flattening, so two DNS entries are required: a "CNAME" and an "A" entry. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656881040992/iUgf-cos5.png" alt="cnameflattening.png" /></p>
<p>In the two screenshots below, notice how a root domain setup requires two DNS entries, "CNAME" and an "A" entry while a sub-domain requires only one. </p>
<p><em>Root Domain Setup Instructions from Hashnode</em>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656878072601/rRKIqdYNc.png" alt="rootdomain.png" /></p>
<p><em>Sub-Domain Setup Instructions from Hashnode</em>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656878369440/kHE12teRi.png" alt="subdomain.png" /></p>
<p>And so for the case of a root domain setup, here is what these settings will look like in Route 53: </p>
<p><em>DNS record setup for <code>sandra-suarez.com</code></em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656892429471/B8dhZYVCJ.png" alt="nonwwwsetup.png" />
<em>DNS record setup for <code>www.sandra-suarez.com</code></em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656882419752/dThACINh1.png" alt="wwwsetup.png" /></p>
<p><em>Here is the final setup of my DNS entries in Route 53:</em>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656891688411/JQboX0p3S.png" alt="final setups.png" /></p>
<h4 id="heading-3-discrepancy-between-hashnodes-and-route-53s-instructions">3. Discrepancy between Hashnode's and Route 53's Instructions</h4>
<p>You may have caught a discrepancy between Hashnode's instructions and Route 53's when it came to setting up the DNS entry for your root domain.  See screenshot below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656895949097/jDvJaVeuO.png" alt="discrepancy.png" /></p>
<p>As of today, July 3, 2022, in order for my blog to work, I need a DNS entry saved with an empty record name, as shown by Route 53's pic on the right.  Creating a DNS entry that mimics Hashnode's setup on the left doesn't impact my setups, as long as I have an entry as suggested by Route 53.  I verified this by first creating my DNS entries as described by Hashnode.  When that didn't work, I added a DNS entry as described by Route 53.  My blog now worked.  I then removed the DNS entry with the '@' and found that my blog still worked.  Finally, I re-ran these test scenarios to ensure my results were consistent. </p>
<h3 id="heading-recap-of-considerations-above">Recap Of Considerations Above</h3>
<p>To quickly summarize:</p>
<blockquote>
<ol>
<li>Decide whether you want your root domain or a sub-domain to point to your Hashnode blog.</li>
<li><em>In Hashnode</em> - Follow Hashnode's <a target="_blank" href="https://support.hashnode.com/docs/mapping-domain/">instructions</a> for custom domains, taking special note of setups for either a root domain or sub-domain mapping.</li>
<li><em>In Route 53</em> -  Ensure the name servers between your registered domain and your hosted zone match.</li>
<li><strong><em>For root domain mappings, perform these additional steps: </em></strong><ul>
<li><em>In Route 53</em> -  Ensure you setup two DNS records, one for your root domain and a second one for "www" to redirect to your root domain.  You only need one DNS record if you are pointing to a sub-domain.</li>
<li><em>In Route 53</em> -  Ensure the record name of the DNS entry for your root domain is empty. </li>
</ul>
</li>
</ol>
</blockquote>
<h3 id="heading-happy-blogging">Happy Blogging</h3>
<p>My hope is that this quick blog saves you time.</p>
<p>Like or comment below if this helps with the setup of your new blog.  I look forward to viewing and following your blog.  </p>
]]></content:encoded></item></channel></rss>