{t("settings.title")}
-
- {t("settings.enforce_sms_consent")}
-
- {
- if (!checked && enforceConsent) return; // Prevent disabling
- updateEnforceConsent({
- variables: { id: bodyshop.id, enforce_sms_consent: checked },
- optimisticResponse: {
- update_bodyshops_by_pk: {
- __typename: "bodyshops",
- id: bodyshop.id,
- enforce_sms_consent: checked
- }
- }
- });
- }}
- disabled={enforceConsent}
- />
-
-
- {enforceConsent &&
}
+ {
}
);
}
diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js
index af16899cf..7faff13a2 100644
--- a/client/src/graphql/bodyshop.queries.js
+++ b/client/src/graphql/bodyshop.queries.js
@@ -142,7 +142,6 @@ export const QUERY_BODYSHOP = gql`
intellipay_config
md_ro_guard
notification_followers
- enforce_sms_consent
employee_teams(order_by: { name: asc }, where: { active: { _eq: true } }) {
id
name
@@ -364,12 +363,3 @@ export const GET_ACTIVE_EMPLOYEES_IN_SHOP = gql`
}
}
`;
-
-export const UPDATE_BODYSHOP_ENFORCE_CONSENT = gql`
- mutation UPDATE_BODYSHOP_ENFORCE_CONSENT($id: uuid!, $enforce_sms_consent: Boolean!) {
- update_bodyshops_by_pk(pk_columns: { id: $id }, _set: { enforce_sms_consent: $enforce_sms_consent }) {
- id
- enforce_sms_consent
- }
- }
-`;
diff --git a/client/src/redux/user/user.actions.js b/client/src/redux/user/user.actions.js
index 125aab415..01ba22534 100644
--- a/client/src/redux/user/user.actions.js
+++ b/client/src/redux/user/user.actions.js
@@ -123,8 +123,3 @@ export const setImexShopId = (imexshopid) => ({
type: UserActionTypes.SET_IMEX_SHOP_ID,
payload: imexshopid
});
-
-export const updateBodyshopEnforceConsent = (enforce_sms_consent) => ({
- type: UserActionTypes.UPDATE_BODYSHOP_ENFORCE_CONSENT,
- payload: enforce_sms_consent
-});
diff --git a/client/src/redux/user/user.reducer.js b/client/src/redux/user/user.reducer.js
index a72d4f068..eebb32433 100644
--- a/client/src/redux/user/user.reducer.js
+++ b/client/src/redux/user/user.reducer.js
@@ -125,14 +125,7 @@ const userReducer = (state = INITIAL_STATE, action) => {
...state,
imexshopid: action.payload
};
- case UserActionTypes.UPDATE_BODYSHOP_ENFORCE_CONSENT:
- return {
- ...state,
- bodyshop: {
- ...state.bodyshop,
- enforce_sms_consent: action.payload
- }
- };
+
default:
return state;
}
diff --git a/client/src/redux/user/user.types.js b/client/src/redux/user/user.types.js
index ff21dbb5a..d9cd6fe62 100644
--- a/client/src/redux/user/user.types.js
+++ b/client/src/redux/user/user.types.js
@@ -33,7 +33,6 @@ const UserActionTypes = {
CHECK_ACTION_CODE_FAILURE: "CHECK_ACTION_CODE_FAILURE",
SET_CURRENT_EULA: "SET_CURRENT_EULA",
EULA_ACCEPTED: "EULA_ACCEPTED",
- SET_IMEX_SHOP_ID: "SET_IMEX_SHOP_ID",
- UPDATE_BODYSHOP_ENFORCE_CONSENT: "UPDATE_BODYSHOP_ENFORCE_CONSENT"
+ SET_IMEX_SHOP_ID: "SET_IMEX_SHOP_ID"
};
export default UserActionTypes;
diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json
index e753871c4..5c4e9cd85 100644
--- a/client/src/translations/en_us/common.json
+++ b/client/src/translations/en_us/common.json
@@ -656,6 +656,7 @@
}
},
"labels": {
+ "consent_settings": "Consent Settings",
"2tiername": "Name => RO",
"2tiersetup": "2 Tier Setup",
"2tiersource": "Source => RO",
@@ -2377,7 +2378,8 @@
"errors": {
"invalidphone": "The phone number is invalid. Unable to open conversation. ",
"noattachedjobs": "No Jobs have been associated to this conversation. ",
- "updatinglabel": "Error updating label. {{error}}"
+ "updatinglabel": "Error updating label. {{error}}",
+ "no_consent": "This phone number has not consented to receive messages."
},
"labels": {
"addlabel": "Add a label to this conversation.",
@@ -2393,7 +2395,8 @@
"selectmedia": "Select Media",
"sentby": "Sent by {{by}} at {{time}}",
"typeamessage": "Send a message...",
- "unarchive": "Unarchive"
+ "unarchive": "Unarchive",
+ "no_consent": "No Consent"
},
"render": {
"conversation_list": "Conversation List"
@@ -3862,6 +3865,14 @@
"validation": {
"unique_vendor_name": "You must enter a unique vendor name."
}
+ },
+ "consent": {
+ "phone_number": "Phone Number",
+ "status": "Consent Status",
+ "updated_at": "Last Updated"
+ },
+ "settings": {
+ "title": "Phone Number Opt-Out list"
}
}
}
diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml
index fd83ecbc4..025166032 100644
--- a/hasura/metadata/tables.yaml
+++ b/hasura/metadata/tables.yaml
@@ -957,7 +957,6 @@
- enforce_conversion_category
- enforce_conversion_csr
- enforce_referral
- - enforce_sms_consent
- entegral_configuration
- entegral_id
- features
@@ -1068,7 +1067,6 @@
- enforce_conversion_category
- enforce_conversion_csr
- enforce_referral
- - enforce_sms_consent
- federal_tax_id
- id
- inhousevendorid
@@ -5864,104 +5862,12 @@
url: '{{$base_url}}/opensearch'
version: 2
- table:
- name: phone_number_consent
+ name: phone_number_opt_out
schema: public
object_relationships:
- name: bodyshop
using:
foreign_key_constraint_on: bodyshopid
- array_relationships:
- - name: phone_number_consent_history
- using:
- foreign_key_constraint_on:
- column: phone_number_consent_id
- table:
- name: phone_number_consent_history
- schema: public
- insert_permissions:
- - role: user
- permission:
- check:
- bodyshop:
- associations:
- _and:
- - user:
- authid:
- _eq: X-Hasura-User-Id
- - active:
- _eq: true
- columns:
- - consent_status
- - phone_number
- - consent_updated_at
- - created_at
- - updated_at
- - bodyshopid
- - id
- comment: ""
- select_permissions:
- - role: user
- permission:
- columns:
- - consent_status
- - phone_number
- - consent_updated_at
- - created_at
- - updated_at
- - bodyshopid
- - id
- filter:
- bodyshop:
- associations:
- _and:
- - user:
- authid:
- _eq: X-Hasura-User-Id
- - active:
- _eq: true
- comment: ""
- update_permissions:
- - role: user
- permission:
- columns:
- - bodyshopid
- - consent_status
- - consent_updated_at
- - created_at
- - phone_number
- - updated_at
- filter: {}
- check: null
- comment: ""
-- table:
- name: phone_number_consent_history
- schema: public
- object_relationships:
- - name: phone_number_consent
- using:
- foreign_key_constraint_on: phone_number_consent_id
- select_permissions:
- - role: user
- permission:
- columns:
- - new_value
- - old_value
- - changed_by
- - reason
- - changed_at
- - id
- - phone_number_consent_id
- filter:
- phone_number_consent:
- bodyshop:
- associations:
- _and:
- - user:
- authid:
- _eq: X-Hasura-User-Id
- - active:
- _eq: true
- comment: ""
- table:
name: phonebook
schema: public
diff --git a/hasura/migrations/1747850002182_drop_table_public_phone_number_consent_history/down.sql b/hasura/migrations/1747850002182_drop_table_public_phone_number_consent_history/down.sql
new file mode 100644
index 000000000..8b7230c77
--- /dev/null
+++ b/hasura/migrations/1747850002182_drop_table_public_phone_number_consent_history/down.sql
@@ -0,0 +1,3 @@
+-- Could not auto-generate a down migration.
+-- Please write an appropriate down migration for the SQL below:
+-- DROP table "public"."phone_number_consent_history";
diff --git a/hasura/migrations/1747850002182_drop_table_public_phone_number_consent_history/up.sql b/hasura/migrations/1747850002182_drop_table_public_phone_number_consent_history/up.sql
new file mode 100644
index 000000000..1093c487f
--- /dev/null
+++ b/hasura/migrations/1747850002182_drop_table_public_phone_number_consent_history/up.sql
@@ -0,0 +1 @@
+DROP table "public"."phone_number_consent_history";
diff --git a/hasura/migrations/1747850205206_alter_table_public_phone_number_consent_drop_column_consent_status/down.sql b/hasura/migrations/1747850205206_alter_table_public_phone_number_consent_drop_column_consent_status/down.sql
new file mode 100644
index 000000000..c7f137e6f
--- /dev/null
+++ b/hasura/migrations/1747850205206_alter_table_public_phone_number_consent_drop_column_consent_status/down.sql
@@ -0,0 +1,2 @@
+alter table "public"."phone_number_consent" alter column "consent_status" drop not null;
+alter table "public"."phone_number_consent" add column "consent_status" bool;
diff --git a/hasura/migrations/1747850205206_alter_table_public_phone_number_consent_drop_column_consent_status/up.sql b/hasura/migrations/1747850205206_alter_table_public_phone_number_consent_drop_column_consent_status/up.sql
new file mode 100644
index 000000000..8daf3ed0d
--- /dev/null
+++ b/hasura/migrations/1747850205206_alter_table_public_phone_number_consent_drop_column_consent_status/up.sql
@@ -0,0 +1 @@
+alter table "public"."phone_number_consent" drop column "consent_status" cascade;
diff --git a/hasura/migrations/1747850221535_alter_table_public_phone_number_consent_drop_column_consent_updated_at/down.sql b/hasura/migrations/1747850221535_alter_table_public_phone_number_consent_drop_column_consent_updated_at/down.sql
new file mode 100644
index 000000000..74f22f6fb
--- /dev/null
+++ b/hasura/migrations/1747850221535_alter_table_public_phone_number_consent_drop_column_consent_updated_at/down.sql
@@ -0,0 +1,3 @@
+alter table "public"."phone_number_consent" alter column "consent_updated_at" set default now();
+alter table "public"."phone_number_consent" alter column "consent_updated_at" drop not null;
+alter table "public"."phone_number_consent" add column "consent_updated_at" timestamptz;
diff --git a/hasura/migrations/1747850221535_alter_table_public_phone_number_consent_drop_column_consent_updated_at/up.sql b/hasura/migrations/1747850221535_alter_table_public_phone_number_consent_drop_column_consent_updated_at/up.sql
new file mode 100644
index 000000000..154b0a1e6
--- /dev/null
+++ b/hasura/migrations/1747850221535_alter_table_public_phone_number_consent_drop_column_consent_updated_at/up.sql
@@ -0,0 +1 @@
+alter table "public"."phone_number_consent" drop column "consent_updated_at" cascade;
diff --git a/hasura/migrations/1747850386584_rename_table_public_phone_number_consent/down.sql b/hasura/migrations/1747850386584_rename_table_public_phone_number_consent/down.sql
new file mode 100644
index 000000000..ede0fa6ca
--- /dev/null
+++ b/hasura/migrations/1747850386584_rename_table_public_phone_number_consent/down.sql
@@ -0,0 +1 @@
+alter table "public"."phone_number_opt_out" rename to "phone_number_consent";
diff --git a/hasura/migrations/1747850386584_rename_table_public_phone_number_consent/up.sql b/hasura/migrations/1747850386584_rename_table_public_phone_number_consent/up.sql
new file mode 100644
index 000000000..592a8c243
--- /dev/null
+++ b/hasura/migrations/1747850386584_rename_table_public_phone_number_consent/up.sql
@@ -0,0 +1 @@
+alter table "public"."phone_number_consent" rename to "phone_number_opt_out";
diff --git a/hasura/migrations/1747850458206_alter_table_public_bodyshops_drop_column_enforce_sms_consent/down.sql b/hasura/migrations/1747850458206_alter_table_public_bodyshops_drop_column_enforce_sms_consent/down.sql
new file mode 100644
index 000000000..f25ada416
--- /dev/null
+++ b/hasura/migrations/1747850458206_alter_table_public_bodyshops_drop_column_enforce_sms_consent/down.sql
@@ -0,0 +1,2 @@
+alter table "public"."bodyshops" alter column "enforce_sms_consent" drop not null;
+alter table "public"."bodyshops" add column "enforce_sms_consent" bool;
diff --git a/hasura/migrations/1747850458206_alter_table_public_bodyshops_drop_column_enforce_sms_consent/up.sql b/hasura/migrations/1747850458206_alter_table_public_bodyshops_drop_column_enforce_sms_consent/up.sql
new file mode 100644
index 000000000..57b8d6ebd
--- /dev/null
+++ b/hasura/migrations/1747850458206_alter_table_public_bodyshops_drop_column_enforce_sms_consent/up.sql
@@ -0,0 +1 @@
+alter table "public"."bodyshops" drop column "enforce_sms_consent" cascade;
diff --git a/package-lock.json b/package-lock.json
index 8e0440f9d..0ee5c9545 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,7 +24,7 @@
"aws4": "^1.13.2",
"axios": "^1.8.4",
"better-queue": "^3.8.12",
- "bullmq": "^5.52.3",
+ "bullmq": "^5.53.0",
"chart.js": "^4.4.8",
"cloudinary": "^2.6.1",
"compression": "^1.8.0",
@@ -4634,9 +4634,9 @@
}
},
"node_modules/bullmq": {
- "version": "5.52.3",
- "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.52.3.tgz",
- "integrity": "sha512-UaVkg+uSgylYWjD6/d8TVm87SjDVZ5jKwDVh/pJACmStn71aIzOIpGazh2JrkGISgT10Q/lG2I40FhPg0KgNCQ==",
+ "version": "5.53.0",
+ "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.53.0.tgz",
+ "integrity": "sha512-AbzcwR+9GdgrenolOC9kApF+TkUKZpUCMiFbXgRYw9ivWhOfLCqKeajIptM7NdwhY7cpXgv+QpbweUuQZUxkyA==",
"license": "MIT",
"dependencies": {
"cron-parser": "^4.9.0",
diff --git a/package.json b/package.json
index a2da483f7..5eec68f9b 100644
--- a/package.json
+++ b/package.json
@@ -31,7 +31,7 @@
"aws4": "^1.13.2",
"axios": "^1.8.4",
"better-queue": "^3.8.12",
- "bullmq": "^5.52.3",
+ "bullmq": "^5.53.0",
"chart.js": "^4.4.8",
"cloudinary": "^2.6.1",
"compression": "^1.8.0",
diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js
index 84e20db6f..d61d814b9 100644
--- a/server/graphql-client/queries.js
+++ b/server/graphql-client/queries.js
@@ -2805,7 +2805,6 @@ exports.GET_BODYSHOP_BY_ID = `
intellipay_config
state
notification_followers
- enforce_sms_consent
}
}
`;
@@ -2969,132 +2968,3 @@ exports.GET_JOB_WATCHERS_MINIMAL = `
}
}
`;
-
-// Query to get consent status for a single phone number
-exports.GET_PHONE_NUMBER_CONSENT = `
- query GET_PHONE_NUMBER_CONSENT($bodyshopid: uuid!, $phone_number: String!) {
- phone_number_consent(where: { bodyshopid: { _eq: $bodyshopid }, phone_number: { _eq: $phone_number } }) {
- id
- bodyshopid
- phone_number
- consent_status
- created_at
- updated_at
- consent_updated_at
- phone_number_consent_history(order_by: { changed_at: desc }) {
- id
- old_value
- new_value
- reason
- changed_at
- changed_by
- }
- }
- }
-`;
-
-// Query to get consent statuses for multiple phone numbers
-exports.GET_PHONE_NUMBER_CONSENTS = `
- query GET_PHONE_NUMBER_CONSENTS($bodyshopid: uuid!, $phone_numbers: [String!]) {
- phone_number_consent(where: { bodyshopid: { _eq: $bodyshopid }, phone_number: { _in: $phone_numbers } }) {
- id
- bodyshopid
- phone_number
- consent_status
- created_at
- updated_at
- consent_updated_at
- phone_number_consent_history(order_by: { changed_at: desc }) {
- id
- old_value
- new_value
- reason
- changed_at
- changed_by
- }
- }
- }
-`;
-
-// Mutation to update enforce_sms_consent
-exports.UPDATE_BODYSHOP_ENFORCE_CONSENT = `
- mutation UPDATE_BODYSHOP_ENFORCE_CONSENT($id: uuid!, $enforce_sms_consent: Boolean!) {
- update_bodyshops_by_pk(
- pk_columns: { id: $id }
- _set: { enforce_sms_consent: $enforce_sms_consent }
- ) {
- id
- enforce_sms_consent
- }
- }
-`;
-
-// Mutation to set consent status for a single phone number
-exports.SET_PHONE_NUMBER_CONSENT = `
- mutation SET_PHONE_NUMBER_CONSENT($bodyshopid: uuid!, $phone_number: String!, $consent_status: Boolean!) {
- insert_phone_number_consent_one(
- object: {
- bodyshopid: $bodyshopid
- phone_number: $phone_number
- consent_status: $consent_status
- consent_updated_at: "now()"
- }
- on_conflict: {
- constraint: phone_number_consent_bodyshopid_phone_number_key
- update_columns: [consent_status, consent_updated_at]
- }
- ) {
- id
- bodyshopid
- phone_number
- consent_status
- created_at
- updated_at
- consent_updated_at
- }
- }
-`;
-
-// Mutation to set consent status for multiple phone numbers
-exports.BULK_SET_PHONE_NUMBER_CONSENT = `
- mutation BULK_SET_PHONE_NUMBER_CONSENT($objects: [phone_number_consent_insert_input!]!) {
- insert_phone_number_consent(
- objects: $objects
- on_conflict: {
- constraint: phone_number_consent_bodyshopid_phone_number_key
- update_columns: [consent_status, consent_updated_at]
- }
- ) {
- affected_rows
- returning {
- id
- bodyshopid
- phone_number
- consent_status
- created_at
- updated_at
- consent_updated_at
- }
- }
- }
-`;
-
-// Mutation to insert multiple consent history records
-exports.INSERT_PHONE_NUMBER_CONSENT_HISTORY = `
- mutation INSERT_PHONE_NUMBER_CONSENT_HISTORY($objects: [phone_number_consent_history_insert_input!]!) {
- insert_phone_number_consent_history(
- objects: $objects
- ) {
- affected_rows
- returning {
- id
- phone_number_consent_id
- old_value
- new_value
- reason
- changed_at
- changed_by
- }
- }
- }
-`;
diff --git a/server/routes/smsRoutes.js b/server/routes/smsRoutes.js
index 917699aaf..bb23d24e8 100644
--- a/server/routes/smsRoutes.js
+++ b/server/routes/smsRoutes.js
@@ -5,7 +5,6 @@ const { receive } = require("../sms/receive");
const { send } = require("../sms/send");
const { status, markConversationRead } = require("../sms/status");
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
-const { setConsent, bulkSetConsent } = require("../sms/consent");
// Twilio Webhook Middleware for production
const twilioWebhookMiddleware = twilio.webhook({ validate: process.env.NODE_ENV === "PRODUCTION" });
@@ -14,7 +13,5 @@ router.post("/receive", twilioWebhookMiddleware, receive);
router.post("/send", validateFirebaseIdTokenMiddleware, send);
router.post("/status", twilioWebhookMiddleware, status);
router.post("/markConversationRead", validateFirebaseIdTokenMiddleware, markConversationRead);
-router.post("/setConsent", validateFirebaseIdTokenMiddleware, setConsent);
-router.post("/bulkSetConsent", validateFirebaseIdTokenMiddleware, bulkSetConsent);
module.exports = router;
diff --git a/server/sms/consent.js b/server/sms/consent.js
deleted file mode 100644
index d7a997423..000000000
--- a/server/sms/consent.js
+++ /dev/null
@@ -1,215 +0,0 @@
-const {
- SET_PHONE_NUMBER_CONSENT,
- BULK_SET_PHONE_NUMBER_CONSENT,
- INSERT_PHONE_NUMBER_CONSENT_HISTORY
-} = require("../graphql-client/queries");
-const { phone } = require("phone");
-const gqlClient = require("../graphql-client/graphql-client").client;
-
-/**
- * Set SMS consent for a phone number
- * @param req
- * @param res
- * @returns {Promise<*>}
- */
-const setConsent = async (req, res) => {
- const { bodyshopid, phone_number, consent_status, reason, changed_by } = req.body;
- const {
- logger,
- ioRedis,
- ioHelpers: { getBodyshopRoom },
- sessionUtils: { getBodyshopFromRedis }
- } = req;
-
- if (!bodyshopid || !phone_number || consent_status === undefined || !reason || !changed_by) {
- logger.log("set-consent-error", "ERROR", req.user.email, null, {
- type: "missing-parameters",
- bodyshopid,
- phone_number,
- consent_status,
- reason,
- changed_by
- });
- return res.status(400).json({ success: false, message: "Missing required parameter(s)." });
- }
-
- try {
- // Check enforce_sms_consent
- const bodyShopData = await getBodyshopFromRedis(bodyshopid);
- const enforceConsent = bodyShopData?.enforce_sms_consent ?? false;
-
- if (!enforceConsent) {
- logger.log("set-consent-error", "ERROR", req.user.email, null, {
- type: "consent-not-enforced",
- bodyshopid
- });
- return res.status(403).json({ success: false, message: "SMS consent enforcement is not enabled." });
- }
-
- const normalizedPhone = phone(phone_number, "CA").phoneNumber.replace(/^\+1/, "");
- const consentResponse = await gqlClient.request(SET_PHONE_NUMBER_CONSENT, {
- bodyshopid,
- phone_number: normalizedPhone,
- consent_status
- });
-
- const consent = consentResponse.insert_phone_number_consent_one;
-
- // Log audit history
- const historyResponse = await gqlClient.request(INSERT_PHONE_NUMBER_CONSENT_HISTORY, {
- objects: [
- {
- phone_number_consent_id: consent.id,
- old_value: null, // Not tracking old value
- new_value: consent_status,
- reason,
- changed_by,
- changed_at: "now()"
- }
- ]
- });
-
- const history = historyResponse.insert_phone_number_consent_history.returning[0];
-
- // Emit WebSocket event
- const broadcastRoom = getBodyshopRoom(bodyshopid);
- ioRedis.to(broadcastRoom).emit("consent-changed", {
- bodyshopId: bodyshopid,
- phone_number: normalizedPhone,
- consent_status,
- reason
- });
-
- logger.log("set-consent-success", "DEBUG", req.user.email, null, {
- bodyshopid,
- phone_number: normalizedPhone,
- consent_status
- });
-
- // Return both consent and history
- res.status(200).json({
- success: true,
- consent: {
- ...consent,
- phone_number_consent_history: [history]
- }
- });
- } catch (error) {
- logger.log("set-consent-error", "ERROR", req.user.email, null, {
- bodyshopid,
- phone_number,
- error: error.message,
- stack: error.stack
- });
- res.status(500).json({ success: false, message: "Failed to update consent status." });
- }
-};
-
-/**
- * Bulk set SMS consent for multiple phone numbers
- * @param req
- * @param res
- * @returns {Promise<*>}
- */
-const bulkSetConsent = async (req, res) => {
- const { bodyshopid, consents } = req.body; // consents: [{ phone_number, consent_status }]
- const {
- logger,
- ioRedis,
- ioHelpers: { getBodyshopRoom },
- sessionUtils: { getBodyshopFromRedis }
- } = req;
-
- if (!bodyshopid || !Array.isArray(consents) || consents.length === 0) {
- logger.log("bulk-set-consent-error", "ERROR", req.user.email, null, {
- type: "missing-parameters",
- bodyshopid,
- consents
- });
- return res.status(400).json({ success: false, message: "Missing or invalid parameters." });
- }
-
- try {
- // Check enforce_sms_consent
- const bodyShopData = await getBodyshopFromRedis(bodyshopid);
- const enforceConsent = bodyShopData?.enforce_sms_consent ?? false;
-
- if (!enforceConsent) {
- logger.log("bulk-set-consent-error", "ERROR", req.user.email, null, {
- type: "consent-not-enforced",
- bodyshopid
- });
- return res.status(403).json({ success: false, message: "SMS consent enforcement is not enabled." });
- }
-
- const objects = consents.map(({ phone_number, consent_status }) => ({
- bodyshopid,
- phone_number: phone(phone_number, "CA").phoneNumber.replace(/^\+1/, ""),
- consent_status,
- consent_updated_at: "now()"
- }));
-
- // Insert or update phone_number_consent records
- const consentResponse = await gqlClient.request(BULK_SET_PHONE_NUMBER_CONSENT, {
- objects
- });
-
- const updatedConsents = consentResponse.insert_phone_number_consent.returning;
-
- // Log audit history
- const historyObjects = updatedConsents.map((consent) => ({
- phone_number_consent_id: consent.id,
- old_value: null, // Not tracking old value for bulk updates
- new_value: consent.consent_status,
- reason: "System update via bulk upload",
- changed_by: "system",
- changed_at: "now()"
- }));
-
- const historyResponse = await gqlClient.request(INSERT_PHONE_NUMBER_CONSENT_HISTORY, {
- objects: historyObjects
- });
-
- const history = historyResponse.insert_phone_number_consent_history.returning;
-
- // Combine consents with their history
- const consentsWithhistory = updatedConsents.map((consent, index) => ({
- ...consent,
- phone_number_consent_history: [history[index]]
- }));
-
- // Emit WebSocket events for each consent change
- const broadcastRoom = getBodyshopRoom(bodyshopid);
- updatedConsents.forEach((consent) => {
- ioRedis.to(broadcastRoom).emit("consent-changed", {
- bodyshopId: bodyshopid,
- phone_number: consent.phone_number,
- consent_status: consent.consent_status,
- reason: "System update via bulk upload"
- });
- });
-
- logger.log("bulk-set-consent-success", "DEBUG", req.user.email, null, {
- bodyshopid,
- updatedCount: updatedConsents.length
- });
-
- res.status(200).json({
- success: true,
- updatedCount: updatedConsents.length,
- consents: consentsWithhistory
- });
- } catch (error) {
- logger.log("bulk-set-consent-error", "ERROR", req.user.email, null, {
- bodyshopid,
- error: error.message,
- stack: error.stack
- });
- res.status(500).json({ success: false, message: "Failed to update consents." });
- }
-};
-
-module.exports = {
- setConsent,
- bulkSetConsent
-};
diff --git a/server/sms/receive.js b/server/sms/receive.js
index 59c4b1b32..ad539dbe4 100644
--- a/server/sms/receive.js
+++ b/server/sms/receive.js
@@ -3,8 +3,7 @@ const {
FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID,
UNARCHIVE_CONVERSATION,
CREATE_CONVERSATION,
- INSERT_MESSAGE,
- SET_PHONE_NUMBER_CONSENT
+ INSERT_MESSAGE
} = require("../graphql-client/queries");
const { phone } = require("phone");
const { admin } = require("../firebase/firebase-handler");
@@ -17,11 +16,11 @@ const InstanceManager = require("../utils/instanceMgr").default;
* @returns {Promise<*>}
*/
const receive = async (req, res) => {
+ console.dir(req.body);
const {
logger,
ioRedis,
- ioHelpers: { getBodyshopRoom, getBodyshopConversationRoom },
- sessionUtils: { getBodyshopFromRedis }
+ ioHelpers: { getBodyshopRoom, getBodyshopConversationRoom }
} = req;
const loggerData = {
@@ -54,35 +53,6 @@ const receive = async (req, res) => {
const bodyshop = response.bodyshops[0];
- // Step 2: Check enforce_sms_consent
- const bodyShopData = await getBodyshopFromRedis(bodyshopid);
- const enforceConsent = bodyShopData?.enforce_sms_consent ?? false;
-
- // Step 3: Handle consent only if enforce_sms_consent is true
- if (enforceConsent) {
- const normalizedPhone = phone(req.body.From, "CA").phoneNumber.replace(/^\+1/, "");
- const isStop = req.body.Body.toUpperCase().includes("STOP");
- const consentStatus = isStop ? false : true;
- const reason = isStop ? "Customer texted STOP" : "Inbound message received";
-
- const consentResponse = await client.request(SET_PHONE_NUMBER_CONSENT, {
- bodyshopid: bodyshop.id,
- phone_number: normalizedPhone,
- consent_status: consentStatus,
- reason,
- changed_by: "system"
- });
-
- // Emit WebSocket event for consent change
- const broadcastRoom = getBodyshopRoom(bodyshop.id);
- ioRedis.to(broadcastRoom).emit("consent-changed", {
- bodyshopId: bodyshop.id,
- phone_number: normalizedPhone,
- consent_status: consentStatus,
- reason
- });
- }
-
// Step 4: Process conversation
const sortedConversations = bodyshop.conversations.sort((a, b) => new Date(a.created_at) - new Date(b.created_at));
const existingConversation = sortedConversations.length
diff --git a/server/sms/send.js b/server/sms/send.js
index 81b2d4d6d..aa3c5a84c 100644
--- a/server/sms/send.js
+++ b/server/sms/send.js
@@ -1,6 +1,6 @@
const twilio = require("twilio");
const { phone } = require("phone");
-const { INSERT_MESSAGE, GET_PHONE_NUMBER_CONSENT } = require("../graphql-client/queries");
+const { INSERT_MESSAGE } = require("../graphql-client/queries");
const client = twilio(process.env.TWILIO_AUTH_TOKEN, process.env.TWILIO_AUTH_KEY);
const gqlClient = require("../graphql-client/graphql-client").client;
@@ -42,30 +42,6 @@ const send = async (req, res) => {
}
try {
- // Check bodyshop's enforce_sms_consent setting
- const bodyShopData = await getBodyshopFromRedis(bodyshopid);
- const enforceConsent = bodyShopData?.enforce_sms_consent ?? false;
-
- // Check consent only if enforcement is enabled
- if (enforceConsent) {
- const normalizedPhone = phone(to, "CA").phoneNumber.replace(/^\+1/, "");
- const consentResponse = await gqlClient.request(GET_PHONE_NUMBER_CONSENT, {
- bodyshopid,
- phone_number: normalizedPhone
- });
- if (!consentResponse.phone_number_consent?.length || !consentResponse.phone_number_consent[0].consent_status) {
- logger.log("sms-outbound-error", "ERROR", req.user.email, null, {
- type: "no-consent",
- phone_number: normalizedPhone,
- conversationid
- });
- return res.status(403).json({
- success: false,
- message: "Phone number has not consented to messaging."
- });
- }
- }
-
const message = await client.messages.create({
body,
messagingServiceSid,
diff --git a/server/sms/status.js b/server/sms/status.js
index 509c76d6b..385dbaa40 100644
--- a/server/sms/status.js
+++ b/server/sms/status.js
@@ -9,6 +9,7 @@ const logger = require("../utils/logger");
* @returns {Promise<*>}
*/
const status = async (req, res) => {
+ console.dir(req.body);
const { SmsSid, SmsStatus } = req.body;
const {
ioRedis,