@b2y/ecommerce-common 1.1.6 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/constants/AppConstants.js +8 -0
- package/constants/StatusMessageConstants.js +37 -0
- package/controller/LocationController.js +144 -0
- package/controller/SubscriptionAbstractController.js +161 -0
- package/controller/TenantAbstractController.js +349 -0
- package/controller/TenantSettingsAbstractController.js +70 -0
- package/index.js +5 -2
- package/package.json +1 -1
|
@@ -3,5 +3,13 @@ const AppConstants = {
|
|
|
3
3
|
LAST_30DAYS: 'LAST30DAYS',
|
|
4
4
|
LAST_6MONTHS: 'LAST6MONTHS',
|
|
5
5
|
OLDER: 'OLDER',
|
|
6
|
+
COMPANY_NAME: 'CompanyName',
|
|
7
|
+
COMPANY_CODE: 'CompanyCode',
|
|
8
|
+
EMAIL: 'Email',
|
|
9
|
+
PHONE_NUMBER: 'PhoneNumber',
|
|
10
|
+
CUSTOMER_PORTAL_DOMAIN: 'CustomerPortalDomain',
|
|
11
|
+
ADMIN_PORTAL_DOMAIN: 'AdminPortalDomain',
|
|
12
|
+
CREATED_BY:'0000d6ab-8064-4786-a906-f458567224b8',
|
|
13
|
+
BOOLEAN:'boolean'
|
|
6
14
|
}
|
|
7
15
|
module.exports = AppConstants;
|
|
@@ -1,4 +1,41 @@
|
|
|
1
1
|
const StatusMessageConstants = {
|
|
2
|
+
SUCCESS: 'Success',
|
|
3
|
+
FAILURE: 'Failure',
|
|
4
|
+
INVALID_REQUEST: 'Invalid request parameters',
|
|
5
|
+
SERVER_ERROR: 'Internal server error',
|
|
6
|
+
// Tenant
|
|
7
|
+
TENANT_NOT_FOUND: 'Tenant not found',
|
|
8
|
+
TENANT_ID_REQUIRED_FIELD: 'TenantID is required for updating the tenant',
|
|
9
|
+
TENANT_UPDATED_SUCCESS: 'Tenant updated successfully',
|
|
10
|
+
TENANT_UPDATE_ERROR: 'Failed to update tenant',
|
|
11
|
+
TENANT_ALREADY_EXISTS: 'Tenant with this information already exists',
|
|
12
|
+
INVALID_EMAIL_FORMAT: 'Invalid email format provided',
|
|
13
|
+
INVALID_PHONE_FORMAT: 'Phone number must be 10-20 digits',
|
|
14
|
+
INVALID_COMPANY_CODE: 'Company code must be a valid positive integer',
|
|
15
|
+
INVALID_SUBSCRIPTION_STATUS: "Invalid subscription status",
|
|
16
|
+
COMPANY_NAME_EXISTS: 'Company name already exists',
|
|
17
|
+
COMPANY_CODE_EXISTS: 'Company code already exists',
|
|
18
|
+
EMAIL_EXISTS: 'Email already exists',
|
|
19
|
+
PHONE_NUMBER_EXISTS: 'Phone number already exists',
|
|
20
|
+
CUSTOMER_PORTAL_DOMAIN_EXISTS: 'Customer portal domain already exists',
|
|
21
|
+
ADMIN_PORTAL_DOMAIN_EXISTS: 'Admin portal domain already exists',
|
|
22
|
+
INVALID_START_END_DATE: 'End date can not be before start date',
|
|
23
|
+
SUBSCRIPTION_PLAN_NOT_FOUND: "Subscription plan not found",
|
|
24
|
+
INVALID_BOOLEAN_TYPE: "{field} must be boolean value",
|
|
25
|
+
|
|
26
|
+
//TenantSettings
|
|
27
|
+
TENANT_SETTINGS_NOT_FOUND: "Tenant settings not foundd",
|
|
28
|
+
|
|
29
|
+
//Location
|
|
30
|
+
STATE_CODE_COUNTRY_CODE_REQUIRE: "State code and country code are required to fetch cities",
|
|
31
|
+
CITIES_NOT_FOUND: "No cities found for given state code",
|
|
32
|
+
COUNTRY_CODE_REQUIRE: "Country code is required to fetch states",
|
|
33
|
+
STATES_NOT_FOUND: "No states found for given country code",
|
|
34
|
+
STATES_FETCH_ERROR: "Error occured while fetching states",
|
|
35
|
+
CITIES_FETCH_ERROR: "Error occurred while fetching cities",
|
|
36
|
+
COUNTRIES_FETCH_ERROR: "Error occurred while fetching countries",
|
|
37
|
+
|
|
38
|
+
// Product Variant
|
|
2
39
|
PRODUCTVARIANT_INVALID_MRP: 'Invalid MRP: must be positive',
|
|
3
40
|
PRODUCTVARIANT_MISSING_PRICE_OR_DISCOUNT: 'Either SellingPrice or DiscountPercentage must be provided',
|
|
4
41
|
PRODUCTVARIANT_INCONSISTENT_PRICING: 'Inconsistent pricing: provided discount percentage does not match calculated value',
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
const {
|
|
2
|
+
getCountries,
|
|
3
|
+
getStatesOfCountry,
|
|
4
|
+
getCitiesOfState,
|
|
5
|
+
} = require("@countrystatecity/countries");
|
|
6
|
+
const AppUtil = require("../utility/AppUtil");
|
|
7
|
+
const StatusMessage = require("../constants/StatusMessageConstants");
|
|
8
|
+
|
|
9
|
+
// Get all cities by state filters
|
|
10
|
+
const getCitiesByState = (logger) => {
|
|
11
|
+
return async (req, res) => {
|
|
12
|
+
try {
|
|
13
|
+
const { countryCode, stateCode } = req.params;
|
|
14
|
+
if (!countryCode || !stateCode) {
|
|
15
|
+
return AppUtil.generateResponse(
|
|
16
|
+
400,
|
|
17
|
+
StatusMessage.FAILURE,
|
|
18
|
+
StatusMessage.STATE_CODE_COUNTRY_CODE_REQUIRE,
|
|
19
|
+
null,
|
|
20
|
+
res,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
const cities = await getCitiesOfState(countryCode, stateCode);
|
|
24
|
+
if (!cities || cities.length === 0) {
|
|
25
|
+
logger.debug("No cities found for state code:", stateCode);
|
|
26
|
+
return AppUtil.generateResponse(
|
|
27
|
+
200,
|
|
28
|
+
StatusMessage.SUCCESS,
|
|
29
|
+
StatusMessage.CITIES_NOT_FOUND,
|
|
30
|
+
null,
|
|
31
|
+
res,
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
const cityNames = cities.map((c) => ({
|
|
35
|
+
CityName: c.name,
|
|
36
|
+
latitude: c.latitude,
|
|
37
|
+
longitude: c.longitude,
|
|
38
|
+
}));
|
|
39
|
+
logger.debug("cities retrieved successfully");
|
|
40
|
+
return AppUtil.generateResponse(
|
|
41
|
+
200,
|
|
42
|
+
StatusMessage.SUCCESS,
|
|
43
|
+
null,
|
|
44
|
+
cityNames,
|
|
45
|
+
res,
|
|
46
|
+
);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
logger.error("Invalid filter format:", error);
|
|
49
|
+
return AppUtil.generateResponse(
|
|
50
|
+
500,
|
|
51
|
+
StatusMessage.FAILURE,
|
|
52
|
+
StatusMessage.CITIES_FETCH_ERROR,
|
|
53
|
+
null,
|
|
54
|
+
res,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const getStatesByCountry = (logger) => {
|
|
61
|
+
return async (req, res) => {
|
|
62
|
+
try {
|
|
63
|
+
const { countryCode } = req.params;
|
|
64
|
+
if (!countryCode) {
|
|
65
|
+
return AppUtil.generateResponse(
|
|
66
|
+
400,
|
|
67
|
+
StatusMessage.FAILURE,
|
|
68
|
+
StatusMessage.COUNTRY_CODE_REQUIRE,
|
|
69
|
+
null,
|
|
70
|
+
res,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
const states = await getStatesOfCountry(countryCode);
|
|
74
|
+
if (!states || states.length === 0) {
|
|
75
|
+
logger.debug("No states found for country code:", countryCode);
|
|
76
|
+
return AppUtil.generateResponse(
|
|
77
|
+
200,
|
|
78
|
+
StatusMessage.SUCCESS,
|
|
79
|
+
StatusMessage.STATES_NOT_FOUND,
|
|
80
|
+
null,
|
|
81
|
+
res,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
// Transform to simpler format
|
|
85
|
+
const formattedStates = states.map((s) => ({
|
|
86
|
+
Code: s.iso2,
|
|
87
|
+
StateName: s.name,
|
|
88
|
+
StateCode: s.state_code,
|
|
89
|
+
}));
|
|
90
|
+
logger.debug("States retrieved successfully");
|
|
91
|
+
return AppUtil.generateResponse(
|
|
92
|
+
200,
|
|
93
|
+
StatusMessage.SUCCESS,
|
|
94
|
+
null,
|
|
95
|
+
formattedStates,
|
|
96
|
+
res,
|
|
97
|
+
);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
logger.error("Error searching for country:", error);
|
|
100
|
+
return AppUtil.generateResponse(
|
|
101
|
+
500,
|
|
102
|
+
StatusMessage.FAILURE,
|
|
103
|
+
StatusMessage.STATES_FETCH_ERROR,
|
|
104
|
+
null,
|
|
105
|
+
res,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
//Getall countries list
|
|
112
|
+
const getAllCountries = (logger) => {
|
|
113
|
+
return async (req, res) => {
|
|
114
|
+
try {
|
|
115
|
+
const countries = await getCountries();
|
|
116
|
+
// transform to simpler format
|
|
117
|
+
const formattedCountries = countries.map((country) => ({
|
|
118
|
+
CountryCode: country.iso2,
|
|
119
|
+
CountryName: country.name,
|
|
120
|
+
iso3: country.iso3,
|
|
121
|
+
PhoneCode: country.phonecode,
|
|
122
|
+
flag: country.emoji,
|
|
123
|
+
}));
|
|
124
|
+
return AppUtil.generateResponse(
|
|
125
|
+
200,
|
|
126
|
+
StatusMessage.SUCCESS,
|
|
127
|
+
null,
|
|
128
|
+
formattedCountries,
|
|
129
|
+
res,
|
|
130
|
+
);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
logger.error("Error fetching countries:", error);
|
|
133
|
+
return AppUtil.generateResponse(
|
|
134
|
+
500,
|
|
135
|
+
StatusMessage.FAILURE,
|
|
136
|
+
StatusMessage.COUNTRIES_FETCH_ERROR,
|
|
137
|
+
null,
|
|
138
|
+
res,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
module.exports = { getCitiesByState, getStatesByCountry, getAllCountries };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
const StatusMessage = require('../constants/StatusMessageConstants');
|
|
2
|
+
const AppUtil = require('../utility/AppUtil');
|
|
3
|
+
const LocationUtility = require('../utility/LocationUtility');
|
|
4
|
+
|
|
5
|
+
// getAllSubscriptionPlans
|
|
6
|
+
const getAllSubscriptionPlans = (
|
|
7
|
+
SubscriptionPlan,
|
|
8
|
+
SubscriptionFeature,
|
|
9
|
+
logger,
|
|
10
|
+
) => {
|
|
11
|
+
return async (req, res) => {
|
|
12
|
+
const { pageNumber, pageSize } = req.query;
|
|
13
|
+
const { limit, offset } = AppUtil.getPagination(pageNumber, pageSize);
|
|
14
|
+
try {
|
|
15
|
+
const { rows, count } = await SubscriptionPlan.findAndCountAll({
|
|
16
|
+
attributes: [
|
|
17
|
+
"SubscriptionPlanID",
|
|
18
|
+
"PlanName",
|
|
19
|
+
"PlanCode",
|
|
20
|
+
"Price",
|
|
21
|
+
"BillingCycle",
|
|
22
|
+
"Currency",
|
|
23
|
+
"TrialPeriodDays",
|
|
24
|
+
"IsActive",
|
|
25
|
+
],
|
|
26
|
+
include: [
|
|
27
|
+
{
|
|
28
|
+
model: SubscriptionFeature,
|
|
29
|
+
as: "Features",
|
|
30
|
+
attributes: ["SubscriptionFeatureID", "FeatureName", "FeatureCode"],
|
|
31
|
+
through: { attributes: ["FeatureValue"] },
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
limit,
|
|
35
|
+
offset,
|
|
36
|
+
distinct: true,
|
|
37
|
+
});
|
|
38
|
+
logger.debug("subscription plans fetched successfully");
|
|
39
|
+
return AppUtil.generateResponse(
|
|
40
|
+
200,
|
|
41
|
+
StatusMessage.SUCCESS,
|
|
42
|
+
null,
|
|
43
|
+
{ rows, count, pageNumber, limit },
|
|
44
|
+
res,
|
|
45
|
+
);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
logger.error("error occurred while fetching subscription plans", error);
|
|
48
|
+
return AppUtil.generateResponse(
|
|
49
|
+
500,
|
|
50
|
+
StatusMessage.FAILURE,
|
|
51
|
+
StatusMessage.SERVER_ERROR,
|
|
52
|
+
null,
|
|
53
|
+
res,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const getTenantSubscription = (
|
|
60
|
+
Tenant,
|
|
61
|
+
TenantSubscription,
|
|
62
|
+
SubscriptionPlan,
|
|
63
|
+
logger,
|
|
64
|
+
) => {
|
|
65
|
+
return async (req, res) => {
|
|
66
|
+
try {
|
|
67
|
+
const { id } = req.params;
|
|
68
|
+
|
|
69
|
+
const tenant = await Tenant.findOne({
|
|
70
|
+
where: { TenantID: id },
|
|
71
|
+
include: [
|
|
72
|
+
{
|
|
73
|
+
model: TenantSubscription,
|
|
74
|
+
as: "CurrentSubscription",
|
|
75
|
+
attributes: [
|
|
76
|
+
"TenantSubscriptionID",
|
|
77
|
+
"Status",
|
|
78
|
+
"StartDate",
|
|
79
|
+
"EndDate",
|
|
80
|
+
"GraceEndDate",
|
|
81
|
+
"TrialEndDate",
|
|
82
|
+
"IsTrial",
|
|
83
|
+
"AutoRenew",
|
|
84
|
+
],
|
|
85
|
+
include: [
|
|
86
|
+
{
|
|
87
|
+
model: SubscriptionPlan,
|
|
88
|
+
as: "SubscriptionPlan",
|
|
89
|
+
attributes: ["SubscriptionPlanID", "PlanName", "PlanCode"],
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (!tenant) {
|
|
97
|
+
return AppUtil.generateResponse(
|
|
98
|
+
404,
|
|
99
|
+
StatusMessage.FAILURE,
|
|
100
|
+
StatusMessage.TENANT_NOT_FOUND,
|
|
101
|
+
null,
|
|
102
|
+
res,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const { countryName, stateName } =
|
|
107
|
+
await LocationUtility.resolveCountryAndState(
|
|
108
|
+
tenant.CountryCode,
|
|
109
|
+
tenant.StateCode,
|
|
110
|
+
logger,
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const formattedTenant = {
|
|
114
|
+
TenantID: tenant.TenantID,
|
|
115
|
+
CompanyName: tenant.CompanyName,
|
|
116
|
+
CompanyCode: tenant.CompanyCode,
|
|
117
|
+
Email: tenant.Email,
|
|
118
|
+
CountryCallingCode: tenant.CountryCallingCode,
|
|
119
|
+
PhoneNumber: tenant.PhoneNumber,
|
|
120
|
+
GSTNo: tenant.GSTNo,
|
|
121
|
+
CustomerPortalDomain: tenant.CustomerPortalDomain,
|
|
122
|
+
AdminPortalDomain: tenant.AdminPortalDomain,
|
|
123
|
+
AddressLine: tenant.AddressLine,
|
|
124
|
+
CityName: tenant.CityName,
|
|
125
|
+
StateCode: tenant.StateCode,
|
|
126
|
+
StateName: stateName,
|
|
127
|
+
CountryCode: tenant.CountryCode,
|
|
128
|
+
CountryName: countryName,
|
|
129
|
+
Zipcode: tenant.Zipcode,
|
|
130
|
+
SubscriptionPlanID: tenant.CurrentSubscription?.SubscriptionPlan?.SubscriptionPlanID,
|
|
131
|
+
PlanName: tenant.CurrentSubscription?.SubscriptionPlan?.PlanName,
|
|
132
|
+
TenantSubscriptionStatus: tenant.CurrentSubscription?.Status,
|
|
133
|
+
StartDate: tenant.CurrentSubscription?.StartDate,
|
|
134
|
+
EndDate: tenant.CurrentSubscription?.EndDate,
|
|
135
|
+
GraceEndDate: tenant.CurrentSubscription?.GraceEndDate,
|
|
136
|
+
TrialEndDate: tenant.CurrentSubscription?.TrialEndDate,
|
|
137
|
+
IsTrial: tenant.CurrentSubscription?.IsTrial,
|
|
138
|
+
AutoRenew: tenant.CurrentSubscription?.AutoRenew,
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
return AppUtil.generateResponse(
|
|
142
|
+
200,
|
|
143
|
+
StatusMessage.SUCCESS,
|
|
144
|
+
null,
|
|
145
|
+
formattedTenant,
|
|
146
|
+
res,
|
|
147
|
+
);
|
|
148
|
+
} catch (error) {
|
|
149
|
+
logger.error("Error fetching tenant:", error);
|
|
150
|
+
return AppUtil.generateResponse(
|
|
151
|
+
500,
|
|
152
|
+
StatusMessage.FAILURE,
|
|
153
|
+
StatusMessage.SERVER_ERROR,
|
|
154
|
+
null,
|
|
155
|
+
res,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
module.exports = {getAllSubscriptionPlans, getTenantSubscription}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
const LocationUtility = require('../utility/LocationUtility');
|
|
2
|
+
const StatusMessage = require('../constants/StatusMessageConstants');
|
|
3
|
+
const AppUtil = require('../utility/AppUtil');
|
|
4
|
+
const SubscriptionStatusEnum = require('../enum/SubscriptionStatusEnum');
|
|
5
|
+
const AppConstants = require('../constants/AppConstants');
|
|
6
|
+
|
|
7
|
+
const updateTenant = (
|
|
8
|
+
Tenant,
|
|
9
|
+
TenantSubscription,
|
|
10
|
+
SubscriptionPlan,
|
|
11
|
+
sequelize,
|
|
12
|
+
logger,
|
|
13
|
+
) => {
|
|
14
|
+
return async (req, res) => {
|
|
15
|
+
let transaction;
|
|
16
|
+
try {
|
|
17
|
+
const tenantId =
|
|
18
|
+
req.params && req.params.TenantID
|
|
19
|
+
? req.params.TenantID
|
|
20
|
+
: req.body.TenantID;
|
|
21
|
+
if (!tenantId) {
|
|
22
|
+
logger.warn("TenantID is required for update.");
|
|
23
|
+
return AppUtil.generateResponse(
|
|
24
|
+
400,
|
|
25
|
+
StatusMessage.FAILURE,
|
|
26
|
+
StatusMessage.TENANT_ID_REQUIRED_FIELD,
|
|
27
|
+
null,
|
|
28
|
+
res,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const existing = await Tenant.findOne({ where: { TenantID: tenantId } });
|
|
33
|
+
if (!existing) {
|
|
34
|
+
logger.warn("Tenant not found with ID:", tenantId);
|
|
35
|
+
return AppUtil.generateResponse(
|
|
36
|
+
404,
|
|
37
|
+
StatusMessage.FAILURE,
|
|
38
|
+
StatusMessage.TENANT_NOT_FOUND,
|
|
39
|
+
null,
|
|
40
|
+
res,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const {
|
|
45
|
+
CompanyName,
|
|
46
|
+
CompanyCode,
|
|
47
|
+
Email,
|
|
48
|
+
PhoneNumber,
|
|
49
|
+
CountryCallingCode,
|
|
50
|
+
GSTNo,
|
|
51
|
+
CustomerPortalDomain,
|
|
52
|
+
AdminPortalDomain,
|
|
53
|
+
AddressLine,
|
|
54
|
+
CityName,
|
|
55
|
+
StateCode,
|
|
56
|
+
CountryCode,
|
|
57
|
+
Zipcode,
|
|
58
|
+
SubscriptionPlanID,
|
|
59
|
+
Status,
|
|
60
|
+
StartDate,
|
|
61
|
+
EndDate,
|
|
62
|
+
AutoRenew,
|
|
63
|
+
IsTrial,
|
|
64
|
+
GraceEndDate,
|
|
65
|
+
TrialEndDate,
|
|
66
|
+
} = req.body;
|
|
67
|
+
|
|
68
|
+
// Validate optional fields when provided
|
|
69
|
+
if (Email && !AppUtil.isValidEmail(Email)) {
|
|
70
|
+
logger.warn("Invalid email format provided for update.");
|
|
71
|
+
return AppUtil.generateResponse(
|
|
72
|
+
400,
|
|
73
|
+
StatusMessage.FAILURE,
|
|
74
|
+
StatusMessage.INVALID_EMAIL_FORMAT,
|
|
75
|
+
null,
|
|
76
|
+
res,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (PhoneNumber && !AppUtil.isValidPhone(PhoneNumber)) {
|
|
81
|
+
logger.warn("Invalid phone number format provided for update.");
|
|
82
|
+
return AppUtil.generateResponse(
|
|
83
|
+
400,
|
|
84
|
+
StatusMessage.FAILURE,
|
|
85
|
+
StatusMessage.INVALID_PHONE_FORMAT,
|
|
86
|
+
null,
|
|
87
|
+
res,
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (CompanyCode !== undefined) {
|
|
92
|
+
if (
|
|
93
|
+
!Number.isInteger(Number(CompanyCode)) ||
|
|
94
|
+
Number(CompanyCode) <= 0
|
|
95
|
+
) {
|
|
96
|
+
logger.warn("Invalid company code provided for update.");
|
|
97
|
+
return AppUtil.generateResponse(
|
|
98
|
+
400,
|
|
99
|
+
StatusMessage.FAILURE,
|
|
100
|
+
StatusMessage.INVALID_COMPANY_CODE,
|
|
101
|
+
null,
|
|
102
|
+
res,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Validate country code, state code and city name
|
|
108
|
+
if (CountryCode && StateCode && CityName && CountryCallingCode) {
|
|
109
|
+
const validation = await LocationUtility.validateCountryAndState(
|
|
110
|
+
CountryCode,
|
|
111
|
+
StateCode,
|
|
112
|
+
CityName,
|
|
113
|
+
CountryCallingCode,
|
|
114
|
+
logger,
|
|
115
|
+
);
|
|
116
|
+
if (!validation.isValid) {
|
|
117
|
+
return AppUtil.generateResponse(
|
|
118
|
+
400,
|
|
119
|
+
StatusMessage.FAILURE,
|
|
120
|
+
validation.error,
|
|
121
|
+
null,
|
|
122
|
+
res,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (Status && !Object.values(SubscriptionStatusEnum).includes(Status)) {
|
|
127
|
+
logger.warn("Invalid Subscription status");
|
|
128
|
+
return AppUtil.generateResponse(
|
|
129
|
+
400,
|
|
130
|
+
StatusMessage.FAILURE,
|
|
131
|
+
StatusMessage.INVALID_SUBSCRIPTION_STATUS,
|
|
132
|
+
null,
|
|
133
|
+
res,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (
|
|
138
|
+
AutoRenew !== undefined &&
|
|
139
|
+
typeof AutoRenew !== AppConstants.BOOLEAN
|
|
140
|
+
) {
|
|
141
|
+
logger.warn("AutoRenew must be boolean type");
|
|
142
|
+
return AppUtil.generateResponse(
|
|
143
|
+
400,
|
|
144
|
+
StatusMessage.FAILURE,
|
|
145
|
+
StatusMessage.INVALID_BOOLEAN_TYPE.replace("{field}", "AutoRenew"),
|
|
146
|
+
null,
|
|
147
|
+
res,
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
if (IsTrial !== undefined && typeof IsTrial !== AppConstants.BOOLEAN) {
|
|
151
|
+
logger.warn("IsTrial must be boolean type");
|
|
152
|
+
return AppUtil.generateResponse(
|
|
153
|
+
400,
|
|
154
|
+
StatusMessage.FAILURE,
|
|
155
|
+
StatusMessage.INVALID_BOOLEAN_TYPE.replace("{field}", "IsTrial"),
|
|
156
|
+
null,
|
|
157
|
+
res,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
transaction = await sequelize.transaction();
|
|
161
|
+
if (SubscriptionPlanID) {
|
|
162
|
+
const subscriptionPlan = await SubscriptionPlan.findOne({
|
|
163
|
+
where: {
|
|
164
|
+
SubscriptionPlanID,
|
|
165
|
+
IsActive: true,
|
|
166
|
+
},
|
|
167
|
+
transaction,
|
|
168
|
+
});
|
|
169
|
+
if (!subscriptionPlan) {
|
|
170
|
+
await transaction.rollback();
|
|
171
|
+
logger.warn("subscription plan not found");
|
|
172
|
+
return AppUtil.generateResponse(
|
|
173
|
+
404,
|
|
174
|
+
StatusMessage.FAILURE,
|
|
175
|
+
StatusMessage.SUBSCRIPTION_PLAN_NOT_FOUND,
|
|
176
|
+
null,
|
|
177
|
+
res,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Build update payload only with provided fields
|
|
182
|
+
const updatePayload = {};
|
|
183
|
+
const fields = {
|
|
184
|
+
CompanyName,
|
|
185
|
+
CompanyCode,
|
|
186
|
+
Email,
|
|
187
|
+
PhoneNumber,
|
|
188
|
+
CountryCode,
|
|
189
|
+
GSTNo,
|
|
190
|
+
CustomerPortalDomain,
|
|
191
|
+
AdminPortalDomain,
|
|
192
|
+
AddressLine,
|
|
193
|
+
CityName,
|
|
194
|
+
StateCode,
|
|
195
|
+
CountryCallingCode,
|
|
196
|
+
Zipcode,
|
|
197
|
+
};
|
|
198
|
+
Object.keys(fields).forEach((k) => {
|
|
199
|
+
if (fields[k] !== undefined)
|
|
200
|
+
updatePayload[k] =
|
|
201
|
+
k === AppConstants.COMPANY_CODE ? Number(fields[k]) : fields[k];
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
updatePayload.UpdatedBy =
|
|
205
|
+
AppConstants.UPDATED_BY || AppConstants.CREATED_BY;
|
|
206
|
+
updatePayload.UpdatedAt = new Date();
|
|
207
|
+
|
|
208
|
+
await existing.update(updatePayload, { transaction });
|
|
209
|
+
|
|
210
|
+
// update subscription
|
|
211
|
+
const updateSubscriptionPayload = {};
|
|
212
|
+
const updateSubscriptionfields = {
|
|
213
|
+
SubscriptionPlanID,
|
|
214
|
+
Status,
|
|
215
|
+
StartDate,
|
|
216
|
+
EndDate,
|
|
217
|
+
GraceEndDate,
|
|
218
|
+
TrialEndDate,
|
|
219
|
+
IsTrial,
|
|
220
|
+
AutoRenew,
|
|
221
|
+
};
|
|
222
|
+
Object.keys(updateSubscriptionfields).forEach((k) => {
|
|
223
|
+
if (updateSubscriptionfields[k] !== undefined)
|
|
224
|
+
updateSubscriptionPayload[k] = updateSubscriptionfields[k];
|
|
225
|
+
});
|
|
226
|
+
if (Object.keys(updateSubscriptionPayload).length !== 0) {
|
|
227
|
+
updateSubscriptionPayload.UpdatedBy = AppConstants.CREATED_BY;
|
|
228
|
+
updateSubscriptionPayload.UpdatedAt = new Date();
|
|
229
|
+
|
|
230
|
+
// find the existing subscription
|
|
231
|
+
const tenantSubscription = await TenantSubscription.findOne({
|
|
232
|
+
where: {
|
|
233
|
+
TenantID: tenantId,
|
|
234
|
+
},
|
|
235
|
+
transaction,
|
|
236
|
+
});
|
|
237
|
+
if (tenantSubscription) {
|
|
238
|
+
await tenantSubscription.update(updateSubscriptionPayload, {
|
|
239
|
+
transaction,
|
|
240
|
+
});
|
|
241
|
+
} else {
|
|
242
|
+
await TenantSubscription.create(
|
|
243
|
+
{
|
|
244
|
+
TenantID: tenantId,
|
|
245
|
+
...updateSubscriptionPayload,
|
|
246
|
+
CreatedBy: AppConstants.CREATED_BY,
|
|
247
|
+
CreatedAt: new Date(),
|
|
248
|
+
},
|
|
249
|
+
{ transaction },
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
await transaction.commit();
|
|
254
|
+
|
|
255
|
+
logger.info("Tenant updated successfully with ID:", tenantId);
|
|
256
|
+
return AppUtil.generateResponse(
|
|
257
|
+
200,
|
|
258
|
+
StatusMessage.SUCCESS,
|
|
259
|
+
StatusMessage.TENANT_UPDATED_SUCCESS,
|
|
260
|
+
null,
|
|
261
|
+
res,
|
|
262
|
+
);
|
|
263
|
+
} catch (error) {
|
|
264
|
+
if (transaction) await transaction.rollback();
|
|
265
|
+
|
|
266
|
+
if (error.name === "SequelizeUniqueConstraintError") {
|
|
267
|
+
const detail = error.original?.detail || "";
|
|
268
|
+
if (detail.includes(AppConstants.COMPANY_NAME)) {
|
|
269
|
+
return AppUtil.generateResponse(
|
|
270
|
+
400,
|
|
271
|
+
StatusMessage.FAILURE,
|
|
272
|
+
StatusMessage.COMPANY_NAME_EXISTS,
|
|
273
|
+
null,
|
|
274
|
+
res,
|
|
275
|
+
);
|
|
276
|
+
} else if (detail.includes(AppConstants.COMPANY_CODE)) {
|
|
277
|
+
return AppUtil.generateResponse(
|
|
278
|
+
400,
|
|
279
|
+
StatusMessage.FAILURE,
|
|
280
|
+
StatusMessage.COMPANY_CODE_EXISTS,
|
|
281
|
+
null,
|
|
282
|
+
res,
|
|
283
|
+
);
|
|
284
|
+
} else if (detail.includes(AppConstants.EMAIL)) {
|
|
285
|
+
return AppUtil.generateResponse(
|
|
286
|
+
400,
|
|
287
|
+
StatusMessage.FAILURE,
|
|
288
|
+
StatusMessage.EMAIL_EXISTS,
|
|
289
|
+
null,
|
|
290
|
+
res,
|
|
291
|
+
);
|
|
292
|
+
} else if (detail.includes(AppConstants.PHONE_NUMBER)) {
|
|
293
|
+
return AppUtil.generateResponse(
|
|
294
|
+
400,
|
|
295
|
+
StatusMessage.FAILURE,
|
|
296
|
+
StatusMessage.PHONE_NUMBER_EXISTS,
|
|
297
|
+
null,
|
|
298
|
+
res,
|
|
299
|
+
);
|
|
300
|
+
} else if (detail.includes(AppConstants.CUSTOMER_PORTAL_DOMAIN)) {
|
|
301
|
+
return AppUtil.generateResponse(
|
|
302
|
+
400,
|
|
303
|
+
StatusMessage.FAILURE,
|
|
304
|
+
StatusMessage.CUSTOMER_PORTAL_DOMAIN_EXISTS,
|
|
305
|
+
null,
|
|
306
|
+
res,
|
|
307
|
+
);
|
|
308
|
+
} else if (detail.includes(AppConstants.ADMIN_PORTAL_DOMAIN)) {
|
|
309
|
+
return AppUtil.generateResponse(
|
|
310
|
+
400,
|
|
311
|
+
StatusMessage.FAILURE,
|
|
312
|
+
StatusMessage.ADMIN_PORTAL_DOMAIN_EXISTS,
|
|
313
|
+
null,
|
|
314
|
+
res,
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
return AppUtil.generateResponse(
|
|
318
|
+
400,
|
|
319
|
+
StatusMessage.FAILURE,
|
|
320
|
+
StatusMessage.TENANT_ALREADY_EXISTS,
|
|
321
|
+
null,
|
|
322
|
+
res,
|
|
323
|
+
);
|
|
324
|
+
} else if (error.name === "SequelizeValidationError") {
|
|
325
|
+
const details = error.errors.map((e) => e.message);
|
|
326
|
+
logger.warn(`Validation Error detected: ${details.join("; ")}`);
|
|
327
|
+
return AppUtil.generateResponse(
|
|
328
|
+
400,
|
|
329
|
+
StatusMessage.FAILURE,
|
|
330
|
+
StatusMessage.INVALID_REQUEST,
|
|
331
|
+
null,
|
|
332
|
+
res,
|
|
333
|
+
);
|
|
334
|
+
} else {
|
|
335
|
+
logger.error("Error in UpdateTenant:", error);
|
|
336
|
+
return AppUtil.generateResponse(
|
|
337
|
+
500,
|
|
338
|
+
StatusMessage.FAILURE,
|
|
339
|
+
StatusMessage.TENANT_UPDATE_ERROR,
|
|
340
|
+
null,
|
|
341
|
+
res,
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
module.exports = { updateTenant };
|
|
349
|
+
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const EntityTypeEnum = require('../enum/EntityTypeEnum');
|
|
2
|
+
const StatusMessage = require('../constants/StatusMessageConstants');
|
|
3
|
+
const AppUtil = require('../utility/AppUtil');
|
|
4
|
+
|
|
5
|
+
const getTenantSettingsById = (TenantSettings, Document, getPublicUrl, logger) => {
|
|
6
|
+
return async (req, res) => {
|
|
7
|
+
try {
|
|
8
|
+
const { id } = req.params;
|
|
9
|
+
|
|
10
|
+
const settings = await TenantSettings.findOne({
|
|
11
|
+
where: {
|
|
12
|
+
TenantID: id
|
|
13
|
+
},
|
|
14
|
+
attributes: ["TenantSettingID", "TenantID", "ThemeColour"],
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
if (!settings) {
|
|
18
|
+
return AppUtil.generateResponse(
|
|
19
|
+
404,
|
|
20
|
+
StatusMessage.FAILURE,
|
|
21
|
+
StatusMessage.TENANT_SETTINGS_NOT_FOUND,
|
|
22
|
+
null,
|
|
23
|
+
res
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const documents = await Document.findAll({
|
|
28
|
+
where: {
|
|
29
|
+
EntityType: EntityTypeEnum.TENANT_SETTINGS,
|
|
30
|
+
EntityID: settings.TenantSettingID
|
|
31
|
+
},
|
|
32
|
+
order: [["SortOrder", "ASC"]]
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const logo = await Promise.all(
|
|
36
|
+
documents.map(async (doc) => ({
|
|
37
|
+
documentId: doc.DocumentID,
|
|
38
|
+
sortOrder: doc.SortOrder,
|
|
39
|
+
documentUrl: await getPublicUrl(doc, logger)
|
|
40
|
+
}))
|
|
41
|
+
);
|
|
42
|
+
const formattedSettings = {
|
|
43
|
+
TenantSettingID: settings.TenantSettingID,
|
|
44
|
+
TenantID: settings.TenantID,
|
|
45
|
+
ThemeColour: settings.ThemeColour,
|
|
46
|
+
Logo: logo
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return AppUtil.generateResponse(
|
|
50
|
+
200,
|
|
51
|
+
StatusMessage.SUCCESS,
|
|
52
|
+
null,
|
|
53
|
+
formattedSettings,
|
|
54
|
+
res
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
} catch (error) {
|
|
58
|
+
logger.error("Error fetching tenant settings:", error);
|
|
59
|
+
return AppUtil.generateResponse(
|
|
60
|
+
500,
|
|
61
|
+
StatusMessage.FAILURE,
|
|
62
|
+
StatusMessage.SERVER_ERROR,
|
|
63
|
+
null,
|
|
64
|
+
res
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}}
|
|
68
|
+
|
|
69
|
+
module.exports = {getTenantSettingsById};
|
|
70
|
+
|
package/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const initializeModels = require('./dbconnection/Connect');
|
|
4
|
-
|
|
4
|
+
const SubscriptionAbstractController = require('./controller/SubscriptionAbstractController');
|
|
5
|
+
const TenantAbstractController = require('./controller/TenantAbstractController');
|
|
6
|
+
const TenantSettingsAbstractController = require('./controller/TenantSettingsAbstractController');
|
|
7
|
+
const LocationController = require('./controller/LocationController');
|
|
5
8
|
const enums = {};
|
|
6
9
|
const enumDir = path.join(__dirname, 'enum');
|
|
7
10
|
fs.readdirSync(enumDir).forEach((file) => {
|
|
@@ -19,4 +22,4 @@ fs.readdirSync(utilDir).forEach((file) => {
|
|
|
19
22
|
}
|
|
20
23
|
})
|
|
21
24
|
|
|
22
|
-
module.exports = {initializeModels, enums, utils}
|
|
25
|
+
module.exports = {initializeModels, enums, utils, SubscriptionAbstractController, TenantAbstractController, TenantSettingsAbstractController, LocationController}
|