<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Insights</title>
    <link>https://orbitalobjectives.com/insights</link>
    <description>Notes from an independent Salesforce consultant on Sales Cloud, Service Cloud, Experience Cloud, CPQ, Account Engagement, Agentforce, HubSpot and Odoo.</description>
    <language>en-us</language>
    <pubDate>Thu, 12 Nov 2026 14:43:03 GMT</pubDate>
    <dc:date>2026-11-12T14:43:03Z</dc:date>
    <dc:language>en-us</dc:language>
    <item>
      <title>Synced email copies can hijack Odoo’s reply routing</title>
      <link>https://orbitalobjectives.com/insights/synced-email-copies-can-hijack-odoos-reply-routing</link>
      <description>&lt;p&gt;Logging customer email on the contact record sounds harmless. Built the obvious way, it breaks something far more important: where replies land.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Logging customer email on the contact record sounds harmless. Built the obvious way, it breaks something far more important: where replies land.&lt;/p&gt;
&lt;h2&gt;How replies find their record&lt;/h2&gt;
&lt;p&gt;When an email arrives, Odoo looks at which message it replies to and attaches it to the record holding that message. If a sync has stored a second copy of that same message on a contact, with the original message ID, the copy can win. The customer’s reply to a quotation then lands on the contact, and the salesperson watching the order never sees it.&lt;/p&gt;
&lt;h2&gt;The second trap: automatic replies&lt;/h2&gt;
&lt;p&gt;Posting a message through the standard chatter method can trigger out-of-office and auto-reply behaviour, even when you pass no recipients. A sync that back-fills a year of mail can send a year of automatic replies.&lt;/p&gt;
&lt;h2&gt;Rules for a safe sync&lt;/h2&gt;
&lt;ul&gt;
 &lt;li&gt;Never store the original message ID on the synced copy. Keep it in your own sync log for de-duplication.&lt;/li&gt;
 &lt;li&gt;Create messages with the low-level method that records without notifying, not the one that posts.&lt;/li&gt;
 &lt;li&gt;Skip mail Odoo already holds, internal mail and anything addressed to a shared alias.&lt;/li&gt;
 &lt;li&gt;Back-fill oldest first. Chatter is ordered by record, not by date, so the order you insert is the order people read.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is also possible to do all of this without a new cloud project, by reusing the sign-in each user already granted for sending mail from Odoo.&lt;/p&gt;  
&lt;img src="https://track.hubspot.com/__ptq.gif?a=43532792&amp;amp;k=14&amp;amp;r=https%3A%2F%2Forbitalobjectives.com%2Finsights%2Fsynced-email-copies-can-hijack-odoos-reply-routing&amp;amp;bu=https%253A%252F%252Forbitalobjectives.com%252Finsights&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <pubDate>Thu, 12 Nov 2026 14:43:03 GMT</pubDate>
      <author>info@orbitalobjectives.com (Orbital Objectives)</author>
      <guid>https://orbitalobjectives.com/insights/synced-email-copies-can-hijack-odoos-reply-routing</guid>
      <dc:date>2026-11-12T14:43:03Z</dc:date>
    </item>
    <item>
      <title>One checkbox on a Field Service project can unlink hundreds of records</title>
      <link>https://orbitalobjectives.com/insights/one-checkbox-on-a-field-service-project-can-unlink-hundreds-of-records</link>
      <description>&lt;p&gt;Someone unchecked Billable on the Field Service project, saw nothing dramatic happen, and checked it again. By then the task customers, the sales order items on tasks and the sales order lines on timesheets had been cleared across the project.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Someone unchecked Billable on the Field Service project, saw nothing dramatic happen, and checked it again. By then the task customers, the sales order items on tasks and the sales order lines on timesheets had been cleared across the project.&lt;/p&gt;
&lt;h2&gt;Why re-checking does not help&lt;/h2&gt;
&lt;p&gt;Turning billing off clears the links as part of the write. Turning it back on only re-enables the feature. The previous values are not stored anywhere the form can restore them from.&lt;/p&gt;
&lt;h2&gt;Where the data still exists&lt;/h2&gt;
&lt;p&gt;Fields with tracking enabled leave a history. Each cleared value was recorded as a tracking entry with its old value, so the links could be rebuilt record by record from that history.&lt;/p&gt;
&lt;h2&gt;How to restore safely&lt;/h2&gt;
&lt;ol&gt;
 &lt;li&gt;Work on a copy first and produce a report of what would be written.&lt;/li&gt;
 &lt;li&gt;Restore from the tracking history, matching each record to its last value before the toggle.&lt;/li&gt;
 &lt;li&gt;Watch for side effects: writing the sales order line back onto a task can confirm a draft order, which calls the tax engine. Decide whether you want that before you run it.&lt;/li&gt;
 &lt;li&gt;Verify counts afterwards against the report.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this case 460 task links and 484 timesheet lines were restored. If you run Field Service with billing, restrict who can edit project settings. A setting this destructive should not sit one click away from everyone with project access.&lt;/p&gt;  
&lt;img src="https://track.hubspot.com/__ptq.gif?a=43532792&amp;amp;k=14&amp;amp;r=https%3A%2F%2Forbitalobjectives.com%2Finsights%2Fone-checkbox-on-a-field-service-project-can-unlink-hundreds-of-records&amp;amp;bu=https%253A%252F%252Forbitalobjectives.com%252Finsights&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <pubDate>Thu, 12 Nov 2026 14:43:02 GMT</pubDate>
      <author>info@orbitalobjectives.com (Orbital Objectives)</author>
      <guid>https://orbitalobjectives.com/insights/one-checkbox-on-a-field-service-project-can-unlink-hundreds-of-records</guid>
      <dc:date>2026-11-12T14:43:02Z</dc:date>
    </item>
    <item>
      <title>Three gaps in Odoo CRM for teams that live on leads</title>
      <link>https://orbitalobjectives.com/insights/three-gaps-in-odoo-crm-for-teams-that-live-on-leads</link>
      <description>&lt;p&gt;Odoo handles opportunities well out of the box. Teams with a long pre-opportunity phase run into three gaps, usually in this order.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Odoo handles opportunities well out of the box. Teams with a long pre-opportunity phase run into three gaps, usually in this order.&lt;/p&gt;
&lt;h2&gt;1. Leads have no workflow of their own&lt;/h2&gt;
&lt;p&gt;Stages are designed for opportunities. A lead is either still a lead or converted, with nothing in between to say whether anyone has contacted it, qualified it or parked it. A lead status with its own small workflow fills that gap. Keep leads and opportunities in the same model, and resist the temptation to split leads into a model of their own.&lt;/p&gt;
&lt;h2&gt;2. You cannot see where records linger&lt;/h2&gt;
&lt;p&gt;Knowing a lead is in a stage is less useful than knowing it has been there for six weeks. Odoo has shipped a duration tracking mixin since version 17 that records the time a record spends in each value of a field. It only works on a many2one field with tracking switched on, so model the lead status as a small table of statuses, not a selection list. With that in place you get time-in-status for every record, and average days to qualify across the funnel.&lt;/p&gt;
&lt;h2&gt;3. Stale alerts ignore planned work&lt;/h2&gt;
&lt;p&gt;Odoo 19 added a rotting indicator that marks records which have sat too long in a pipeline stage. It is tied to stages, so it does not cover a lead status of your own. And any rule built only on days elapsed punishes the rep who has a call booked for next Tuesday. Useful stale detection checks two things: the threshold for the record’s current status, and whether a future activity is already scheduled. Only records that fail both get flagged and escalated.&lt;/p&gt;
&lt;h2&gt;Build it as an inheriting module&lt;/h2&gt;
&lt;p&gt;All three can be added in a custom module that inherits from the standard CRM models. Nothing in the base app is forked or patched, so upgrades stay possible. One practical note: a scheduled job that ships inactive in the module’s data file may still be switched on in production, so check the live setting before assuming what is running.&lt;/p&gt;  
&lt;img src="https://track.hubspot.com/__ptq.gif?a=43532792&amp;amp;k=14&amp;amp;r=https%3A%2F%2Forbitalobjectives.com%2Finsights%2Fthree-gaps-in-odoo-crm-for-teams-that-live-on-leads&amp;amp;bu=https%253A%252F%252Forbitalobjectives.com%252Finsights&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <pubDate>Thu, 12 Nov 2026 14:43:00 GMT</pubDate>
      <author>info@orbitalobjectives.com (Orbital Objectives)</author>
      <guid>https://orbitalobjectives.com/insights/three-gaps-in-odoo-crm-for-teams-that-live-on-leads</guid>
      <dc:date>2026-11-12T14:43:00Z</dc:date>
    </item>
    <item>
      <title>Your Flows deployed to production. They are not running.</title>
      <link>https://orbitalobjectives.com/insights/your-flows-deployed-to-production.-they-are-not-running</link>
      <description>&lt;p&gt;The deployment succeeded, every test passed, and the first real case did nothing. On a Service Cloud go-live, the whole stack of case Flows arrived in production as inactive versions, although each one was active in the sandbox.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;The deployment succeeded, every test passed, and the first real case did nothing. On a Service Cloud go-live, the whole stack of case Flows arrived in production as inactive versions, although each one was active in the sandbox.&lt;/p&gt;
&lt;h2&gt;Why it happens&lt;/h2&gt;
&lt;p&gt;This is default behaviour. Active Flows and processes deployed to a production org through change sets or the Metadata API are deployed inactive unless the org has opted in. Sandboxes deploy them active, which is why it never shows up in testing.&lt;/p&gt;
&lt;h2&gt;Two ways to handle it&lt;/h2&gt;
&lt;ul&gt;
 &lt;li&gt;Opt in. In Process Automation Settings, enable “Deploy processes and flows as active” and set a flow test coverage percentage. From then on a deployment fails if Apex tests do not cover enough of your active autolaunched Flows. Screen Flows are outside that requirement.&lt;/li&gt;
 &lt;li&gt;Leave the default and activate deliberately. Deploy, then activate the intended version of each Flow as a scripted step, so the moment automation switches on is one you chose.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Assert it, do not assume it&lt;/h2&gt;
&lt;p&gt;Whichever route you take, finish every production deploy by checking that each Flow has the active version you expect, and run one smoke test on a real record. A green deployment tells you the metadata arrived. It does not tell you anything is running.&lt;/p&gt;  
&lt;img src="https://track.hubspot.com/__ptq.gif?a=43532792&amp;amp;k=14&amp;amp;r=https%3A%2F%2Forbitalobjectives.com%2Finsights%2Fyour-flows-deployed-to-production.-they-are-not-running&amp;amp;bu=https%253A%252F%252Forbitalobjectives.com%252Finsights&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <pubDate>Thu, 12 Nov 2026 14:42:59 GMT</pubDate>
      <author>info@orbitalobjectives.com (Orbital Objectives)</author>
      <guid>https://orbitalobjectives.com/insights/your-flows-deployed-to-production.-they-are-not-running</guid>
      <dc:date>2026-11-12T14:42:59Z</dc:date>
    </item>
    <item>
      <title>The missing flag that lost every portal learner’s progress</title>
      <link>https://orbitalobjectives.com/insights/the-missing-flag-that-lost-every-portal-learners-progress</link>
      <description>&lt;p&gt;Customers reported that their course progress never saved. Staff could not reproduce it. Every internal test passed.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Customers reported that their course progress never saved. Staff could not reproduce it. Every internal test passed.&lt;/p&gt;
&lt;h2&gt;Root cause&lt;/h2&gt;
&lt;p&gt;The controller route that receives progress updates used website features but was declared without website=True. For internal users the request happened to work. For portal users the website context was missing, the handler raised, and the endpoint returned a server error. The course player ignored the failed save and carried on.&lt;/p&gt;
&lt;h2&gt;Why the tests missed it&lt;/h2&gt;
&lt;p&gt;The existing test called the route as a public user. That path returned early, before the line that failed, so the test passed without ever exercising the code a real learner hits.&lt;/p&gt;
&lt;h2&gt;The fix&lt;/h2&gt;
&lt;ul&gt;
 &lt;li&gt;Declare the route with website=True.&lt;/li&gt;
 &lt;li&gt;Add a regression test that signs in as a portal user and asserts the progress is stored.&lt;/li&gt;
 &lt;li&gt;Check any other custom or third-party route used by portal users for the same omission. I found the identical bug in a vendored module’s consent page.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The wider lesson is about test users. Internal, portal and public users take different paths through the same controller. A test suite that covers only one of them is covering a third of the code.&lt;/p&gt;  
&lt;img src="https://track.hubspot.com/__ptq.gif?a=43532792&amp;amp;k=14&amp;amp;r=https%3A%2F%2Forbitalobjectives.com%2Finsights%2Fthe-missing-flag-that-lost-every-portal-learners-progress&amp;amp;bu=https%253A%252F%252Forbitalobjectives.com%252Finsights&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <pubDate>Thu, 12 Nov 2026 14:42:58 GMT</pubDate>
      <author>info@orbitalobjectives.com (Orbital Objectives)</author>
      <guid>https://orbitalobjectives.com/insights/the-missing-flag-that-lost-every-portal-learners-progress</guid>
      <dc:date>2026-11-12T14:42:58Z</dc:date>
    </item>
    <item>
      <title>Questions to ask before you turn on Omni-Channel</title>
      <link>https://orbitalobjectives.com/insights/questions-to-ask-before-you-turn-on-omni-channel</link>
      <description>&lt;p&gt;Omni-Channel pushes work to agents based on their availability and capacity. It is a good feature and it is often switched on for teams that would be better served by plain queues. These are the questions I ask before recommending it.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Omni-Channel pushes work to agents based on their availability and capacity. It is a good feature and it is often switched on for teams that would be better served by plain queues. These are the questions I ask before recommending it.&lt;/p&gt;
&lt;h2&gt;Volume and channels&lt;/h2&gt;
&lt;ul&gt;
 &lt;li&gt;Which channels do customers use today, and roughly how many cases arrive per week on each?&lt;/li&gt;
 &lt;li&gt;Is a new channel such as chat or messaging planned in the next year?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Routing pain&lt;/h2&gt;
&lt;ul&gt;
 &lt;li&gt;How does a case reach an agent now: someone assigns it, or agents pull from a queue?&lt;/li&gt;
 &lt;li&gt;Are some agents overloaded while others wait?&lt;/li&gt;
 &lt;li&gt;Do cases need a specific skill, product line or language, or can anyone on the team take them?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Supervision&lt;/h2&gt;
&lt;ul&gt;
 &lt;li&gt;Does a supervisor need a live view of queue depth and who is available?&lt;/li&gt;
 &lt;li&gt;Are there response-time targets that differ by channel or customer?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Reading the answers&lt;/h2&gt;
&lt;ul&gt;
 &lt;li&gt;Manual assignment and uneven workload: Omni-Channel with capacity-based routing addresses this directly.&lt;/li&gt;
 &lt;li&gt;Cases that need the right person, not the next person: add skills-based routing.&lt;/li&gt;
 &lt;li&gt;A small team, one or two channels and no complaints about distribution: queues and assignment rules are enough. Revisit when the team grows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On one recent Service Cloud project we deliberately left Omni-Channel out of the first phase and listed it as a later option. Two regional queues solved the problem the team actually had.&lt;/p&gt;  
&lt;img src="https://track.hubspot.com/__ptq.gif?a=43532792&amp;amp;k=14&amp;amp;r=https%3A%2F%2Forbitalobjectives.com%2Finsights%2Fquestions-to-ask-before-you-turn-on-omni-channel&amp;amp;bu=https%253A%252F%252Forbitalobjectives.com%252Finsights&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <pubDate>Thu, 12 Nov 2026 14:42:57 GMT</pubDate>
      <author>info@orbitalobjectives.com (Orbital Objectives)</author>
      <guid>https://orbitalobjectives.com/insights/questions-to-ask-before-you-turn-on-omni-channel</guid>
      <dc:date>2026-11-12T14:42:57Z</dc:date>
    </item>
    <item>
      <title>CPQ quote templates will not follow your custom lookups</title>
      <link>https://orbitalobjectives.com/insights/cpq-quote-templates-will-not-follow-your-custom-lookups</link>
      <description>&lt;p&gt;You add a lookup from the quote to a custom object, drop a merge field into the template that reaches through it, and the PDF prints the merge field itself. Nothing is wrong with your syntax. You have found one of the edges of the CPQ template engine.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;You add a lookup from the quote to a custom object, drop a merge field into the template that reaches through it, and the PDF prints the merge field itself. Nothing is wrong with your syntax. You have found one of the edges of the CPQ template engine.&lt;/p&gt;
&lt;h2&gt;What the engine actually resolves&lt;/h2&gt;
&lt;p&gt;There are two different contexts in a quote template, and they behave differently.&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;Line columns read fields on the quote line. They do not support dot notation at all, so a column cannot reach a related record.&lt;/li&gt;
 &lt;li&gt;HTML template content can merge from five sources only: the quote, its primary contact, its sales rep, the template record and the generated document. A record behind any other lookup, including one you created, is not on that list.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Fix 1: flatten the value onto the quote&lt;/h2&gt;
&lt;p&gt;Create a formula field on the quote that pulls the value across the lookup, then reference that field in the template. This is the fix for names, numbers, dates and short text, and it takes minutes.&lt;/p&gt;
&lt;h2&gt;Fix 2: long text needs a different route&lt;/h2&gt;
&lt;p&gt;Formula fields cannot reference a long text area on another object, which is exactly where disclaimers and legal wording tend to live. Two options work: a record-triggered Flow that stamps the text into a long text field on the quote, or Quote Terms with term conditions.&lt;/p&gt;
&lt;h2&gt;Fix 3: use Quote Terms for legal text&lt;/h2&gt;
&lt;p&gt;If the content is a disclaimer that should appear only under certain conditions, Quote Terms are the feature built for it. They are versioned, conditional and editable by an admin, which is what you want for wording that a lender or a lawyer will change.&lt;/p&gt;
&lt;p&gt;Before you promise a quote layout, list every value on it and note which object it lives on. Anything that is not on the quote or one of the five sources needs one of these three routes, and it is cheaper to know that in scoping than in UAT.&lt;/p&gt;  
&lt;img src="https://track.hubspot.com/__ptq.gif?a=43532792&amp;amp;k=14&amp;amp;r=https%3A%2F%2Forbitalobjectives.com%2Finsights%2Fcpq-quote-templates-will-not-follow-your-custom-lookups&amp;amp;bu=https%253A%252F%252Forbitalobjectives.com%252Finsights&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <pubDate>Thu, 12 Nov 2026 14:42:55 GMT</pubDate>
      <author>info@orbitalobjectives.com (Orbital Objectives)</author>
      <guid>https://orbitalobjectives.com/insights/cpq-quote-templates-will-not-follow-your-custom-lookups</guid>
      <dc:date>2026-11-12T14:42:55Z</dc:date>
    </item>
    <item>
      <title>Large uploads that crash Odoo.sh workers, and how to store them anyway</title>
      <link>https://orbitalobjectives.com/insights/large-uploads-that-crash-odoo.sh-workers-and-how-to-store-them-anyway</link>
      <description>&lt;p&gt;Loading training content into Odoo, a 480 MB video took down the worker handling it. A larger batch failed partway and then refused to retry, reporting that the attachment collided with an existing file.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Loading training content into Odoo, a 480 MB video took down the worker handling it. A larger batch failed partway and then refused to retry, reporting that the attachment collided with an existing file.&lt;/p&gt;
&lt;h2&gt;Root cause&lt;/h2&gt;
&lt;p&gt;Creating an attachment from raw content holds the entire file in memory, and more than once while it is hashed and written. On a hosted worker with a memory limit, a large file is enough to get the process killed. The collision on retry was the half-written file from the first attempt.&lt;/p&gt;
&lt;h2&gt;A streaming approach&lt;/h2&gt;
&lt;ol&gt;
 &lt;li&gt;Receive the upload in chunks and write each chunk to a temporary file, updating a checksum as you go.&lt;/li&gt;
 &lt;li&gt;Move the finished file into the filestore at the path its checksum dictates.&lt;/li&gt;
 &lt;li&gt;Create the attachment record without content, then set its stored filename, size and checksum directly.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Peak memory is now about one chunk, whatever the file size.&lt;/p&gt;
&lt;h2&gt;Related limits worth knowing&lt;/h2&gt;
&lt;ul&gt;
 &lt;li&gt;The stored file size is a 32-bit integer in the database. A generated file over 2 GB fails with “integer out of range” unless you handle that case.&lt;/li&gt;
 &lt;li&gt;On Odoo.sh, staging builds are full copies of production and count toward the storage quota. A few large generated files can exhaust it. Purge generated files after download.&lt;/li&gt;
 &lt;li&gt;A shell session without the right data directory reads and writes a different filestore from the live site.&lt;/li&gt;
&lt;/ul&gt;  
&lt;img src="https://track.hubspot.com/__ptq.gif?a=43532792&amp;amp;k=14&amp;amp;r=https%3A%2F%2Forbitalobjectives.com%2Finsights%2Flarge-uploads-that-crash-odoo.sh-workers-and-how-to-store-them-anyway&amp;amp;bu=https%253A%252F%252Forbitalobjectives.com%252Finsights&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <pubDate>Thu, 12 Nov 2026 14:42:54 GMT</pubDate>
      <author>info@orbitalobjectives.com (Orbital Objectives)</author>
      <guid>https://orbitalobjectives.com/insights/large-uploads-that-crash-odoo.sh-workers-and-how-to-store-them-anyway</guid>
      <dc:date>2026-11-12T14:42:54Z</dc:date>
    </item>
    <item>
      <title>Two silent failures on a public Experience Cloud page</title>
      <link>https://orbitalobjectives.com/insights/two-silent-failures-on-a-public-experience-cloud-page</link>
      <description>&lt;p&gt;Public pages run as the guest user, under tighter rules than anything you test while logged in. Two problems from one project, both invisible until someone checked the result and not the screen.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Public pages run as the guest user, under tighter rules than anything you test while logged in. Two problems from one project, both invisible until someone checked the result and not the screen.&lt;/p&gt;
&lt;h2&gt;Guest file uploads that attach to nothing&lt;/h2&gt;
&lt;p&gt;A public case form let visitors add photos. The files uploaded, and the code then linked each file to the new case by inserting a ContentDocumentLink. For a guest user that insert failed, even from Apex running in system mode.&lt;/p&gt;
&lt;p&gt;The fix is to never create the link yourself. Set FirstPublishLocationId on the ContentVersion to the case when you insert the file, and Salesforce creates the link as part of the same operation.&lt;/p&gt;
&lt;h2&gt;A confirmation dialog that always said no&lt;/h2&gt;
&lt;p&gt;A delete button on a partner page asked “Are you sure?” with the browser’s own confirm dialog. Under Lightning Web Security that call returned nothing, the code read that as a refusal, and the delete never ran. Nobody had reported it because nothing looked broken.&lt;/p&gt;
&lt;p&gt;Use the platform’s LightningConfirm module in place of the browser dialog. It returns a promise that resolves to the user’s choice, and it is styled like the rest of the page.&lt;/p&gt;
&lt;h2&gt;The habit that catches both&lt;/h2&gt;
&lt;p&gt;Test public pages in a private browser window as a real guest, and check the record afterwards: is the file on the case, is the row gone. An end-to-end browser test for the public form now does this on every change.&lt;/p&gt;  
&lt;img src="https://track.hubspot.com/__ptq.gif?a=43532792&amp;amp;k=14&amp;amp;r=https%3A%2F%2Forbitalobjectives.com%2Finsights%2Ftwo-silent-failures-on-a-public-experience-cloud-page&amp;amp;bu=https%253A%252F%252Forbitalobjectives.com%252Finsights&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <pubDate>Thu, 12 Nov 2026 14:42:53 GMT</pubDate>
      <author>info@orbitalobjectives.com (Orbital Objectives)</author>
      <guid>https://orbitalobjectives.com/insights/two-silent-failures-on-a-public-experience-cloud-page</guid>
      <dc:date>2026-11-12T14:42:53Z</dc:date>
    </item>
    <item>
      <title>Changing a scoring rule re-scores everyone. Completion actions do not.</title>
      <link>https://orbitalobjectives.com/insights/changing-a-scoring-rule-re-scores-everyone.-completion-actions-do-not</link>
      <description>&lt;p&gt;A marketing team asked me a reasonable question: if we lower the points for an email open, will existing scores drop? The answer is yes and no, because their account was scoring opens in two places.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;A marketing team asked me a reasonable question: if we lower the points for an email open, will existing scores drop? The answer is yes and no, because their account was scoring opens in two places.&lt;/p&gt;
&lt;h2&gt;Two systems, one number&lt;/h2&gt;
&lt;ul&gt;
 &lt;li&gt;Baseline scoring rules live in the account settings. They assign points to activity types. When you change one, Account Engagement re-scores existing prospects and tells you how many will be affected before you save. Expect those records to sync to Salesforce afterwards.&lt;/li&gt;
 &lt;li&gt;Completion actions on individual emails and forms can also adjust score. These are one-time adjustments. They are added at the moment the action fires and are never recalculated.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The prospect’s score is the sum of both. If every email carries a completion action that adds a large number on open, the baseline rule for opens is almost irrelevant, and changing it will not undo the inflation already recorded.&lt;/p&gt;
&lt;h2&gt;How to tell which you have&lt;/h2&gt;
&lt;ol&gt;
 &lt;li&gt;Open a high-scoring prospect and read the activity history. Completion-action adjustments appear as their own entries.&lt;/li&gt;
 &lt;li&gt;Check a sample of sent emails for score-adjusting completion actions.&lt;/li&gt;
 &lt;li&gt;Compare what the baseline rules alone would produce for that prospect with the score on the record.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;What I usually recommend&lt;/h2&gt;
&lt;p&gt;If completion actions have been inflating scores for a long time, adjusting baseline rules will not fix it. Decide on one mechanism, remove the other going forward, and reset scores so the model starts clean. Warn sales before the reset, because every threshold-based automation and report will move on the same day.&lt;/p&gt;  
&lt;img src="https://track.hubspot.com/__ptq.gif?a=43532792&amp;amp;k=14&amp;amp;r=https%3A%2F%2Forbitalobjectives.com%2Finsights%2Fchanging-a-scoring-rule-re-scores-everyone.-completion-actions-do-not&amp;amp;bu=https%253A%252F%252Forbitalobjectives.com%252Finsights&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <pubDate>Thu, 12 Nov 2026 14:42:51 GMT</pubDate>
      <author>info@orbitalobjectives.com (Orbital Objectives)</author>
      <guid>https://orbitalobjectives.com/insights/changing-a-scoring-rule-re-scores-everyone.-completion-actions-do-not</guid>
      <dc:date>2026-11-12T14:42:51Z</dc:date>
    </item>
  </channel>
</rss>
