Base
This commit is contained in:
parent
750d472c37
commit
fd155575d4
@ -0,0 +1,75 @@
|
||||
'use strict';
|
||||
|
||||
const businessColumns = {
|
||||
street_address: { type: 'TEXT' },
|
||||
address_line_2: { type: 'TEXT' },
|
||||
city: { type: 'TEXT' },
|
||||
state: { type: 'TEXT' },
|
||||
postal_code: { type: 'TEXT' },
|
||||
country: { type: 'TEXT' },
|
||||
website_url: { type: 'TEXT' },
|
||||
business_phone: { type: 'TEXT' },
|
||||
business_email: { type: 'TEXT' },
|
||||
timezone: { type: 'TEXT' },
|
||||
};
|
||||
|
||||
function normalizeColumnDefinition(Sequelize, definition) {
|
||||
const normalized = { ...definition };
|
||||
|
||||
if (definition.type === 'TEXT') {
|
||||
normalized.type = Sequelize.DataTypes.TEXT;
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
async function addColumnsIfMissing(queryInterface, Sequelize, transaction, tableName, columns) {
|
||||
const table = await queryInterface.describeTable(tableName);
|
||||
|
||||
for (const [columnName, definition] of Object.entries(columns)) {
|
||||
if (!table[columnName]) {
|
||||
await queryInterface.addColumn(
|
||||
tableName,
|
||||
columnName,
|
||||
normalizeColumnDefinition(Sequelize, definition),
|
||||
{ transaction },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function removeColumnsIfPresent(queryInterface, transaction, tableName, columns) {
|
||||
const table = await queryInterface.describeTable(tableName);
|
||||
|
||||
for (const columnName of Object.keys(columns).reverse()) {
|
||||
if (table[columnName]) {
|
||||
await queryInterface.removeColumn(tableName, columnName, { transaction });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
async up(queryInterface, Sequelize) {
|
||||
const transaction = await queryInterface.sequelize.transaction();
|
||||
|
||||
try {
|
||||
await addColumnsIfMissing(queryInterface, Sequelize, transaction, 'businesses', businessColumns);
|
||||
await transaction.commit();
|
||||
} catch (error) {
|
||||
await transaction.rollback();
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
async down(queryInterface) {
|
||||
const transaction = await queryInterface.sequelize.transaction();
|
||||
|
||||
try {
|
||||
await removeColumnsIfPresent(queryInterface, transaction, 'businesses', businessColumns);
|
||||
await transaction.commit();
|
||||
} catch (error) {
|
||||
await transaction.rollback();
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -15,6 +15,46 @@ name: {
|
||||
|
||||
},
|
||||
|
||||
street_address: {
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
|
||||
address_line_2: {
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
|
||||
city: {
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
|
||||
state: {
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
|
||||
postal_code: {
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
|
||||
country: {
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
|
||||
website_url: {
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
|
||||
business_phone: {
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
|
||||
business_email: {
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
|
||||
timezone: {
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
|
||||
google_review_link: {
|
||||
type: DataTypes.TEXT,
|
||||
|
||||
|
||||
@ -108,6 +108,21 @@ function normalizeOptionalUrl(value, message) {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
function normalizeOptionalWebsiteUrl(value) {
|
||||
const normalized = normalizeString(value);
|
||||
|
||||
if (!normalized) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const url = /^[a-zA-Z][a-zA-Z\d+.-]*:\/\//.test(normalized)
|
||||
? normalized
|
||||
: `https://${normalized}`;
|
||||
|
||||
validateUrl(url, 'Website must be a valid URL.');
|
||||
return url;
|
||||
}
|
||||
|
||||
function normalizeOptionalDate(value, message) {
|
||||
const normalized = normalizeString(value);
|
||||
|
||||
@ -136,11 +151,11 @@ function normalizeDefaultReviewPlatform(value, fallback = 'google') {
|
||||
return DEFAULT_REVIEW_PLATFORMS.has(fallback) ? fallback : 'google';
|
||||
}
|
||||
|
||||
function normalizeOptionalEmail(value) {
|
||||
function normalizeOptionalEmail(value, message = 'Reply-to email must be a valid email address.') {
|
||||
const normalized = normalizeString(value).toLowerCase();
|
||||
|
||||
if (normalized && !EMAIL_PATTERN.test(normalized)) {
|
||||
const error = new Error('Reply-to email must be a valid email address.');
|
||||
const error = new Error(message);
|
||||
error.code = 400;
|
||||
throw error;
|
||||
}
|
||||
@ -507,6 +522,19 @@ router.put('/growth-tools/business', wrapAsync(async (req, res) => {
|
||||
business = await db.businesses.create({
|
||||
name: businessName,
|
||||
business_type: normalizeBusinessType(body.businessType || body.business_type, 'hybrid'),
|
||||
street_address: normalizeString(body.streetAddress ?? body.street_address),
|
||||
address_line_2: normalizeString(body.addressLine2 ?? body.address_line_2),
|
||||
city: normalizeString(body.city),
|
||||
state: normalizeString(body.state),
|
||||
postal_code: normalizeString(body.postalCode ?? body.postal_code),
|
||||
country: normalizeString(body.country),
|
||||
website_url: normalizeOptionalWebsiteUrl(body.websiteUrl ?? body.website_url),
|
||||
business_phone: normalizeString(body.businessPhone ?? body.business_phone),
|
||||
business_email: normalizeOptionalEmail(
|
||||
body.businessEmail ?? body.business_email,
|
||||
'Business email must be a valid email address.',
|
||||
),
|
||||
timezone: normalizeString(body.timezone),
|
||||
automation_mode: 'set_and_forget',
|
||||
is_active: parseBoolean(body.isActive ?? body.is_active, true),
|
||||
createdById: currentUser.id,
|
||||
@ -557,6 +585,19 @@ router.put('/growth-tools/business', wrapAsync(async (req, res) => {
|
||||
const updatePayload = {
|
||||
name: businessName || business.name,
|
||||
business_type: businessType,
|
||||
street_address: normalizeString(body.streetAddress ?? body.street_address ?? business.street_address),
|
||||
address_line_2: normalizeString(body.addressLine2 ?? body.address_line_2 ?? business.address_line_2),
|
||||
city: normalizeString(body.city ?? business.city),
|
||||
state: normalizeString(body.state ?? business.state),
|
||||
postal_code: normalizeString(body.postalCode ?? body.postal_code ?? business.postal_code),
|
||||
country: normalizeString(body.country ?? business.country),
|
||||
website_url: normalizeOptionalWebsiteUrl(body.websiteUrl ?? body.website_url ?? business.website_url),
|
||||
business_phone: normalizeString(body.businessPhone ?? body.business_phone ?? business.business_phone),
|
||||
business_email: normalizeOptionalEmail(
|
||||
body.businessEmail ?? body.business_email ?? business.business_email,
|
||||
'Business email must be a valid email address.',
|
||||
),
|
||||
timezone: normalizeString(body.timezone ?? business.timezone),
|
||||
automation_mode: normalizeString(body.automationMode || body.automation_mode) || 'set_and_forget',
|
||||
ownerId,
|
||||
review_destination: reviewDestination,
|
||||
|
||||
@ -1013,6 +1013,16 @@ function serializeBusiness(req, business) {
|
||||
return {
|
||||
id: business.id,
|
||||
name: business.name,
|
||||
street_address: business.street_address || '',
|
||||
address_line_2: business.address_line_2 || '',
|
||||
city: business.city || '',
|
||||
state: business.state || '',
|
||||
postal_code: business.postal_code || '',
|
||||
country: business.country || '',
|
||||
website_url: business.website_url || '',
|
||||
business_phone: business.business_phone || '',
|
||||
business_email: business.business_email || '',
|
||||
timezone: business.timezone || '',
|
||||
ownerId: business.ownerId || '',
|
||||
is_active: business.is_active !== false,
|
||||
stripe_account_reference: business.stripe_account_reference || '',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user