Repository: beyondessential/tamanu
Pull request #7550: feat(patientDetails): NASS-1596: Add back location hierarchy to desktop
Author: login: tcodling
Created: 2025-04-14T21:16:34Z | Merged: 2025-04-21T20:22:49Z

### Changes

_Add a brief description of the changes in this PR to help give the reviewer context._

### Deploys

- [x] **Deploy to Tamanu Internal** <!-- #deploy -->

### Tests

- [ ] **Run E2E Tests** <!-- #e2e -->

### Remember to...

- ...write or update tests
- ...add UI screenshots and **testing notes** to the Linear issue
- ...add any **manual upgrade steps** to the Linear issue
- ...update the [config reference](https://beyond-essential.slab.com/posts/reference-config-file-0c70ukly), [settings reference](https://beyond-essential.slab.com/posts/reference-settings-0blw1x2q), or any [relevant runbook(s)](https://beyond-essential.slab.com/topics/runbooks-bs04ml6c)
- ...call out additions or changes to **config files** for the deployment team to take note of

<!-- Thank you! -->



Diff:
diff --git a/packages/settings/src/schema/global.ts b/packages/settings/src/schema/global.ts
index 8bce8347347..21bfaa5e166 100644
--- a/packages/settings/src/schema/global.ts
+++ b/packages/settings/src/schema/global.ts
@@ -232,13 +232,13 @@ export const globalSettings = {
           },
         },
         disableInputPasting: {
-          description: 'Disable pasting into input fields (except email login and patient data fields)',
+          description:
+            'Disable pasting into input fields (except email login and patient data fields)',
           type: yup.boolean(),
           defaultValue: false,
         },
         discharge: {
-          description:
-            'Encounter discharge configuration',
+          description: 'Encounter discharge configuration',
           properties: {
             dischargeNoteMandatory: {
               type: yup.boolean(),
@@ -252,6 +252,11 @@ export const globalSettings = {
             },
           },
         },
+        patientDetailsLocationHierarchy: {
+          description: 'Use location hierarchy in patient details',
+          type: yup.boolean(),
+          defaultValue: false,
+        },
       },
     },
     customisations: {
@@ -1297,8 +1302,8 @@ export const globalSettings = {
           description: 'Settings for the time frame of recent notifications',
           type: yup.number(),
           defaultValue: 48,
-        }
-      }
+        },
+      },
     },
   },
 };
diff --git a/packages/web/app/components/Field/HierarchyFields.jsx b/packages/web/app/components/Field/HierarchyFields.jsx
index 234656d1f38..cce802f5b04 100644
--- a/packages/web/app/components/Field/HierarchyFields.jsx
+++ b/packages/web/app/components/Field/HierarchyFields.jsx
@@ -20,6 +20,9 @@ export const HierarchyFields = ({ fields, leafNodeType, relationType }) => {
     fields.find(f => f.referenceType === type),
   );
   const hierarchyToShow = configuredFields.length > 0 ? configuredFields : [leafNodeType];
+
+  if (fields.length === 0) return null;
+
   return (
     <Container>
       {hierarchyToShow.map((type, index) => {
@@ -29,7 +32,7 @@ export const HierarchyFields = ({ fields, leafNodeType, relationType }) => {
 
         return (
           <HierarchyFieldItem
-            key={fieldData.name}
+            key={fieldData?.name}
             relationType={relationType}
             isFirstLevel={index === 0}
             parentId={parentId}
diff --git a/packages/web/app/forms/PatientDetailsForm/layouts/generic/GenericLayout.jsx b/packages/web/app/forms/PatientDetailsForm/layouts/generic/GenericLayout.jsx
index b88dbb210db..91731fd2eb0 100644
--- a/packages/web/app/forms/PatientDetailsForm/layouts/generic/GenericLayout.jsx
+++ b/packages/web/app/forms/PatientDetailsForm/layouts/generic/GenericLayout.jsx
@@ -37,6 +37,7 @@ export const GenericPrimaryDetailsLayout = ({
   const isReminderContactEnabled = getSetting(SETTING_KEYS.FEATURES_REMINDER_CONTACT_ENABLED);
   const villageSuggester = useSuggester('village');
   const hideOtherSex = getSetting('features.hideOtherSex') === true;
+  const isUsingLocationHierarchy = getSetting('features.patientDetailsLocationHierarchy');
 
   return (
     <>
@@ -106,15 +107,21 @@ export const GenericPrimaryDetailsLayout = ({
           required
           saveDateAsString
         />
-        <LocalisedField
-          name="villageId"
-          label={
-            <TranslatedText stringId="general.localisedField.villageId.label" fallback="Village" />
-          }
-          component={AutocompleteField}
-          suggester={villageSuggester}
-          required={isRequiredPatientData('villageId')}
-        />
+
+        {!isUsingLocationHierarchy && (
+          <LocalisedField
+            name="villageId"
+            label={
+              <TranslatedText
+                stringId="general.localisedField.villageId.label"
+                fallback="Village"
+              />
+            }
+            component={AutocompleteField}
+            suggester={villageSuggester}
+            required={isRequiredPatientData('villageId')}
+          />
+        )}
         <LocalisedField
           name="sex"
           label={<TranslatedText stringId="general.localisedField.sex.label" fallback="Sex" />}
diff --git a/packages/web/app/forms/PatientDetailsForm/layouts/generic/patientFields/GenericLocationFields.jsx b/packages/web/app/forms/PatientDetailsForm/layouts/generic/patientFields/GenericLocationFields.jsx
index e447e7b2779..803e031be72 100644
--- a/packages/web/app/forms/PatientDetailsForm/layouts/generic/patientFields/GenericLocationFields.jsx
+++ b/packages/web/app/forms/PatientDetailsForm/layouts/generic/patientFields/GenericLocationFields.jsx
@@ -1,11 +1,18 @@
 import React from 'react';
-import { AutocompleteField, TextField } from '../../../../../components';
+import { AutocompleteField, HierarchyFields, TextField } from '../../../../../components';
 import { ConfiguredMandatoryPatientFields } from '../../../ConfiguredMandatoryPatientFields';
 
 import { useSuggester } from '../../../../../api';
 import { TranslatedText } from '../../../../../components/Translation/TranslatedText';
+import { REFERENCE_DATA_RELATION_TYPES, REFERENCE_TYPES } from '@tamanu/constants';
+import { useFilterPatientFields } from '../../../useFilterPatientFields';
+import { useSettings } from '../../../../../contexts/Settings';
 
 export const GenericLocationFields = ({ filterByMandatory }) => {
+  const { getSetting } = useSettings();
+
+  const isUsingLocationHierarchy = getSetting('features.patientDetailsLocationHierarchy');
+
   const subdivisionSuggester = useSuggester('subdivision');
   const divisionSuggester = useSuggester('division');
   const settlementSuggester = useSuggester('settlement');
@@ -20,23 +27,25 @@ export const GenericLocationFields = ({ filterByMandatory }) => {
         <TranslatedText stringId="general.localisedField.cityTown.label" fallback="City/town" />
       ),
     },
-    subdivisionId: {
-      component: AutocompleteField,
-      suggester: subdivisionSuggester,
-      label: (
-        <TranslatedText
-          stringId="general.localisedField.subdivisionId.label"
-          fallback="Sub division"
-        />
-      ),
-    },
-    divisionId: {
-      component: AutocompleteField,
-      suggester: divisionSuggester,
-      label: (
-        <TranslatedText stringId="general.localisedField.divisionId.label" fallback="Division" />
-      ),
-    },
+    ...(!isUsingLocationHierarchy && {
+      subdivisionId: {
+        component: AutocompleteField,
+        suggester: subdivisionSuggester,
+        label: (
+          <TranslatedText
+            stringId="general.localisedField.subdivisionId.label"
+            fallback="Sub division"
+          />
+        ),
+      },
+      divisionId: {
+        component: AutocompleteField,
+        suggester: divisionSuggester,
+        label: (
+          <TranslatedText stringId="general.localisedField.divisionId.label" fallback="Division" />
+        ),
+      },
+    }),
     countryId: {
       component: AutocompleteField,
       suggester: countrySuggester,
@@ -44,16 +53,18 @@ export const GenericLocationFields = ({ filterByMandatory }) => {
         <TranslatedText stringId="general.localisedField.countryId.label" fallback="Country" />
       ),
     },
-    settlementId: {
-      component: AutocompleteField,
-      suggester: settlementSuggester,
-      label: (
-        <TranslatedText
-          stringId="general.localisedField.settlementId.label"
-          fallback="Settlement"
-        />
-      ),
-    },
+    ...(!isUsingLocationHierarchy && {
+      settlementId: {
+        component: AutocompleteField,
+        suggester: settlementSuggester,
+        label: (
+          <TranslatedText
+            stringId="general.localisedField.settlementId.label"
+            fallback="Settlement"
+          />
+        ),
+      },
+    }),
     medicalAreaId: {
       component: AutocompleteField,
       suggester: medicalAreaSuggester,
@@ -84,10 +95,58 @@ export const GenericLocationFields = ({ filterByMandatory }) => {
       ),
     },
   };
+
+  const CURRENT_LOCATION_HIERARCHY_FIELDS = {
+    divisionId: {
+      referenceType: REFERENCE_TYPES.DIVISION,
+      label: (
+        <TranslatedText stringId="general.localisedField.divisionId.label" fallback="Division" />
+      ),
+    },
+    subdivisionId: {
+      referenceType: REFERENCE_TYPES.SUBDIVISION,
+      label: (
+        <TranslatedText
+          stringId="general.localisedField.subdivisionId.label"
+          fallback="Sub division"
+        />
+      ),
+    },
+    settlementId: {
+      referenceType: REFERENCE_TYPES.SETTLEMENT,
+      label: (
+        <TranslatedText
+          stringId="general.localisedField.settlementId.label"
+          fallback="Settlement"
+        />
+      ),
+    },
+    villageId: {
+      referenceType: REFERENCE_TYPES.VILLAGE,
+      label: (
+        <TranslatedText stringId="general.localisedField.villageId.label" fallback="Village" />
+      ),
+    },
+  };
+
+  const { fieldsToShow: locationHierarchyFieldsToShow } = useFilterPatientFields({
+    fields: CURRENT_LOCATION_HIERARCHY_FIELDS,
+    filterByMandatory,
+  });
+
   return (
-    <ConfiguredMandatoryPatientFields
-      fields={LOCATION_FIELDS}
-      filterByMandatory={filterByMandatory}
-    />
+    <>
+      {isUsingLocationHierarchy && (
+        <HierarchyFields
+          relationType={REFERENCE_DATA_RELATION_TYPES.ADDRESS_HIERARCHY}
+          leafNodeType={REFERENCE_TYPES.VILLAGE}
+          fields={locationHierarchyFieldsToShow}
+        />
+      )}
+      <ConfiguredMandatoryPatientFields
+        fields={LOCATION_FIELDS}
+        filterByMandatory={filterByMandatory}
+      />
+    </>
   );
 };


Reviews:
user: login: tcodling
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T21:23:45Z
user: login: tcodling
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T21:24:15Z
user: login: dannash100
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T22:09:41Z
user: login: dannash100
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T22:20:06Z

Review comments:
diff_hunk: @@ -252,6 +252,11 @@ export const globalSettings = {
             },
           },
         },
+        useLocationHierarchy: {
+          description: 'Use location hierarchy in patient details',
+          type: yup.boolean(),
+          defaultValue: false,
+        },
path: packages/settings/src/schema/global.ts
user: login: tcodling
body: Not sure about this setting. Super open to ideas of better name/place from reviewer. It doesnt really fit nicely anywhere i can tell
created_at: 2025-04-14T21:23:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -106,15 +107,21 @@ export const GenericPrimaryDetailsLayout = ({
           required
           saveDateAsString
         />
-        <LocalisedField
-          name="villageId"
-          label={
-            <TranslatedText stringId="general.localisedField.villageId.label" fallback="Village" />
-          }
-          component={AutocompleteField}
-          suggester={villageSuggester}
-          required={isRequiredPatientData('villageId')}
-        />
+
+        {!isUsingHierarchyLogic && (
path: packages/web/app/forms/PatientDetailsForm/layouts/generic/GenericLayout.jsx
user: login: tcodling
body: This will show in the additional data section instead when using hierarchy logic
created_at: 2025-04-14T21:24:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -20,40 +27,51 @@ export const GenericLocationFields = ({ filterByMandatory }) => {
         <TranslatedText stringId="general.localisedField.cityTown.label" fallback="City/town" />
       ),
     },
-    subdivisionId: {
-      component: AutocompleteField,
-      suggester: subdivisionSuggester,
-      label: (
-        <TranslatedText
-          stringId="general.localisedField.subdivisionId.label"
-          fallback="Sub division"
-        />
-      ),
-    },
-    divisionId: {
-      component: AutocompleteField,
-      suggester: divisionSuggester,
-      label: (
-        <TranslatedText stringId="general.localisedField.divisionId.label" fallback="Division" />
-      ),
-    },
+    ...(isUsingLocationHierarchy
+      ? {}
+      : {
+          subdivisionId: {
+            component: AutocompleteField,
+            suggester: subdivisionSuggester,
+            label: (
+              <TranslatedText
+                stringId="general.localisedField.subdivisionId.label"
+                fallback="Sub division"
+              />
+            ),
+          },
+          divisionId: {
+            component: AutocompleteField,
+            suggester: divisionSuggester,
+            label: (
+              <TranslatedText
+                stringId="general.localisedField.divisionId.label"
+                fallback="Division"
+              />
+            ),
+          },
+        }),
     countryId: {
       component: AutocompleteField,
       suggester: countrySuggester,
       label: (
         <TranslatedText stringId="general.localisedField.countryId.label" fallback="Country" />
       ),
     },
-    settlementId: {
-      component: AutocompleteField,
-      suggester: settlementSuggester,
-      label: (
-        <TranslatedText
-          stringId="general.localisedField.settlementId.label"
-          fallback="Settlement"
-        />
-      ),
-    },
+    ...(isUsingLocationHierarchy
path: packages/web/app/forms/PatientDetailsForm/layouts/generic/patientFields/GenericLocationFields.jsx
user: login: dannash100
body: ```suggestion
    ...(isUsingLocationHierarchy && {
          settlementId: {
            component: AutocompleteField,
            suggester: settlementSuggester,
            label: (
              <TranslatedText
                stringId="general.localisedField.settlementId.label"
                fallback="Settlement"
              />
            ),
          },
        })),
```
would work in these cases
created_at: 2025-04-14T22:06:09Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-04-14T21:26:30Z
body: **Android builds 📱**
- **27948:** [Download Android APK](https://github.com/beyondessential/tamanu/actions/runs/14458131706/artifacts/2944104842) **Latest**
- **27910:** [Download Android APK](https://github.com/beyondessential/tamanu/actions/runs/14456892869/artifacts/2943781450)
- **27909:** [Download Android APK](https://github.com/beyondessential/tamanu/actions/runs/14456880870/artifacts/2943713479)
- **27905:** [Download Android APK](https://github.com/beyondessential/tamanu/actions/runs/14456627650/artifacts/2943630953)
- **27901:** [Download Android APK](https://github.com/beyondessential/tamanu/actions/runs/14456086634/artifacts/2943501116)
- **27897:** [Download Android APK](https://github.com/beyondessential/tamanu/actions/runs/14455954149/artifacts/2943422669)
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-14T21:36:21Z
body: #### :tropical_drink: `up` on tamanu-on-k8s/bes/tamanu-on-k8s/nass-1596-add-back-location-hierarchy-desktop

  <details>
  <summary>Pulumi report</summary>

  
  <pre>
  Updating (bes/nass-1596-add-back-location-hierarchy-desktop)

View Live: https://app.pulumi.com/bes/tamanu-on-k8s/nass-1596-add-back-location-hierarchy-desktop/updates/6

@ Updating....

@ Updating.....
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running read pulumi:pulumi:StackReference bes/k8s-core/tamanu-internal-main
@ Updating....
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running read pulumi:pulumi:StackReference bes/k8s-core/tamanu-internal-main
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Using tailscale proxy https://k8s-operator-tamanu-internal-main.tail53aef.ts.net
@ Updating....
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running read pulumi:pulumi:StackReference bes/core/tamanu-internal
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Waiting for central-db...
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Waiting for facility-1-db...
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Waiting for facility-2-db...
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running read pulumi:pulumi:StackReference bes/core/tamanu-internal
@ Updating....
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running read kubernetes:core/v1:ConfigMap actual-provisioning
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Secret facility-1-db-superuser not found or not ready: Error: HTTP-Code: 404
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Message: Unknown API Status Code!
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Body: "{\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"secrets \\\"facility-1-db-superuser\\\" not found\",\"reason\":\"NotFound\",\"details\":{\"name\":\"facility-1-db-superuser\",\"kind\":\"secrets\"},\"code\":404}
"
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Headers: {"audit-id":"04648495-8831-4c4a-ab29-343c483dc52a","cache-control":"no-cache, private","connection":"close","content-length":"220","content-type":"application/json","date":"Mon, 14 Apr 2025 23:59:43 GMT","x-kubernetes-pf-flowschema-uid":"7d46608e-fb55-48cf-90aa-981c856b1d54","x-kubernetes-pf-prioritylevel-uid":"ed197318-138c-44ea-825e-1d4df495928e"}
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Secret central-db-superuser not found or not ready: Error: HTTP-Code: 404
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Message: Unknown API Status Code!
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Body: "{\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"secrets \\\"central-db-superuser\\\" not found\",\"reason\":\"NotFound\",\"details\":{\"name\":\"central-db-superuser\",\"kind\":\"secrets\"},\"code\":404}
"
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Headers: {"audit-id":"f1892fc4-4246-4920-9adf-a7f944b2da50","cache-control":"no-cache, private","connection":"close","content-length":"214","content-type":"application/json","date":"Mon, 14 Apr 2025 23:59:43 GMT","x-kubernetes-pf-flowschema-uid":"7d46608e-fb55-48cf-90aa-981c856b1d54","x-kubernetes-pf-prioritylevel-uid":"ed197318-138c-44ea-825e-1d4df495928e"}
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Secret facility-2-db-superuser not found or not ready: Error: HTTP-Code: 404
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Message: Unknown API Status Code!
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Body: "{\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"secrets \\\"facility-2-db-superuser\\\" not found\",\"reason\":\"NotFound\",\"details\":{\"name\":\"facility-2-db-superuser\",\"kind\":\"secrets\"},\"code\":404}
"
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running Headers: {"audit-id":"8ddbf1e3-f830-4399-966d-48fdd281d931","cache-control":"no-cache, private","connection":"close","content-length":"220","content-type":"application/json","date":"Mon, 14 Apr 2025 23:59:43 GMT","x-kubernetes-pf-flowschema-uid":"7d46608e-fb55-48cf-90aa-981c856b1d54","x-kubernetes-pf-prioritylevel-uid":"ed197318-138c-44ea-825e-1d4df495928e"}
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop running read kubernetes:core/v1:ConfigMap actual-provisioning
@ Updating....
  pulumi:pulumi:Stack tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop  16 messages
Diagnostics:
pulumi:pulumi:Stack (tamanu-on-k8s-nass-1596-add-back-location-hierarchy-desktop):
  Waiting for central-db...
  Waiting for facility-1-db...
  Waiting for facility-2-db...

  Using tailscale proxy https://k8s-operator-tamanu-internal-main.tail53aef.ts.net

  Secret facility-1-db-superuser not found or not ready: Error: HTTP-Code: 404
  Message: Unknown API Status Code!
  Body: "{\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"secrets \\\"facility-1-db-superuser\\\" not found\",\"reason\":\"NotFound\",\"details\":{\"name\":\"facility-1-db-superuser\",\"kind\":\"secrets\"},\"code\":404}
"
  Headers: {"audit-id":"04648495-8831-4c4a-ab29-343c483dc52a","cache-control":"no-cache, private","connection":"close","content-length":"220","content-type":"application/json","date":"Mon, 14 Apr 2025 23:59:43 GMT","x-kubernetes-pf-flowschema-uid":"7d46608e-fb55-48cf-90aa-981c856b1d54","x-kubernetes-pf-prioritylevel-uid":"ed197318-138c-44ea-825e-1d4df495928e"}
  Secret central-db-superuser not found or not ready: Error: HTTP-Code: 404
  Message: Unknown API Status Code!
  Body: "{\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"secrets \\\"central-db-superuser\\\" not found\",\"reason\":\"NotFound\",\"details\":{\"name\":\"central-db-superuser\",\"kind\":\"secrets\"},\"code\":404}
"
  Headers: {"audit-id":"f1892fc4-4246-4920-9adf-a7f944b2da50","cache-control":"no-cache, private","connection":"close","content-length":"214","content-type":"application/json","date":"Mon, 14 Apr 2025 23:59:43 GMT","x-kubernetes-pf-flowschema-uid":"7d46608e-fb55-48cf-90aa-981c856b1d54","x-kubernetes-pf-prioritylevel-uid":"ed197318-138c-44ea-825e-1d4df495928e"}
  Secret facility-2-db-superuser not found or not ready: Error: HTTP-Code: 404
  Message: Unknown API Status Code!
  Body: "{\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"secrets \\\"facility-2-db-superuser\\\" not found\",\"reason\":\"NotFound\",\"details\":{\"name\":\"facility-2-db-superuser\",\"kind\":\"secrets\"},\"code\":404}
"
  Headers: {"audit-id":"8ddbf1e3-f830-4399-966d-48fdd281d931","cache-control":"no-cache, private","connection":"close","content-length":"220","content-type":"application/json","date":"Mon, 14 Apr 2025 23:59:43 GMT","x-kubernetes-pf-flowschema-uid":"7d46608e-fb55-48cf-90aa-981c856b1d54","x-kubernetes-pf-prioritylevel-uid":"ed197318-138c-44ea-825e-1d4df495928e"}

Outputs:
  urls: {
      Central    : "https://central.nass-1596-add-back-location-hierarchy-desktop.cd.tamanu.app"
      Facility- 1: "https://facility-1.nass-1596-add-back-location-hierarchy-desktop.cd.tamanu.app"
      Facility- 2: "https://facility-2.nass-1596-add-back-location-hierarchy-desktop.cd.tamanu.app"
  }

Resources:
  53 unchanged

Duration: 6s

  </pre>
  
  </details>
author_association: NONE