{
- const parts = [];
- if (owner.ownr_fn || owner.ownr_ln) {
- parts.push([owner.ownr_fn, owner.ownr_ln].filter(Boolean).join(" "));
- }
- if (owner.ownr_co_nm) {
- parts.push(owner.ownr_co_nm);
- }
- return parts.join(", ") || "-";
- };
-
// Map phone numbers to their associated owners and identify phone field
const getAssociatedOwners = (phoneNumber) => {
if (!ownersData?.owners) return [];
@@ -102,15 +93,20 @@ function PhoneNumberConsentList({ bodyshop, currentUser }) {
}
return owners.map((owner) => (
- {formatOwnerName(owner)} ({owner.phoneField})
+
+
+
+
+ ({owner.phoneField})
+
));
},
sorter: (a, b) => {
const aOwners = getAssociatedOwners(a.phone_number);
const bOwners = getAssociatedOwners(b.phone_number);
- const aName = aOwners[0] ? formatOwnerName(aOwners[0]) : "";
- const bName = bOwners[0] ? formatOwnerName(bOwners[0]) : "";
+ const aName = aOwners[0] ? `${aOwners[0].ownr_fn} ${aOwners[0].ownr_ln}` : "";
+ const bName = bOwners[0] ? `${bOwners[0].ownr_fn} ${bOwners[0].ownr_ln}` : "";
return aName.localeCompare(bName);
}
},
@@ -124,6 +120,7 @@ function PhoneNumberConsentList({ bodyshop, currentUser }) {
return (
+
{t("consent.text_body")}
setSearch(value)}
diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js
index 7faff13a2..73e222c01 100644
--- a/client/src/graphql/bodyshop.queries.js
+++ b/client/src/graphql/bodyshop.queries.js
@@ -312,7 +312,6 @@ export const QUERY_INTAKE_CHECKLIST = gql`
intakechecklist
status
owner {
- allow_text_message
id
}
labhrs: joblines_aggregate(where: { _and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }] }) {
diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js
index 5150b7a9f..68c8adfbe 100644
--- a/client/src/graphql/jobs.queries.js
+++ b/client/src/graphql/jobs.queries.js
@@ -874,7 +874,6 @@ export const QUERY_JOB_CARD_DETAILS = gql`
}
owner {
id
- allow_text_message
preferred_contact
tax_number
}
@@ -2071,7 +2070,6 @@ export const QUERY_JOB_CHECKLISTS = gql`
production_vars
owner {
id
- allow_text_message
}
bodyshop {
id
@@ -2428,7 +2426,6 @@ export const QUERY_PARTS_QUEUE_CARD_DETAILS = gql`
ownr_ph2
owner {
id
- allow_text_message
preferred_contact
tax_number
}
diff --git a/client/src/graphql/owners.queries.js b/client/src/graphql/owners.queries.js
index d169263f4..de1b654b7 100644
--- a/client/src/graphql/owners.queries.js
+++ b/client/src/graphql/owners.queries.js
@@ -49,7 +49,6 @@ export const QUERY_OWNER_BY_ID = gql`
owners_by_pk(id: $id) {
id
accountingid
- allow_text_message
ownr_addr1
ownr_addr2
ownr_co_nm
@@ -104,7 +103,6 @@ export const QUERY_ALL_OWNERS = gql`
query QUERY_ALL_OWNERS {
owners {
id
- allow_text_message
created_at
ownr_addr1
ownr_addr2
@@ -129,7 +127,6 @@ export const QUERY_ALL_OWNERS_PAGINATED = gql`
query QUERY_ALL_OWNERS_PAGINATED($search: String, $offset: Int, $limit: Int, $order: [owners_order_by!]!) {
search_owners(args: { search: $search }, offset: $offset, limit: $limit, order_by: $order) {
id
- allow_text_message
created_at
ownr_addr1
ownr_addr2
diff --git a/client/src/pages/jobs-create/jobs-create.container.jsx b/client/src/pages/jobs-create/jobs-create.container.jsx
index b12cd7823..0ed5c9d70 100644
--- a/client/src/pages/jobs-create/jobs-create.container.jsx
+++ b/client/src/pages/jobs-create/jobs-create.container.jsx
@@ -114,7 +114,6 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
if (!!!job.ownerid) {
ownerData = job.owner.data;
ownerData.shopid = bodyshop.id;
- delete ownerData.allow_text_message;
delete ownerData.preferred_contact;
delete job.ownerid;
} else {
diff --git a/client/src/pages/shop/shop.page.component.jsx b/client/src/pages/shop/shop.page.component.jsx
index b6ded16f6..f26f06d5a 100644
--- a/client/src/pages/shop/shop.page.component.jsx
+++ b/client/src/pages/shop/shop.page.component.jsx
@@ -92,13 +92,15 @@ export function ShopPage({ bodyshop, setSelectedHeader, setBreadcrumbs }) {
});
}
- // Add Consent Settings tab
- items.push({
- key: "consent",
- label: t("bodyshop.labels.consent_settings"),
- children:
- });
-
+ if (bodyshop.messagingservicesid) {
+ // Add Consent Settings tab
+ items.push({
+ key: "consent",
+ label: t("bodyshop.labels.consent_settings"),
+ children:
+ });
+ }
+
return (
history({ search: `?tab=${key}` })} items={items} />
diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json
index 52d6c1c00..fd3dd5134 100644
--- a/client/src/translations/en_us/common.json
+++ b/client/src/translations/en_us/common.json
@@ -775,7 +775,6 @@
},
"labels": {
"addtoproduction": "Add Job to Production?",
- "allow_text_message": "Permission to Text?",
"checklist": "Checklist",
"printpack": "Job Intake Print Pack",
"removefromproduction": "Remove Job from Production?"
@@ -2524,7 +2523,6 @@
"fields": {
"accountingid": "Accounting ID",
"address": "Address",
- "allow_text_message": "Permission to Text?",
"name": "Name",
"note": "Owner Note",
"ownr_addr1": "Address",
@@ -3876,7 +3874,8 @@
"created_at": "Opt-Out Date",
"no_owners": "No Associated Owners",
"phone_1": "Phone 1",
- "phone_2": "Phone 2"
+ "phone_2": "Phone 2",
+ "text_body": "Users can opt out of receiving SMS messages by replying with keywords such as STOP, UNSUBSCRIBE, CANCEL, END, QUIT, STOPALL, REVOKE and OPTOUT. To opt back in, users can reply with START, YES, or UNSTOP. Even after opting out, users can still send messages to us, which will be received and processed as needed. Ensure customers are informed to reply with these keywords to manage their messaging preferences. After opting out, users receive a confirmation message and will not receive further messages until they opt back in."
},
"settings": {
"title": "Phone Number Opt-Out List"
diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json
index b01353c1b..bf3817291 100644
--- a/client/src/translations/es/common.json
+++ b/client/src/translations/es/common.json
@@ -775,7 +775,6 @@
},
"labels": {
"addtoproduction": "",
- "allow_text_message": "",
"checklist": "",
"printpack": "",
"removefromproduction": ""
@@ -2526,7 +2525,6 @@
"fields": {
"accountingid": "",
"address": "Dirección",
- "allow_text_message": "Permiso de texto?",
"name": "Nombre",
"note": "",
"ownr_addr1": "Dirección",
@@ -3878,7 +3876,8 @@
"created_at": "",
"no_owners": "",
"phone_1": "",
- "phone_2": ""
+ "phone_2": "",
+ "text_body": ""
},
"settings": {
"title": ""
diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json
index e77bd39c8..8a4092e1a 100644
--- a/client/src/translations/fr/common.json
+++ b/client/src/translations/fr/common.json
@@ -775,7 +775,6 @@
},
"labels": {
"addtoproduction": "",
- "allow_text_message": "",
"checklist": "",
"printpack": "",
"removefromproduction": ""
@@ -2526,7 +2525,6 @@
"fields": {
"accountingid": "",
"address": "Adresse",
- "allow_text_message": "Autorisation de texte?",
"name": "Prénom",
"note": "",
"ownr_addr1": "Adresse",
@@ -3878,7 +3876,8 @@
"created_at": "Opt-Out Date",
"no_owners": "No Associated Owners",
"phone_1": "Phone 1",
- "phone_2": "Phone 2"
+ "phone_2": "Phone 2",
+ "text_body": ""
},
"settings": {
"title": ""
diff --git a/new_bodyshop_translations.babel b/new_bodyshop_translations.babel
index 5409f6ce5..e92daf2e6 100644
--- a/new_bodyshop_translations.babel
+++ b/new_bodyshop_translations.babel
@@ -10028,25 +10028,6 @@
-
- allow_text_message
-
-
-
-
- en-US
- false
-
-
- es-ES
- false
-
-
- fr-CA
- false
-
-
-
checklist
@@ -33000,25 +32981,6 @@
-
- allow_text_message
-
-
-
-
- en-US
- false
-
-
- es-ES
- false
-
-
- fr-CA
- false
-
-
-
name
diff --git a/server/sms/receive.js b/server/sms/receive.js
index 514d375b4..a9670b76a 100644
--- a/server/sms/receive.js
+++ b/server/sms/receive.js
@@ -12,6 +12,10 @@ const { phone } = require("phone");
const { admin } = require("../firebase/firebase-handler");
const InstanceManager = require("../utils/instanceMgr").default;
+// Note: When we handle different languages, we might need to adjust these keywords accordingly.
+const optInKeywords = ["START", "YES", "UNSTOP"];
+const optOutKeywords = ["STOP", "STOPALL", "UNSUBSCRIBE", "CANCEL", "END", "QUIT", "REVOKE", "OPTOUT"];
+
/**
* Receive SMS messages from Twilio and process them
* @param req
@@ -58,9 +62,6 @@ const receive = async (req, res) => {
const messageText = (req.body.Body || "").trim().toUpperCase();
// Step 2: Check for opt-in or opt-out keywords
- const optInKeywords = ["START", "YES", "UNSTOP"];
- const optOutKeywords = ["STOP", "STOPALL", "UNSUBSCRIBE", "CANCEL", "END", "QUIT"];
-
if (optInKeywords.includes(messageText) || optOutKeywords.includes(messageText)) {
// Check if the phone number is in phone_number_opt_out
const optOutCheck = await client.request(CHECK_PHONE_NUMBER_OPT_OUT, {