Repository: msupply-foundation/open-msupply
Pull request #6789: Add insert returns as shipped when inserting from shipments
Author: login: fergie-nz
Labels: name: Priority: Should Have
name: Team Ruru 🦉
description: Roxy, Andrei, Chris & Aimee
name: feature: CIV
Created: 2025-03-03T22:02:27Z | Merged: 2025-03-10T19:45:16Z

<!-- IMPORTANT!
  - Every PR must reference an issue; this helps to explain the intent of the PR
 -->

Fixes #6481

# 👩🏻‍💻 What does this PR do?

Sets return status as 'shipped' by default when a return is created from a shipment.

This happens for both inbound and outbound shipments for supplier and customer returns respectively.

Follow up [issue](https://github.com/msupply-foundation/open-msupply/issues/6790) created for more fleshed out UX.
<!-- Explain the changes you made -->

<!-- why are the changes needed -->

<!-- Add a screenshot if there are UI changes  -->

## 💌 Any notes for the reviewer?

<!-- Do you have any specific questions for the reviewer? -->

<!-- Is there a high risk/complicated change they should focus on? -->

<!-- any general areas of the codebase touched? any side effects caused? -->

<!-- Anything half cooked but going to be finished off in a different PR? -->

# 🧪 Testing

<!-- Explain the steps you'd take to test the changes of this PR manually -->

- [ ] Create an inbound shipment from store A - B (easy to test this if on the same site)
- [ ] Add an item to the shipment
- [ ] Set the shipment status as delivered
- [ ] Select the line for the shipment, and return the selected line using the footer ui
- [ ] Navigate to Supplier Returns, and see a return is created and that the status is 'Shipped'.
- [ ] Manually create a return, and see it is generated with status 'New'
- [ ] Log in to store B, and navigate to Customer Returns
- [ ] See a transfer return is generated. See that the status 'shipped'.

Then:

- [ ] Repeat the above steps with outbound shipments and customer returns.
>  Note - a customer return will not create a transfer supplier return, so skip this part. 
> Note - status of customer return generated from an outbound shipment will be 'Verified' rather than 'Shipped'



# 📃 Documentation

- [x] **No documentation required**: no user facing changes or a bug fix which isn't a change in behaviour


# 📃 Reviewer Checklist

The PR Reviewer(s) should fill out this section before approving the PR

**Breaking Changes**
- [ ] No Breaking Changes in the Graphql API
- [ ] Technically some Breaking Changes but not expected to impact any integrations

**Issue Review**
- [ ] All requirements in original issue have been covered
- [ ] A follow up issue(s) have been created to cover additional requirements

**Tests Pass**
- [ ] Postgres
- [ ] SQLite
- [ ] Frontend



Linked issue #6481: I am not notified when a supplier return is created (and it's only in nw status so never gets finalised...)
## What went wrong? 😲

If I return items from an inbound shipment using the new footer UI, I do not get an alert letting me know that it has been created - I just have to assume it has been! 

Then, since I didn't get an alert, I didn't notice that it was created on new status and therefore hasn't actually been sent to the supplier yet...it's 
not intuitive to me that I would need to take further action here. 

I've upped the priority on this a little as I feel like it will be a common support ask. 

## Expected behaviour 🤔

## How to Reproduce 🔨

Steps to reproduce the behaviour:

1. Create an inbound shipment 
2. Select some lines and choose to return them (ps the scroll bar is not visible here once the modal shows up (and the input field is at the very right) so it's hard to know what action to take...) 
3. No alert! 

## Your environment 🌱

<!-- e.g. 1.2.3 -->

- Open mSupply Version: 2.5 
- Platform: demo-oms

Linked issue comments: user: login: andreievg
created_at: 2025-02-20T22:45:29Z
body: Navigate to the return when created
author_association: COLLABORATOR
user: login: roxy-dao
created_at: 2025-02-27T03:08:34Z
body: mSupply finalises returns when they're created from an invoice, do we want to do that? Or do we want to navigate away? 

You can already enter all the info you need in to in the return modal? 🤔 
author_association: CONTRIBUTOR
user: login: DhanyaHerath
created_at: 2025-02-27T03:09:49Z
body: @roxy-dao Yes agreed! Tbh I had assumed it was already finalised - why would I want to look at it again? What would I change?

When I was first using it I actually went to the supplier's store to see whether the return had gotten there
author_association: CONTRIBUTOR
user: login: regotaina
created_at: 2025-03-02T22:08:09Z
body: > [@roxy-dao](https://github.com/roxy-dao) Yes agreed! Tbh I had assumed it was already finalised - why would I want to look at it again? What would I change?
> 
> When I was first using it I actually went to the supplier's store to see whether the return had gotten there

I agree it is confusing atm, still finding this one in the regression tests for 2.6. Thanks for working on this one, team :)
author_association: CONTRIBUTOR
user: login: fergie-nz
created_at: 2025-03-03T03:07:06Z
body: Just want to clarify solution would be:

Create and finalise return when created from Inbound or Outbound shipments
Don't navigate away from Inbound or Outbound shipments when creating a return

author_association: CONTRIBUTOR
user: login: Chris-Petty
created_at: 2025-03-03T03:26:25Z
body: I reckon 

1. Yes when making the return finalise immediately so it goes to the supplier
2. I reckon show snackbar and in it have a hyperlink to the created invoice (make sure it's easy enough to touch on android)

Could do 1. in this issue and make another issue for 2. to break down the work
author_association: CONTRIBUTOR
user: login: alainsussol
created_at: 2025-08-03T20:33:11Z
body: # 🧪 Testing

<!-- Explain the steps you'd take to test the changes of this PR manually -->

- [x] Create an inbound shipment from store A - B (easy to test this if on the same site)
- [x] Add an item to the shipment
- [x] Set the shipment status as delivered 
- [x] Select the line for the shipment, and return the selected line using the footer ui
- [x] Navigate to Supplier Returns, and see a return is created and that the status is 'Shipped'. **-PASS-**
- [x] A customer credit has been created on the supplier store **-PASS-**
- [x] Manually create a return, and see it is generated with status 'New'     **-PASS-**
- [x] Log in to store B, and navigate to Customer Returns  **-PASS-**
- [x] See a transfer return is generated. See that the status 'shipped'.   **-PASS-**

Then:

- [x] Repeat the above steps with outbound shipments and customer returns.   **-PASS-**
>  Note - a customer return will not create a transfer supplier return, so skip this part. 
> Note - status of customer return generated from an outbound shipment will be 'Verified' rather than 'Shipped'  **-PASS-**
author_association: NONE

Diff:
diff --git a/client/packages/common/src/intl/locales/en/common.json b/client/packages/common/src/intl/locales/en/common.json
index ddfa8d79b0f..9d4db145f1e 100644
--- a/client/packages/common/src/intl/locales/en/common.json
+++ b/client/packages/common/src/intl/locales/en/common.json
@@ -1659,6 +1659,8 @@
   "messages.zero-line-quantities_one": "The quantity of 1 line has been set to 0",
   "messages.zero-line-quantities_other": "The quantity of {{count}} lines has been set to 0",
   "messages.zero-return-quantity-will-delete-lines": "There are no return quantities specified. Click OK again to confirm and remove these lines from the return.",
+  "messages.customer-return-created-verified": "Customer Return successfully created as Verified",
+  "messages.supplier-return-created-shipped": "Supplier Return successfully created as Shipped",
   "monitoring": "Monitoring",
   "multiple": "[multiple]",
   "outbound-shipment": "Outbound Shipments",
diff --git a/client/packages/common/src/types/schema.ts b/client/packages/common/src/types/schema.ts
index bd7992ec507..4bfcd89c4bd 100644
--- a/client/packages/common/src/types/schema.ts
+++ b/client/packages/common/src/types/schema.ts
@@ -3498,6 +3498,7 @@ export type InvoiceFilterInput = {
   colour?: InputMaybe<EqualFilterStringInput>;
   comment?: InputMaybe<StringFilterInput>;
   createdDatetime?: InputMaybe<DatetimeFilterInput>;
+  createdOrBackdatedDatetime?: InputMaybe<DatetimeFilterInput>;
   deliveredDatetime?: InputMaybe<DatetimeFilterInput>;
   id?: InputMaybe<EqualFilterStringInput>;
   invoiceNumber?: InputMaybe<EqualFilterBigNumberInput>;
diff --git a/client/packages/invoices/src/Returns/CustomerListView/AppBarButtons.tsx b/client/packages/invoices/src/Returns/CustomerListView/AppBarButtons.tsx
index 3ea835d7800..f8ebbd7c38f 100644
--- a/client/packages/invoices/src/Returns/CustomerListView/AppBarButtons.tsx
+++ b/client/packages/invoices/src/Returns/CustomerListView/AppBarButtons.tsx
@@ -64,11 +64,11 @@ export const AppBarButtonsComponent: FC<{
               id: FnUtils.generateUUID(),
               customerId: name?.id,
               customerReturnLines: [],
-            }).then(invoiceNumber => {
+            }).then(customerReturn => {
               navigate(
                 RouteBuilder.create(AppRoute.Distribution)
                   .addPart(AppRoute.CustomerReturn)
-                  .addPart(String(invoiceNumber))
+                  .addPart(String(customerReturn?.invoiceNumber))
                   .build()
               );
             });
diff --git a/client/packages/invoices/src/Returns/SupplierListView/AppBarButtons.tsx b/client/packages/invoices/src/Returns/SupplierListView/AppBarButtons.tsx
index dfe0d65a103..d265da193f3 100644
--- a/client/packages/invoices/src/Returns/SupplierListView/AppBarButtons.tsx
+++ b/client/packages/invoices/src/Returns/SupplierListView/AppBarButtons.tsx
@@ -64,11 +64,11 @@ export const AppBarButtonsComponent: FC<{
               id: FnUtils.generateUUID(),
               supplierId: name?.id,
               supplierReturnLines: [],
-            }).then(invoiceNumber => {
+            }).then(supplierReturn => {
               navigate(
                 RouteBuilder.create(AppRoute.Replenishment)
                   .addPart(AppRoute.SupplierReturn)
-                  .addPart(String(invoiceNumber))
+                  .addPart(String(supplierReturn?.invoiceNumber))
                   .build()
               );
             });
diff --git a/client/packages/invoices/src/Returns/api/api.ts b/client/packages/invoices/src/Returns/api/api.ts
index ef2ed24c124..052b8ba8aca 100644
--- a/client/packages/invoices/src/Returns/api/api.ts
+++ b/client/packages/invoices/src/Returns/api/api.ts
@@ -252,7 +252,7 @@ export const getReturnsQueries = (sdk: Sdk, storeId: string) => ({
     const { insertSupplierReturn } = result;
 
     if (insertSupplierReturn.__typename === 'InvoiceNode') {
-      return insertSupplierReturn.invoiceNumber;
+      return insertSupplierReturn;
     }
 
     throw new Error('Could not insert supplier return');
@@ -340,7 +340,7 @@ export const getReturnsQueries = (sdk: Sdk, storeId: string) => ({
     const { insertCustomerReturn } = result;
 
     if (insertCustomerReturn.__typename === 'InvoiceNode') {
-      return insertCustomerReturn.invoiceNumber;
+      return insertCustomerReturn;
     }
 
     throw new Error('Could not insert customer return');
diff --git a/client/packages/invoices/src/Returns/api/operations.generated.ts b/client/packages/invoices/src/Returns/api/operations.generated.ts
index 4a642e6baab..13bef19ed5d 100644
--- a/client/packages/invoices/src/Returns/api/operations.generated.ts
+++ b/client/packages/invoices/src/Returns/api/operations.generated.ts
@@ -81,7 +81,7 @@ export type InsertSupplierReturnMutationVariables = Types.Exact<{
 }>;
 
 
-export type InsertSupplierReturnMutation = { __typename: 'Mutations', insertSupplierReturn: { __typename: 'InsertSupplierReturnError', error: { __typename: 'OtherPartyNotASupplier', description: string } | { __typename: 'OtherPartyNotVisible', description: string } } | { __typename: 'InvoiceNode', id: string, invoiceNumber: number } };
+export type InsertSupplierReturnMutation = { __typename: 'Mutations', insertSupplierReturn: { __typename: 'InsertSupplierReturnError', error: { __typename: 'OtherPartyNotASupplier', description: string } | { __typename: 'OtherPartyNotVisible', description: string } } | { __typename: 'InvoiceNode', id: string, invoiceNumber: number, originalShipment?: { __typename: 'InvoiceNode', id: string } | null } };
 
 export type UpdateSupplierReturnMutationVariables = Types.Exact<{
   storeId: Types.Scalars['String']['input'];
@@ -97,7 +97,7 @@ export type UpdateSupplierReturnLinesMutationVariables = Types.Exact<{
 }>;
 
 
-export type UpdateSupplierReturnLinesMutation = { __typename: 'Mutations', updateSupplierReturnLines: { __typename: 'InvoiceNode', id: string } };
+export type UpdateSupplierReturnLinesMutation = { __typename: 'Mutations', updateSupplierReturnLines: { __typename: 'InvoiceNode', id: string, originalShipment?: { __typename: 'InvoiceNode', id: string } | null } };
 
 export type InsertCustomerReturnMutationVariables = Types.Exact<{
   storeId: Types.Scalars['String']['input'];
@@ -105,7 +105,7 @@ export type InsertCustomerReturnMutationVariables = Types.Exact<{
 }>;
 
 
-export type InsertCustomerReturnMutation = { __typename: 'Mutations', insertCustomerReturn: { __typename: 'InsertCustomerReturnError', error: { __typename: 'OtherPartyNotACustomer', description: string } | { __typename: 'OtherPartyNotVisible', description: string } } | { __typename: 'InvoiceNode', id: string, invoiceNumber: number } };
+export type InsertCustomerReturnMutation = { __typename: 'Mutations', insertCustomerReturn: { __typename: 'InsertCustomerReturnError', error: { __typename: 'OtherPartyNotACustomer', description: string } | { __typename: 'OtherPartyNotVisible', description: string } } | { __typename: 'InvoiceNode', id: string, invoiceNumber: number, originalShipment?: { __typename: 'InvoiceNode', id: string } | null } };
 
 export type DeleteSupplierReturnMutationVariables = Types.Exact<{
   storeId: Types.Scalars['String']['input'];
@@ -129,7 +129,7 @@ export type UpdateCustomerReturnLinesMutationVariables = Types.Exact<{
 }>;
 
 
-export type UpdateCustomerReturnLinesMutation = { __typename: 'Mutations', updateCustomerReturnLines: { __typename: 'InvoiceNode', id: string } };
+export type UpdateCustomerReturnLinesMutation = { __typename: 'Mutations', updateCustomerReturnLines: { __typename: 'InvoiceNode', id: string, originalShipment?: { __typename: 'InvoiceNode', id: string } | null } };
 
 export type DeleteCustomerReturnMutationVariables = Types.Exact<{
   storeId: Types.Scalars['String']['input'];
@@ -467,6 +467,9 @@ export const InsertSupplierReturnDocument = gql`
       __typename
       id
       invoiceNumber
+      originalShipment {
+        id
+      }
     }
     ... on InsertSupplierReturnError {
       __typename
@@ -495,6 +498,9 @@ export const UpdateSupplierReturnLinesDocument = gql`
     ... on InvoiceNode {
       __typename
       id
+      originalShipment {
+        id
+      }
     }
   }
 }
@@ -506,6 +512,9 @@ export const InsertCustomerReturnDocument = gql`
       __typename
       id
       invoiceNumber
+      originalShipment {
+        id
+      }
     }
     ... on InsertCustomerReturnError {
       __typename
@@ -543,6 +552,9 @@ export const UpdateCustomerReturnLinesDocument = gql`
     ... on InvoiceNode {
       __typename
       id
+      originalShipment {
+        id
+      }
     }
   }
 }
diff --git a/client/packages/invoices/src/Returns/api/operations.graphql b/client/packages/invoices/src/Returns/api/operations.graphql
index 99195218f49..abf8ada518b 100644
--- a/client/packages/invoices/src/Returns/api/operations.graphql
+++ b/client/packages/invoices/src/Returns/api/operations.graphql
@@ -331,6 +331,9 @@ mutation insertSupplierReturn($storeId: String!, $input: SupplierReturnInput!) {
       __typename
       id
       invoiceNumber
+      originalShipment {
+        id
+      }
     }
 
     ... on InsertSupplierReturnError {
@@ -363,6 +366,9 @@ mutation updateSupplierReturnLines(
     ... on InvoiceNode {
       __typename
       id
+      originalShipment {
+        id
+      }
     }
   }
 }
@@ -373,6 +379,9 @@ mutation insertCustomerReturn($storeId: String!, $input: CustomerReturnInput!) {
       __typename
       id
       invoiceNumber
+      originalShipment {
+        id
+      }
     }
 
     ... on InsertCustomerReturnError {
@@ -414,6 +423,9 @@ mutation updateCustomerReturnLines(
     ... on InvoiceNode {
       __typename
       id
+      originalShipment {
+        id
+      }
     }
   }
 }
diff --git a/client/packages/invoices/src/Returns/modals/CustomerReturn/CustomerReturn.tsx b/client/packages/invoices/src/Returns/modals/CustomerReturn/CustomerReturn.tsx
index 33f43ae8a83..d25fba48060 100644
--- a/client/packages/invoices/src/Returns/modals/CustomerReturn/CustomerReturn.tsx
+++ b/client/packages/invoices/src/Returns/modals/CustomerReturn/CustomerReturn.tsx
@@ -9,6 +9,7 @@ import {
   ModalMode,
   Box,
   AlertColor,
+  useNotification,
 } from '@openmsupply-client/common';
 import { ItemSelector } from './ItemSelector';
 import { ReturnSteps, Tabs } from './ReturnSteps';
@@ -46,6 +47,7 @@ export const CustomerReturnEditModal = ({
 }: CustomerReturnEditModalProps) => {
   const t = useTranslation();
   const { currentTab, onChangeTab } = useTabs(Tabs.Quantity);
+  const { success } = useNotification();
 
   const [itemId, setItemId] = useState<string | undefined>(
     initialItemId ?? undefined
@@ -78,8 +80,9 @@ export const CustomerReturnEditModal = ({
 
   const onOk = async () => {
     try {
-      !isDisabled && (await save());
+      let customerReturn = !isDisabled && (await save());
       onCreate?.();
+      !!customerReturn && customerReturn?.originalShipment?.id && isNewReturn && success(t('messages.customer-return-created-verified'))();
       onClose();
     } catch {
       // TODO: handle error display...
diff --git a/client/packages/invoices/src/Returns/modals/CustomerReturn/useDraftCustomerReturnLines.ts b/client/packages/invoices/src/Returns/modals/CustomerReturn/useDraftCustomerReturnLines.ts
index 5cc85e767fa..198c0cd3046 100644
--- a/client/packages/invoices/src/Returns/modals/CustomerReturn/useDraftCustomerReturnLines.ts
+++ b/client/packages/invoices/src/Returns/modals/CustomerReturn/useDraftCustomerReturnLines.ts
@@ -114,19 +114,18 @@ export const useDraftCustomerReturnLines = ({
 
     // TODO: error handling here
     // also need to consider what we do if the error was on the first page of the wizard
-    if (!returnId) {
+    return !returnId ?
       await insert({
         id: FnUtils.generateUUID(),
         customerId,
         outboundShipmentId,
         customerReturnLines,
-      });
-    } else {
+      })
+      :
       await updateLines({
         customerReturnId: returnId,
         customerReturnLines,
       });
-    }
   };
 
   return { lines: draftLines, update, save, addDraftLine };
diff --git a/client/packages/invoices/src/Returns/modals/SupplierReturn/SupplierReturn.tsx b/client/packages/invoices/src/Returns/modals/SupplierReturn/SupplierReturn.tsx
index c987c43de68..5480d56d255 100644
--- a/client/packages/invoices/src/Returns/modals/SupplierReturn/SupplierReturn.tsx
+++ b/client/packages/invoices/src/Returns/modals/SupplierReturn/SupplierReturn.tsx
@@ -9,6 +9,7 @@ import {
   Box,
   ModalMode,
   AlertColor,
+  useNotification,
 } from '@openmsupply-client/common';
 import { ItemSelector } from './ItemSelector';
 import { ReturnSteps, Tabs } from './ReturnSteps';
@@ -46,6 +47,7 @@ export const SupplierReturnEditModal = ({
 }: SupplierReturnEditModalProps) => {
   const t = useTranslation();
   const { currentTab, onChangeTab } = useTabs(Tabs.Quantity);
+  const { success } = useNotification();
   const [itemId, setItemId] = useState<string | undefined>(
     initialItemId ?? undefined
   );
@@ -76,8 +78,9 @@ export const SupplierReturnEditModal = ({
 
   const onOk = async () => {
     try {
-      !isDisabled && (await save());
+      let supplierReturn = !isDisabled && (await save());
       onCreate?.();
+      !!supplierReturn && supplierReturn?.originalShipment?.id && isNewReturn && success(t('messages.supplier-return-created-shipped'))();
       onClose();
     } catch {
       // TODO: handle error display...
diff --git a/client/packages/invoices/src/Returns/modals/SupplierReturn/useDraftSupplierReturnLines.ts b/client/packages/invoices/src/Returns/modals/SupplierReturn/useDraftSupplierReturnLines.ts
index 037ab78d91c..75c4c9d1d92 100644
--- a/client/packages/invoices/src/Returns/modals/SupplierReturn/useDraftSupplierReturnLines.ts
+++ b/client/packages/invoices/src/Returns/modals/SupplierReturn/useDraftSupplierReturnLines.ts
@@ -57,19 +57,18 @@ export const useDraftSupplierReturnLines = ({
       }
     );
 
-    if (!returnId) {
+    return !returnId ?
       await insert({
         id: FnUtils.generateUUID(),
         supplierId,
         inboundShipmentId,
         supplierReturnLines,
-      });
-    } else {
+      })
+      :
       await updateLines({
         supplierReturnId: returnId,
         supplierReturnLines,
       });
-    }
 
     // TODO: error handling here
     // also need to consider what we do if the error was on the first page of the wizard
diff --git a/server/graphql/invoice/src/mutations/customer_return/insert.rs b/server/graphql/invoice/src/mutations/customer_return/insert.rs
index 42ead8ad04a..4ca122959a0 100644
--- a/server/graphql/invoice/src/mutations/customer_return/insert.rs
+++ b/server/graphql/invoice/src/mutations/customer_return/insert.rs
@@ -104,7 +104,8 @@ fn map_error(error: ServiceError) -> Result<InsertErrorInterface> {
         | ServiceError::OriginalInvoiceNotAnOutboundShipment
         | ServiceError::CannotReturnOutboundShipment
         | ServiceError::InvoiceAlreadyExists
-        | ServiceError::OtherPartyDoesNotExist => BadUserInput(formatted_error),
+        | ServiceError::OtherPartyDoesNotExist
+        | ServiceError::ErrorSettingNonNewStatus { .. } => BadUserInput(formatted_error),
 
         ServiceError::NewlyCreatedInvoiceDoesNotExist
         | ServiceError::LineInsertError { .. }
diff --git a/server/graphql/invoice/src/mutations/supplier_return/insert.rs b/server/graphql/invoice/src/mutations/supplier_return/insert.rs
index 8fbbef3fbf6..355d11cae1b 100644
--- a/server/graphql/invoice/src/mutations/supplier_return/insert.rs
+++ b/server/graphql/invoice/src/mutations/supplier_return/insert.rs
@@ -100,7 +100,8 @@ fn map_error(error: ServiceError) -> Result<InsertErrorInterface> {
         | ServiceError::OriginalInvoiceNotAnInboundShipment
         | ServiceError::CannotReturnInboundShipment
         | ServiceError::InvoiceAlreadyExists
-        | ServiceError::OtherPartyDoesNotExist => BadUserInput(formatted_error),
+        | ServiceError::OtherPartyDoesNotExist
+        | ServiceError::ErrorSettingNonNewStatus { .. } => BadUserInput(formatted_error),
         ServiceError::NewlyCreatedInvoiceDoesNotExist
         | ServiceError::LineInsertError { .. }
         | ServiceError::LineReturnReasonUpdateError { .. }
diff --git a/server/service/src/invoice/customer_return/insert/mod.rs b/server/service/src/invoice/customer_return/insert/mod.rs
index 8b05ea728d3..b3b95bbb401 100644
--- a/server/service/src/invoice/customer_return/insert/mod.rs
+++ b/server/service/src/invoice/customer_return/insert/mod.rs
@@ -16,7 +16,10 @@ pub mod validate;
 use generate::generate;
 use validate::validate;
 
-use super::CustomerReturnLineInput;
+use super::{
+    update_customer_return, CustomerReturnLineInput, UpdateCustomerReturn,
+    UpdateCustomerReturnError, UpdateCustomerReturnStatus,
+};
 
 #[derive(Clone, Debug, Default, PartialEq)]
 pub struct InsertCustomerReturn {
@@ -51,6 +54,9 @@ pub enum InsertCustomerReturnError {
         line_id: String,
         error: UpdateLineReturnReasonError,
     },
+    ErrorSettingNonNewStatus {
+        update_error: UpdateCustomerReturnError,
+    },
 }
 
 type OutError = InsertCustomerReturnError;
@@ -91,6 +97,21 @@ pub fn insert_customer_return(
                 })?;
             }
 
+            // Update to not new status after upserting lines
+            if customer_return.original_shipment_id.is_some() {
+                let _ = update_customer_return(
+                    ctx,
+                    UpdateCustomerReturn {
+                        id: customer_return.id.clone(),
+                        status: Some(UpdateCustomerReturnStatus::Verified),
+                        ..Default::default()
+                    },
+                )
+                .map_err(|e| {
+                    InsertCustomerReturnError::ErrorSettingNonNewStatus { update_error: e }
+                })?;
+            };
+
             activity_log_entry(
                 ctx,
                 ActivityLogType::InvoiceCreated,
@@ -412,6 +433,7 @@ mod test {
                 u.name_link_id = mock_name_customer_a().id;
                 u.user_id = Some(mock_user_account_a().id);
                 u.original_shipment_id = Some(returnable_outbound_shipment().id);
+                u.status = InvoiceStatus::Verified;
                 u
             })
         );
@@ -432,5 +454,34 @@ mod test {
                 u
             })
         );
+
+        // Check new return without original shipment gets created with status of 'New'
+        service_provider
+            .invoice_service
+            .insert_customer_return(
+                &context,
+                inline_init(|r: &mut InsertCustomerReturn| {
+                    r.id = "new_customer_return_id_2".to_string();
+                    r.other_party_id = mock_name_customer_a().id;
+                    r.outbound_shipment_id = None;
+                }),
+            )
+            .unwrap();
+
+        let invoice = InvoiceRowRepository::new(&connection)
+            .find_one_by_id("new_customer_return_id_2")
+            .unwrap()
+            .unwrap();
+
+        assert_eq!(invoice.id, "new_customer_return_id_2");
+        assert_eq!(
+            invoice,
+            inline_edit(&invoice, |mut u| {
+                u.name_link_id = mock_name_customer_a().id;
+                u.user_id = Some(mock_user_account_a().id);
+                u.status = InvoiceStatus::New;
+                u
+            })
+        );
     }
 }
diff --git a/server/service/src/invoice/customer_return/update/mod.rs b/server/service/src/invoice/customer_return/update/mod.rs
index c9fd7efc43b..1c475f94238 100644
--- a/server/service/src/invoice/customer_return/update/mod.rs
+++ b/server/service/src/invoice/customer_return/update/mod.rs
@@ -86,7 +86,7 @@ pub fn update_customer_return(
     Ok(invoice)
 }
 
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Clone)]
 pub enum UpdateCustomerReturnError {
     InvoiceDoesNotExist,
     NotACustomerReturn,
diff --git a/server/service/src/invoice/supplier_return/insert/mod.rs b/server/service/src/invoice/supplier_return/insert/mod.rs
index e3fbb66a13a..f197a5e3060 100644
--- a/server/service/src/invoice/supplier_return/insert/mod.rs
+++ b/server/service/src/invoice/supplier_return/insert/mod.rs
@@ -4,7 +4,7 @@ use repository::{
 
 use crate::{
     activity_log::activity_log_entry,
-    invoice::get_invoice,
+    invoice::{get_invoice, UpdateSupplierReturn},
     invoice_line::{
         stock_out_line::{insert_stock_out_line, InsertStockOutLineError},
         update_return_reason_id::{update_return_reason_id, UpdateLineReturnReasonError},
@@ -16,7 +16,10 @@ pub mod validate;
 use generate::generate;
 use validate::validate;
 
-use super::SupplierReturnLineInput;
+use super::{
+    update::{update_supplier_return, UpdateSupplierReturnError, UpdateSupplierReturnStatus},
+    SupplierReturnLineInput,
+};
 
 #[derive(Clone, Debug, Default, PartialEq)]
 pub struct InsertSupplierReturn {
@@ -50,6 +53,9 @@ pub enum InsertSupplierReturnError {
         line_id: String,
         error: UpdateLineReturnReasonError,
     },
+    ErrorSettingNonNewStatus {
+        update_error: UpdateSupplierReturnError,
+    },
 }
 
 type OutError = InsertSupplierReturnError;
@@ -90,6 +96,21 @@ pub fn insert_supplier_return(
                 })?;
             }
 
+            // Update to not new status after upserting lines
+            if supplier_return.original_shipment_id.is_some() {
+                update_supplier_return(
+                    ctx,
+                    UpdateSupplierReturn {
+                        supplier_return_id: supplier_return.id.clone(),
+                        status: Some(UpdateSupplierReturnStatus::Shipped),
+                        ..Default::default()
+                    },
+                )
+                .map_err(|e| {
+                    InsertSupplierReturnError::ErrorSettingNonNewStatus { update_error: e }
+                })?;
+            };
+
             activity_log_entry(
                 ctx,
                 ActivityLogType::InvoiceCreated,
@@ -133,7 +154,8 @@ mod test {
             mock_supplier_return_a, mock_user_account_a, MockData, MockDataInserts,
         },
         test_db::setup_all_with_data,
-        InvoiceLineRowRepository, InvoiceRowRepository, NameRow, NameStoreJoinRow, ReturnReasonRow,
+        InvoiceLineRowRepository, InvoiceRowRepository, InvoiceStatus, NameRow, NameStoreJoinRow,
+        ReturnReasonRow,
     };
     use util::{inline_edit, inline_init};
 
@@ -412,6 +434,7 @@ mod test {
                 u.name_link_id = supplier().id;
                 u.user_id = Some(mock_user_account_a().id);
                 u.original_shipment_id = Some(mock_inbound_shipment_a().id);
+                u.status = InvoiceStatus::Shipped;
                 u
             })
         );
@@ -432,5 +455,34 @@ mod test {
                 u
             })
         );
+
+        // Check new return without original shipment gets created with status of 'New'
+        service_provider
+            .invoice_service
+            .insert_supplier_return(
+                &context,
+                inline_init(|r: &mut InsertSupplierReturn| {
+                    r.id = "new_supplier_return_id_2".to_string();
+                    r.other_party_id = supplier().id;
+                    r.inbound_shipment_id = None;
+                }),
+            )
+            .unwrap();
+
+        let invoice = InvoiceRowRepository::new(&connection)
+            .find_one_by_id("new_supplier_return_id_2")
+            .unwrap()
+            .unwrap();
+
+        assert_eq!(invoice.id, "new_supplier_return_id_2");
+        assert_eq!(
+            invoice,
+            inline_edit(&invoice, |mut u| {
+                u.name_link_id = supplier().id;
+                u.user_id = Some(mock_user_account_a().id);
+                u.status = InvoiceStatus::New;
+                u
+            })
+        );
     }
 }
diff --git a/server/service/src/invoice/supplier_return/update/mod.rs b/server/service/src/invoice/supplier_return/update/mod.rs
index 35bdfc5d4f5..70c63fc41f5 100644
--- a/server/service/src/invoice/supplier_return/update/mod.rs
+++ b/server/service/src/invoice/supplier_return/update/mod.rs
@@ -33,7 +33,7 @@ pub struct UpdateSupplierReturn {
     pub transport_reference: Option<String>,
 }
 
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq, Debug, Clone)]
 pub enum UpdateSupplierReturnError {
     ReturnDoesNotExist,
     ReturnDoesNotBelongToCurrentStore,


Reviews:
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T22:06:22Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T22:10:20Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T22:11:17Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T22:12:28Z
user: login: roxy-dao
body: Thanks for the changes Ferg. I just have a few comments below. 

- Customer return only has the following statuses: `New`, `Delivered` and `Verified`, so to change the status to finalised, it should be set to `Verified`
- Supplier returns is the one that finalises on `Shipped` status. 

Adding tests would also help validate your changes.
The validation on insert stock_out_line is not allow finalising of supplier returns, I imagine the same thing will happen with customer return once you change the status to `Verified`
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T19:38:16Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T22:07:11Z
user: login: roxy-dao
body: Thanks for the changes Ferg.

Have you tested your changes? 
There's still one more request up top that hasn't been implemented yet

> Adding tests would also help validate your changes.
> The validation on insert stock_out_line is not allow finalising of supplier returns, I imagine the same thing will happen with customer return once you change the status to Verified

Due to the lines being inserted on a finalized invoice 
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T22:41:19Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T23:21:34Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T23:35:57Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T23:41:30Z
user: login: fergie-nz
body: Hi @roxy-dao , I've made a few changes to the front end as I realise the return modal was being used in multiple places.

Where returns are being made and their status is not new, two db calls are being made (and therefore two changelog rows). This is similar to how we are managing new return -> add lines -> set return to desired status.

Transfer returns are being updated to match the status of the generated return.

I've updated the PR test instructions to match these changes.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T23:44:34Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T03:46:00Z
user: login: roxy-dao
body: Thanks for the changes Ferg. I just have one more request. 

It would be nice if there was a toast to tell the user that a 'verified' or 'shipped' return has been created. Currently you press `Ok` and the user has no idea what has happened.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T23:24:09Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T04:33:55Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-09T22:58:51Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-09T22:59:44Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-09T23:02:03Z
user: login: roxy-dao
body: Thanks for the changes Ferg. Just have a question...
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T01:05:34Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T02:57:45Z
user: login: fergie-nz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T03:57:08Z
user: login: roxy-dao
body: LGTM~ tysm for all the changes Ferg!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T04:27:21Z

Review comments:
diff_hunk: @@ -120,6 +121,7 @@ export const useDraftCustomerReturnLines = ({
         customerId,
         outboundShipmentId,
         customerReturnLines,
+        status: InsertCustomerReturnStatusInput.Shipped,
path: client/packages/invoices/src/Returns/modals/CustomerReturn/useDraftCustomerReturnLines.ts
user: login: fergie-nz
body: This hook is only used when creating returns from shipments, so we can use shipped for this case.
created_at: 2025-03-03T22:06:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -120,6 +121,7 @@ export const useDraftCustomerReturnLines = ({
         customerId,
         outboundShipmentId,
         customerReturnLines,
+        status: InsertCustomerReturnStatusInput.Shipped,
       });
     } else {
       await updateLines({
path: client/packages/invoices/src/Returns/modals/CustomerReturn/useDraftCustomerReturnLines.ts
user: login: fergie-nz
body: This case is actually never encountered. When creating a second return from the same shipment (even from the same shipment line), a new return is created. So we don't need to add a status as part of the input to update lines (which also might not make sense from a UX perspective anyway if the return is created with a non 'shipped' status.)

Further option to remove mention of returnId in this hook given that it is not used anywhere? I am assuming it was used at some point and/or having flexibility in this case allows for easier future plugging in.
created_at: 2025-03-03T22:10:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -20,6 +21,13 @@ pub struct InsertInput {
     pub customer_id: String,
     pub outbound_shipment_id: Option<String>,
     pub customer_return_lines: Vec<CustomerReturnLineInput>,
+    pub status: Option<InsertCustomerReturnStatusInput>,
+}
+
+#[derive(Enum, Copy, Clone, PartialEq, Eq, Debug)]
+pub enum InsertCustomerReturnStatusInput {
+    New,
+    Shipped,
path: server/graphql/invoice/src/mutations/customer_return/insert.rs
user: login: fergie-nz
body: Have not used the 'picked' status option for input. Maybe there is a future use case for this? I figure it is easy to add in future if need be.
created_at: 2025-03-03T22:11:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -94,6 +94,7 @@ pub fn generate(
                     reason_id: None,
                     note: None,
                 }],
+                status: None,
path: server/service/src/vaccination/update/generate.rs
user: login: fergie-nz
body: This None status will default to new, and doesn't change existing insert behaviour from vaccines.
created_at: 2025-03-03T22:12:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -120,6 +121,7 @@ export const useDraftCustomerReturnLines = ({
         customerId,
         outboundShipmentId,
         customerReturnLines,
+        status: InsertCustomerReturnStatusInput.Shipped,
path: client/packages/invoices/src/Returns/modals/CustomerReturn/useDraftCustomerReturnLines.ts
user: login: roxy-dao
body: This should be `Verified`
created_at: 2025-03-04T19:12:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -120,6 +121,7 @@ export const useDraftCustomerReturnLines = ({
         customerId,
         outboundShipmentId,
         customerReturnLines,
+        status: InsertCustomerReturnStatusInput.Shipped,
       });
     } else {
       await updateLines({
path: client/packages/invoices/src/Returns/modals/CustomerReturn/useDraftCustomerReturnLines.ts
user: login: roxy-dao
body: Yes remove this since we are finalising customer returns straight away now
created_at: 2025-03-04T19:13:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -63,6 +64,7 @@ export const useDraftSupplierReturnLines = ({
         supplierId,
         inboundShipmentId,
         supplierReturnLines,
+        status: InsertSupplierReturnStatusInput.Shipped,
       });
     } else {
       await updateLines({
path: client/packages/invoices/src/Returns/modals/SupplierReturn/useDraftSupplierReturnLines.ts
user: login: roxy-dao
body: Same here, remove please since it won't be called
created_at: 2025-03-04T19:14:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -165,3 +175,13 @@ impl CustomerReturnLineInput {
         }
     }
 }
+
+impl InsertCustomerReturnStatusInput {
+    pub fn to_domain(&self) -> InsertCustomerReturnStatus {
+        use InsertCustomerReturnStatus::*;
+        match self {
+            InsertCustomerReturnStatusInput::New => New,
+            InsertCustomerReturnStatusInput::Shipped => Shipped,
path: server/graphql/invoice/src/mutations/customer_return/insert.rs
user: login: roxy-dao
body: This should be `Verified`, not `Shipped`
created_at: 2025-03-04T19:16:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -47,7 +54,7 @@ pub fn generate(
         name_store_id: other_party.store_id().map(|id| id.to_string()),
         store_id: store_id.to_string(),
         created_datetime: current_datetime,
-        status: InvoiceStatus::New,
+        status: status,
path: server/service/src/invoice/customer_return/insert/generate.rs
user: login: roxy-dao
body: ```suggestion
        status,
```

Redundant field name since the variable is already the same as the field name
created_at: 2025-03-04T19:18:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -18,13 +19,20 @@ use validate::validate;
 
 use super::CustomerReturnLineInput;
 
+#[derive(Clone, Debug, PartialEq)]
+pub enum InsertCustomerReturnStatus {
+    New,
+    Shipped,
path: server/service/src/invoice/customer_return/insert/mod.rs
user: login: roxy-dao
body: ```suggestion
    Verified,
```
created_at: 2025-03-04T19:25:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -94,6 +94,7 @@ pub fn generate(
                     reason_id: None,
                     note: None,
                 }],
+                status: None,
path: server/service/src/vaccination/update/generate.rs
user: login: roxy-dao
body: We would want to finalise this as well.
created_at: 2025-03-04T19:28:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -165,3 +175,13 @@ impl CustomerReturnLineInput {
         }
     }
 }
+
+impl InsertCustomerReturnStatusInput {
+    pub fn to_domain(&self) -> InsertCustomerReturnStatus {
+        use InsertCustomerReturnStatus::*;
+        match self {
+            InsertCustomerReturnStatusInput::New => New,
+            InsertCustomerReturnStatusInput::Shipped => Shipped,
path: server/graphql/invoice/src/mutations/customer_return/insert.rs
user: login: fergie-nz
body: Nice good catch thank you - I had copied the supplier statuses
created_at: 2025-03-04T22:07:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -139,7 +140,7 @@ const DetailViewInner = () => {
               modalMode={returnModalMode}
               inboundShipmentId={data.id}
               isNewReturn
-            />
+              status={InsertSupplierReturnStatusInput.Shipped} />
path: client/packages/invoices/src/InboundShipment/DetailView/DetailView.tsx
user: login: fergie-nz
body: Now passing status from Detail view and Footer component separately (as they both use the same modal)
created_at: 2025-03-05T23:21:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -57,12 +60,15 @@ export const useDraftSupplierReturnLines = ({
       }
     );
 
+    console.log('return id', returnId);
+
     if (!returnId) {
       await insert({
         id: FnUtils.generateUUID(),
         supplierId,
         inboundShipmentId,
         supplierReturnLines,
+        status: insertStatus,
       });
     } else {
       await updateLines({
path: client/packages/invoices/src/Returns/modals/SupplierReturn/useDraftSupplierReturnLines.ts
user: login: fergie-nz
body: I realise we actually do need the else condition cases I realise.

When manually creating returns (not from shipments detail view), it will send two api requests: first to generate, and second to update with lines. 
So this will stop from making two separate returns, and link the lines to the originals id in this case.
created_at: 2025-03-05T23:35:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -94,6 +94,7 @@ pub fn generate(
                     reason_id: None,
                     note: None,
                 }],
+                status: Some(InsertCustomerReturnStatus::New),
path: server/service/src/vaccination/update/generate.rs
user: login: fergie-nz
body: Passing status as New here (it must be new to add lines)

This is subsequently updated to verified in a second DB call.
created_at: 2025-03-05T23:41:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3498,6 +3498,7 @@ export type InvoiceFilterInput = {
   colour?: InputMaybe<EqualFilterStringInput>;
   comment?: InputMaybe<StringFilterInput>;
   createdDatetime?: InputMaybe<DatetimeFilterInput>;
+  createdOrBackdatedDatetime?: InputMaybe<DatetimeFilterInput>;
path: client/packages/common/src/types/schema.ts
user: login: fergie-nz
body: Unrelated to this PR - I think non generated schema was committed to rc branch
created_at: 2025-03-06T03:45:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -50,6 +53,10 @@ pub enum InsertSupplierReturnError {
         line_id: String,
         error: UpdateLineReturnReasonError,
     },
+    ErrorSettingNonNewStatus {
+        update_error: UpdateSupplierReturnError,
+    },
+    ManuallyCreatedReturnMustHaveNewStatus,
path: server/service/src/invoice/supplier_return/insert/mod.rs
user: login: roxy-dao
body: Why was this added? I don't see anywhere where it's doing a check and prompting this error
created_at: 2025-03-06T21:40:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -90,6 +97,25 @@ pub fn insert_supplier_return(
                 })?;
             }
 
+            // Update to not new status after upserting lines
+            if supplier_return.original_shipment_id.is_some() {
+                update_supplier_return(
+                    ctx,
+                    UpdateSupplierReturn {
+                        supplier_return_id: supplier_return.id.clone(),
+                        comment: None,
+                        status: Some(UpdateSupplierReturnStatus::Shipped),
+                        colour: None,
+                        on_hold: None,
+                        their_reference: None,
+                        transport_reference: None,
path: server/service/src/invoice/supplier_return/insert/mod.rs
user: login: roxy-dao
body: ```suggestion
                    UpdateSupplierReturn {
                        supplier_return_id: supplier_return.id.clone(),
                        status: Some(UpdateSupplierReturnStatus::Shipped),
                        ..Default::default()
```
Can default the None values instead of declaring each one
created_at: 2025-03-06T23:17:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -91,6 +98,25 @@ pub fn insert_customer_return(
                 })?;
             }
 
+            // Update to not new status after upserting lines
+            if customer_return.original_shipment_id.is_some() {
+                let _ = update_customer_return(
+                    ctx,
+                    UpdateCustomerReturn {
+                        id: customer_return.id.clone(),
+                        comment: None,
+                        status: Some(UpdateCustomerReturnStatus::Verified),
+                        colour: None,
+                        on_hold: None,
+                        their_reference: None,
+                        other_party_id: None,
path: server/service/src/invoice/customer_return/insert/mod.rs
user: login: roxy-dao
body: ```suggestion
                        id: customer_return.id.clone(),
                        status: Some(UpdateCustomerReturnStatus::Verified),
                        ..Default::default()
```
created_at: 2025-03-06T23:17:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -50,6 +53,10 @@ pub enum InsertSupplierReturnError {
         line_id: String,
         error: UpdateLineReturnReasonError,
     },
+    ErrorSettingNonNewStatus {
+        update_error: UpdateSupplierReturnError,
+    },
+    ManuallyCreatedReturnMustHaveNewStatus,
path: server/service/src/invoice/supplier_return/insert/mod.rs
user: login: fergie-nz
body: You're right! I added that earlier when giving the front end the capacity to choose status. Not needed now, thank you
created_at: 2025-03-07T04:33:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -414,6 +423,9 @@ mutation updateCustomerReturnLines(
     ... on InvoiceNode {
       __typename
       id
+      originalShipment {
+        id
+      }
path: client/packages/invoices/src/Returns/api/operations.graphql
user: login: fergie-nz
body: This adding to graphql (and for updateSupplierReturnLines) is for type compatibility.

I wonder if it is possible to not return this type and have type compatibility, but I couldn't see how to.
created_at: 2025-03-09T22:58:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -340,7 +340,7 @@ export const getReturnsQueries = (sdk: Sdk, storeId: string) => ({
     const { insertCustomerReturn } = result;
 
     if (insertCustomerReturn.__typename === 'InvoiceNode') {
-      return insertCustomerReturn.invoiceNumber;
+      return insertCustomerReturn;
path: client/packages/invoices/src/Returns/api/api.ts
user: login: fergie-nz
body: returning the full return so that navigation to return from AppBarButtons still works with invoice number
created_at: 2025-03-09T22:59:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -78,8 +80,9 @@ export const CustomerReturnEditModal = ({
 
   const onOk = async () => {
     try {
-      !isDisabled && (await save());
+      let customerReturn = !isDisabled && (await save());
       onCreate?.();
+      !!customerReturn && customerReturn?.originalShipment?.id && isNewReturn && success(t('messages.customer-return-created-verified'))();
path: client/packages/invoices/src/Returns/modals/CustomerReturn/CustomerReturn.tsx
user: login: fergie-nz
body: Type mapping was a little bit messy to make this work where it could be false | invoice node 
created_at: 2025-03-09T23:02:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -78,8 +80,9 @@ export const CustomerReturnEditModal = ({
 
   const onOk = async () => {
     try {
-      !isDisabled && (await save());
+      let customerReturn = !isDisabled && (await save());
       onCreate?.();
+      !!customerReturn && customerReturn?.originalShipment?.id && isNewReturn && success(t('messages.customer-return-created-verified'))();
path: client/packages/invoices/src/Returns/modals/CustomerReturn/CustomerReturn.tsx
user: login: roxy-dao
body: Do we need to check original shipment id and is new return? If api returns with a result (!!customerReturn) then it would prompt the message, correct? 
created_at: 2025-03-10T01:01:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -100,7 +100,9 @@ fn map_error(error: ServiceError) -> Result<InsertErrorInterface> {
         | ServiceError::OriginalInvoiceNotAnInboundShipment
         | ServiceError::CannotReturnInboundShipment
         | ServiceError::InvoiceAlreadyExists
-        | ServiceError::OtherPartyDoesNotExist => BadUserInput(formatted_error),
+        | ServiceError::OtherPartyDoesNotExist
+        | ServiceError::ManuallyCreatedReturnMustHaveNewStatus
path: server/graphql/invoice/src/mutations/supplier_return/insert.rs
user: login: roxy-dao
body: This should be removed if not used in validation... as requested https://github.com/msupply-foundation/open-msupply/pull/6789#discussion_r1984090283
created_at: 2025-03-10T01:02:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -76,8 +78,9 @@ export const SupplierReturnEditModal = ({
 
   const onOk = async () => {
     try {
-      !isDisabled && (await save());
+      let supplierReturn = !isDisabled && (await save());
       onCreate?.();
+      !!supplierReturn && supplierReturn?.originalShipment?.id && isNewReturn && success(t('messages.supplier-return-created-shipped'))();
path: client/packages/invoices/src/Returns/modals/SupplierReturn/SupplierReturn.tsx
user: login: roxy-dao
body: See above comment
created_at: 2025-03-10T01:05:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -100,7 +100,9 @@ fn map_error(error: ServiceError) -> Result<InsertErrorInterface> {
         | ServiceError::OriginalInvoiceNotAnInboundShipment
         | ServiceError::CannotReturnInboundShipment
         | ServiceError::InvoiceAlreadyExists
-        | ServiceError::OtherPartyDoesNotExist => BadUserInput(formatted_error),
+        | ServiceError::OtherPartyDoesNotExist
+        | ServiceError::ManuallyCreatedReturnMustHaveNewStatus
path: server/graphql/invoice/src/mutations/supplier_return/insert.rs
user: login: fergie-nz
body: Thank you for catching this, I missed this.
created_at: 2025-03-10T02:57:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -76,8 +78,9 @@ export const SupplierReturnEditModal = ({
 
   const onOk = async () => {
     try {
-      !isDisabled && (await save());
+      let supplierReturn = !isDisabled && (await save());
       onCreate?.();
+      !!supplierReturn && supplierReturn?.originalShipment?.id && isNewReturn && success(t('messages.supplier-return-created-shipped'))();
path: client/packages/invoices/src/Returns/modals/SupplierReturn/SupplierReturn.tsx
user: login: fergie-nz
body: This one is needed because the same insert modal is used both from appbarbuttons in the return list views, and in shipment list views. And in both cases a return node is returned - so we need the additional check that it has an original shipment id.
created_at: 2025-03-10T03:57:08Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-03-04T22:27:43Z
body: <!-- GITHUB_ACTION_COMMENT_PR -->
## Bundle size difference
Comparing this PR to `main`

|Old size      | New size     | Diff                     |
|:------------ |:-------------|:-------------------------|
|5.97 MB         |5.98 MB         | 959 B (0.02%) |

author_association: CONTRIBUTOR
user: login: fergie-nz
created_at: 2025-03-05T07:44:13Z
body: > We would want to finalise this as well.

I think this is okay because the customer return from vaccination is immediately verified after creation.
author_association: CONTRIBUTOR
user: login: roxy-dao
created_at: 2025-03-06T02:08:08Z
body: Hi Ferg~

Just to iterate over what was talked about:
We don't need to pass the status through from Frontend
We can conclude which returns have been created from an Inbound/Outbound shipment if it has an originalShipmentId.
We can then in the insert method, do a check for if this exists and if it does, finalise the return
author_association: CONTRIBUTOR