@sommpicks/sommpicks-shopify 24.12.0
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/Logger.ts +18 -0
- package/README.md +258 -0
- package/addTypings.sh +2 -0
- package/bitbucket-pipelines.yml +38 -0
- package/index.ts +132 -0
- package/package.json +57 -0
- package/publish.sh +20 -0
- package/services/CacheWrapper.ts +30 -0
- package/services/CountryCodeService.ts +507 -0
- package/shopify/ShopifyAppService.ts +109 -0
- package/shopify/ShopifyAssetService.ts +20 -0
- package/shopify/ShopifyBillingService.ts +73 -0
- package/shopify/ShopifyCartTrasnformationService.ts +207 -0
- package/shopify/ShopifyCollectionService.ts +523 -0
- package/shopify/ShopifyCustomerService.ts +472 -0
- package/shopify/ShopifyDeliveryCustomisationService.ts +220 -0
- package/shopify/ShopifyDiscountService.ts +131 -0
- package/shopify/ShopifyDraftOrderService.ts +125 -0
- package/shopify/ShopifyFulfillmentService.ts +41 -0
- package/shopify/ShopifyFunctionsProductDiscountsService.ts +166 -0
- package/shopify/ShopifyInventoryService.ts +415 -0
- package/shopify/ShopifyLocationService.ts +29 -0
- package/shopify/ShopifyOrderRefundsService.ts +138 -0
- package/shopify/ShopifyOrderRiskService.ts +19 -0
- package/shopify/ShopifyOrderService.ts +1143 -0
- package/shopify/ShopifyPageService.ts +62 -0
- package/shopify/ShopifyProductService.ts +772 -0
- package/shopify/ShopifyShippingZonesService.ts +37 -0
- package/shopify/ShopifyShopService.ts +101 -0
- package/shopify/ShopifyTemplateService.ts +30 -0
- package/shopify/ShopifyThemeService.ts +33 -0
- package/shopify/ShopifyUtils.ts +56 -0
- package/shopify/ShopifyWebhookService.ts +110 -0
- package/shopify/base/APIVersion.ts +4 -0
- package/shopify/base/AbstractService.ts +152 -0
- package/shopify/base/ErrorHelper.ts +24 -0
- package/shopify/errors/InspiraShopifyCustomError.ts +7 -0
- package/shopify/errors/InspiraShopifyError.ts +15 -0
- package/shopify/errors/InspiraShopifyUnableToReserveInventoryError.ts +7 -0
- package/shopify/helpers/ShopifyProductServiceHelper.ts +450 -0
- package/shopify/product/ShopifyProductCountService.ts +110 -0
- package/shopify/product/ShopifyProductListService.ts +333 -0
- package/shopify/product/ShopifyProductMetafieldsService.ts +405 -0
- package/shopify/product/ShopifyProductPublicationsService.ts +112 -0
- package/shopify/product/ShopifyVariantService.ts +584 -0
- package/shopify/router/ShopifyMandatoryRouter.ts +37 -0
- package/shopify/router/ShopifyRouter.ts +85 -0
- package/shopify/router/ShopifyRouterBis.ts +85 -0
- package/shopify/router/ShopifyRouterBisBis.ts +85 -0
- package/shopify/router/ShopifyRouterBisBisBis.ts +85 -0
- package/shopify/router/ShopifyRouterBisBisBisBis.ts +85 -0
- package/shopify/router/WebhookSkipMiddleware.ts +73 -0
- package/shopify/router/services/CryptoService.ts +26 -0
- package/shopify/router/services/HmacValidator.ts +36 -0
- package/shopify/router/services/OauthService.ts +17 -0
- package/shopify/router/services/RestUtils.ts +13 -0
- package/shopify/router/services/rateLimiter/MemoryStores.ts +46 -0
- package/shopify/router/services/rateLimiter/StoreRateLimiter.ts +46 -0
- package/test/README.md +223 -0
- package/test/router/ShopifyRouter.test.ts +71 -0
- package/test/router/WebhookSkipMiddleware.test.ts +86 -0
- package/test/router/services/HmacValidator.test.ts +24 -0
- package/test/router/services/RestUtils.test.ts +13 -0
- package/test/router/services/rateLimiter/StoreRateLimiter.test.ts +62 -0
- package/test/services/CacheWrapper.test.ts +30 -0
- package/test/shopify/ShopifyOrderService.test.ts +29 -0
- package/test/shopify/ShopifyProductService.test.ts +118 -0
- package/test/shopify/ShopifyWebhookService.test.ts +105 -0
- package/tsconfig.json +10 -0
- package/typings/axios.d.ts +8 -0
- package/typings/index.d.ts +1682 -0
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
import { Logger } from '../Logger';
|
|
2
|
+
import { AxiosInstance } from 'axios';
|
|
3
|
+
import ErrorHelper from './base/ErrorHelper';
|
|
4
|
+
import InspiraShopifyError from './errors/InspiraShopifyError';
|
|
5
|
+
import moment = require('moment');
|
|
6
|
+
import { AbstractService } from './base/AbstractService';
|
|
7
|
+
|
|
8
|
+
export class ShopifyCustomerService extends AbstractService {
|
|
9
|
+
|
|
10
|
+
constructor(private axiosInstance: AxiosInstance) { super(); }
|
|
11
|
+
|
|
12
|
+
public getById = async (customerId: number): Promise<ICustomer> => {
|
|
13
|
+
return new Promise<ICustomer>(async (resolve, reject) => {
|
|
14
|
+
try {
|
|
15
|
+
Logger.info(`Get customer By Id ${customerId}`);
|
|
16
|
+
const response = await this.axiosInstance.get(`/customers/${customerId}.json`);
|
|
17
|
+
Logger.info('Customer found', response.data.customer);
|
|
18
|
+
resolve(response.data.customer);
|
|
19
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
public getByEmail = async (email: string): Promise<ICustomer[]> => {
|
|
24
|
+
return new Promise<ICustomer[]>(async (resolve, reject) => {
|
|
25
|
+
try {
|
|
26
|
+
Logger.info(`Get customers By Email ${email}`);
|
|
27
|
+
const response = await this.axiosInstance.get(`/customers/search.json?query=email:${email}`);
|
|
28
|
+
Logger.info('Customers found', response.data.customers);
|
|
29
|
+
resolve(response.data.customers);
|
|
30
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
*
|
|
37
|
+
* Searches using /customers/search.json?query= and returns the customers that has the tag doing a filter on the endpoint results.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} tag to search for.
|
|
40
|
+
* @returns Promise
|
|
41
|
+
*/
|
|
42
|
+
public getByTag = async (tag: string): Promise<ICustomer[]> => {
|
|
43
|
+
return new Promise<ICustomer[]>(async (resolve, reject) => {
|
|
44
|
+
try {
|
|
45
|
+
Logger.info(`Get customers By Tag ${tag}`);
|
|
46
|
+
const response = await this.axiosInstance.get(`/customers/search.json?query=${tag.trim()}`);
|
|
47
|
+
const customers = response.data.customers;
|
|
48
|
+
Logger.info('Initial Customers found', response.data.customers);
|
|
49
|
+
const foundCustomers: ICustomer[] = [];
|
|
50
|
+
for (const customer of customers) {
|
|
51
|
+
if (customer.tags && (customer.tags as string).trim().toLowerCase().indexOf(tag.trim().toLowerCase()) > -1) {
|
|
52
|
+
foundCustomers.push(customer);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
Logger.info('Customers found', response.data.customers);
|
|
56
|
+
resolve(foundCustomers);
|
|
57
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
*
|
|
63
|
+
* Searches using /customers/search.json?query= and returns the customers that contains the string in the last name field.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} text to search for.
|
|
66
|
+
* @returns Promise
|
|
67
|
+
*/
|
|
68
|
+
public getByLastNameContains = async (text: string): Promise<ICustomer[]> => {
|
|
69
|
+
return new Promise<ICustomer[]>(async (resolve, reject) => {
|
|
70
|
+
try {
|
|
71
|
+
Logger.info(`Get customers By Last Name ${text}`);
|
|
72
|
+
const response = await this.axiosInstance.get(`/customers/search.json?query=${text.trim()}`);
|
|
73
|
+
const customers: ICustomer[] = response.data.customers;
|
|
74
|
+
Logger.info('Initial Customers found', response.data.customers);
|
|
75
|
+
const foundCustomers: ICustomer[] = [];
|
|
76
|
+
for (const customer of customers) {
|
|
77
|
+
if (customer.last_name && customer.last_name.trim().toLowerCase().indexOf(text.trim().toLowerCase()) > -1) {
|
|
78
|
+
foundCustomers.push(customer);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
Logger.info('Customers found', response.data.customers);
|
|
82
|
+
resolve(foundCustomers);
|
|
83
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
public create = async (customer: ICustomer): Promise<ICustomer> => {
|
|
88
|
+
return new Promise<ICustomer>(async (resolve, reject) => {
|
|
89
|
+
try {
|
|
90
|
+
Logger.info('Create customers', customer);
|
|
91
|
+
const response = await this.axiosInstance.post('/customers.json', { customer: customer });
|
|
92
|
+
resolve(response.data.customer);
|
|
93
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
*
|
|
99
|
+
* @param custormerId Customer Id in shopify
|
|
100
|
+
* @param {ICustomer} customer add fields that need to be updated. Id field is required
|
|
101
|
+
* @returns
|
|
102
|
+
*/
|
|
103
|
+
public update = async (custormerId: number, customer: ICustomer): Promise<ICustomer> => {
|
|
104
|
+
return new Promise<ICustomer>(async (resolve, reject) => {
|
|
105
|
+
try {
|
|
106
|
+
Logger.info(`Update customers ${custormerId}`, customer);
|
|
107
|
+
const response = await this.axiosInstance.put(`/customers/${custormerId}.json`, { customer: customer });
|
|
108
|
+
resolve(response.data.customer);
|
|
109
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
*
|
|
115
|
+
* Adds one or more tags to a customer. It does add them toghether with the existing ones.
|
|
116
|
+
*
|
|
117
|
+
* @param {number} customerId customer id number
|
|
118
|
+
* @param {tags: string; id: number;} customer customer to apply change to. Just tags and id fields
|
|
119
|
+
* @param {string[]} tags tags to add
|
|
120
|
+
* @returns Promise
|
|
121
|
+
*/
|
|
122
|
+
public addTags = async (customerId: number, customer: { tags: string; id: number; }, tags: string[]): Promise<ICustomer> => {
|
|
123
|
+
return new Promise<ICustomer>(async (resolve, reject) => {
|
|
124
|
+
try {
|
|
125
|
+
if(customerId !== customer.id) {
|
|
126
|
+
throw new Error(`Trying to add tags to the wrong customer - ${customerId} vs ${customer.id}`);
|
|
127
|
+
}
|
|
128
|
+
Logger.info(`Added tags of (${tags.join(',')}) to customer with id of ${customerId}`);
|
|
129
|
+
customer.tags = [...new Set([...customer.tags.split(','), ...tags])].join();
|
|
130
|
+
const responsedCustomer: ICustomer = await this.update(customerId, customer as any);
|
|
131
|
+
resolve(responsedCustomer);
|
|
132
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
*
|
|
138
|
+
* Removes one or more tags to a customer
|
|
139
|
+
*
|
|
140
|
+
* @param {number} customerId customer id number
|
|
141
|
+
* @param {tags: string; id: number;} customer customer to apply change to. Just tags and id fields
|
|
142
|
+
* @param {string[]} tags tags to remove
|
|
143
|
+
* @returns Promise
|
|
144
|
+
*/
|
|
145
|
+
public removeTags = async (customerId: number, customer: { tags: string; id: number; }, tags: string[]): Promise<ICustomer> => {
|
|
146
|
+
return new Promise<ICustomer>(async (resolve, reject) => {
|
|
147
|
+
try {
|
|
148
|
+
if(customerId !== customer.id) {
|
|
149
|
+
throw new Error(`Trying to remove tags to the wrong customer - ${customerId} vs ${customer.id}`);
|
|
150
|
+
}
|
|
151
|
+
Logger.info(`Removing tags of (${tags.join(',')}) to customer with id of ${customerId}`);
|
|
152
|
+
customer.tags = (customer.tags).split(',').filter(function (x) {
|
|
153
|
+
return tags.indexOf(x.trim()) < 0;
|
|
154
|
+
}).join(',');
|
|
155
|
+
const responsedCustomer: ICustomer = await this.update(customerId, customer as any);
|
|
156
|
+
resolve(responsedCustomer);
|
|
157
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
158
|
+
});
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
public getInBatch = async (sinceId: number): Promise<ICustomerBatch> => {
|
|
162
|
+
return new Promise<ICustomerBatch>(async (resolve, reject) => {
|
|
163
|
+
try {
|
|
164
|
+
Logger.info(`Getting customer since id ${sinceId}`);
|
|
165
|
+
const response = await this.axiosInstance.get('/customers/count.json');
|
|
166
|
+
const count = response.data.count;
|
|
167
|
+
const batches = parseInt(((count / 250) + 1).toString());
|
|
168
|
+
const customerBatch: ICustomerBatch = { batches: batches, customers: [], nextSinceId: 0 };
|
|
169
|
+
const customersGetURL = `/customers.json?limit=250&since_id=${sinceId}`;
|
|
170
|
+
const customersRetrieved = await this.axiosInstance.get(customersGetURL);
|
|
171
|
+
customerBatch.customers = customersRetrieved.data.customers;
|
|
172
|
+
if (customerBatch.customers && customerBatch.customers.length > 249) {
|
|
173
|
+
customerBatch.nextSinceId = customerBatch.customers[customerBatch.customers.length - 1].id;
|
|
174
|
+
} else {
|
|
175
|
+
customerBatch.nextSinceId = null;
|
|
176
|
+
}
|
|
177
|
+
resolve(customerBatch);
|
|
178
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
public getCustomerEmails = async (ids: number[]): Promise<{ email: string; id: number; }[]> => {
|
|
183
|
+
return new Promise<{ email: string; id: number; }[]>(async (resolve, reject) => {
|
|
184
|
+
try {
|
|
185
|
+
let emails: { email: string; id: number; }[] = [];
|
|
186
|
+
const idsChunks: number[][] = this.sliceIntoChunks(ids, 250);
|
|
187
|
+
|
|
188
|
+
Logger.info(`Getting customer emails in ${idsChunks.length} chunks of 250`);
|
|
189
|
+
|
|
190
|
+
for (const idsChunk of idsChunks) {
|
|
191
|
+
const customersGetURL = `/customers.json?ids=${idsChunk.join(',')}&limit=250&fields=id, email`;
|
|
192
|
+
Logger.info(`idsChunk ... ${customersGetURL}`);
|
|
193
|
+
const customersRetrieved = await this.axiosInstance.get(customersGetURL);
|
|
194
|
+
if(customersRetrieved.data?.customers && customersRetrieved.data.customers.length > 0) {
|
|
195
|
+
Logger.info(`idsChunk - customersRetrieved ... ${JSON.stringify(customersRetrieved.data)}`);
|
|
196
|
+
emails = emails.concat(customersRetrieved.data.customers);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
resolve(emails);
|
|
200
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
*
|
|
206
|
+
* @param {number} num? Optional if you want to get a certain amount of products. Leave blank to get all.
|
|
207
|
+
* @returns Promise
|
|
208
|
+
*/
|
|
209
|
+
public getAll = async (num?: number): Promise<ICustomer[]> => {
|
|
210
|
+
return new Promise<ICustomer[]>(async (resolve, reject) => {
|
|
211
|
+
try {
|
|
212
|
+
Logger.info('getting customers');
|
|
213
|
+
let customers: ICustomer[] = [];
|
|
214
|
+
const response = await this.axiosInstance.get('/customers/count.json');
|
|
215
|
+
const count = response.data.count > num && num !== undefined ? num : response.data.count;
|
|
216
|
+
while (customers.length < count) {
|
|
217
|
+
let customerGetURL = '/customers.json?limit=100&since_id=';
|
|
218
|
+
if (customers.length > 1) {
|
|
219
|
+
customerGetURL += customers[customers.length - 1].id;
|
|
220
|
+
} else {
|
|
221
|
+
customerGetURL += '0';
|
|
222
|
+
}
|
|
223
|
+
const customersRetrieved = await this.axiosInstance.get(customerGetURL);
|
|
224
|
+
customers = customers.concat(customersRetrieved.data.customers);
|
|
225
|
+
if (!customersRetrieved.data.customers || customersRetrieved.data.customers.length < 100) {
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
resolve(customers.slice(0, count));
|
|
230
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
231
|
+
});
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Adds an address to a customer.
|
|
236
|
+
*
|
|
237
|
+
* @param {number} customerId - Customer Id
|
|
238
|
+
* @param {IAddress} address
|
|
239
|
+
* @returns Promise
|
|
240
|
+
*/
|
|
241
|
+
public addAddress = async (customerId: number, address: IAddress): Promise<IAddress> => {
|
|
242
|
+
return new Promise<IAddress>(async (resolve, reject) => {
|
|
243
|
+
try {
|
|
244
|
+
Logger.info(`Adding a address to customer ${customerId}`, address);
|
|
245
|
+
const response = await this.axiosInstance.post(`/customers/${customerId}/addresses.json`, { address: address });
|
|
246
|
+
resolve(response.data.customer_address);
|
|
247
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
248
|
+
});
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Adds an address to a customer as its default.
|
|
253
|
+
*
|
|
254
|
+
* @param {number} customerId - Cusotmer Id
|
|
255
|
+
* @param {IAddress} address
|
|
256
|
+
* @returns Promise
|
|
257
|
+
*/
|
|
258
|
+
public addAddressAsDefault = async (customerId: number, address: IAddress): Promise<IAddress> => {
|
|
259
|
+
return new Promise<IAddress>(async (resolve, reject) => {
|
|
260
|
+
try {
|
|
261
|
+
let addressCreated = await this.addAddress(customerId, address);
|
|
262
|
+
addressCreated = await this.addressAsDefault(customerId, addressCreated.id);
|
|
263
|
+
resolve(addressCreated);
|
|
264
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
265
|
+
});
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Replaces the default address of a customer for the address provided.
|
|
270
|
+
*
|
|
271
|
+
* @param {number} customerId - Customer Id
|
|
272
|
+
* @param {IAddress} address
|
|
273
|
+
* @returns Promise
|
|
274
|
+
*/
|
|
275
|
+
public replacesAddressAsDefault = async (customerId: number, address: IAddress): Promise<IAddress> => {
|
|
276
|
+
return new Promise<IAddress>(async (resolve, reject) => {
|
|
277
|
+
try {
|
|
278
|
+
const customer = await this.getById(customerId);
|
|
279
|
+
const defaultAddressId = customer.default_address ? customer.default_address.id : null;
|
|
280
|
+
let addressCreated = await this.addAddress(customerId, address);
|
|
281
|
+
addressCreated = await this.addressAsDefault(customerId, addressCreated.id);
|
|
282
|
+
if (defaultAddressId) {
|
|
283
|
+
await this.removeAddress(customerId, defaultAddressId);
|
|
284
|
+
} else {
|
|
285
|
+
Logger.info('There wasn\'t a default address');
|
|
286
|
+
}
|
|
287
|
+
resolve(addressCreated);
|
|
288
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
289
|
+
});
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Converts an address of a customer to its default.
|
|
294
|
+
*
|
|
295
|
+
* @param {number} customerId - Customer Id
|
|
296
|
+
* @param {IAddress} addressId
|
|
297
|
+
* @returns Promise
|
|
298
|
+
*/
|
|
299
|
+
public addressAsDefault = async (customerId: number, addressId: number): Promise<IAddress> => {
|
|
300
|
+
return new Promise<IAddress>(async (resolve, reject) => {
|
|
301
|
+
try {
|
|
302
|
+
Logger.info(`Address ${addressId} of customer ${customerId} as default`);
|
|
303
|
+
const response = await this.axiosInstance.put(`/customers/${customerId}/addresses/${addressId}/default.json`, {});
|
|
304
|
+
resolve(response.data.customer_address);
|
|
305
|
+
} catch (error) { Logger.error('Error setting address as default', error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
306
|
+
});
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Updates an address to a customer.
|
|
311
|
+
*
|
|
312
|
+
* @param {number} id - Cusotmer Id
|
|
313
|
+
* @param {IAddress} address with id field in
|
|
314
|
+
* @returns Promise
|
|
315
|
+
*/
|
|
316
|
+
public updateAddress = async (id: number, address: IAddress): Promise<IAddress> => {
|
|
317
|
+
return new Promise<IAddress>(async (resolve, reject) => {
|
|
318
|
+
try {
|
|
319
|
+
Logger.info(`Updating address ${address.id} to customer ${id}`, address);
|
|
320
|
+
const response = await this.axiosInstance.put(`/customers/${id}/addresses/${address.id}.json`, { address: address });
|
|
321
|
+
resolve(response.data.customer_address);
|
|
322
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
323
|
+
});
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Removes an address to a customer.
|
|
328
|
+
*
|
|
329
|
+
* @param {number} customerId - Customer Id
|
|
330
|
+
* @param {number} addressId
|
|
331
|
+
* @returns Promise
|
|
332
|
+
*/
|
|
333
|
+
public removeAddress = async (customerId: number, addressId: number): Promise<void> => {
|
|
334
|
+
return new Promise<void>(async (resolve, reject) => {
|
|
335
|
+
try {
|
|
336
|
+
Logger.info(`Removing address ${addressId} for customer ${customerId}`);
|
|
337
|
+
await this.axiosInstance.delete(`/customers/${customerId}/addresses/${addressId}.json`);
|
|
338
|
+
resolve();
|
|
339
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
340
|
+
});
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Gets all metafields for a customer or empty array.
|
|
345
|
+
*
|
|
346
|
+
* @param {number} id - Cusotmer Id
|
|
347
|
+
* @returns Promise
|
|
348
|
+
*/
|
|
349
|
+
public getMetafields = async (id: number): Promise<IMetafield[]> => {
|
|
350
|
+
return new Promise<IMetafield[]>(async (resolve, reject) => {
|
|
351
|
+
try {
|
|
352
|
+
Logger.info(`Getting metafields for customer id -> ${id}`);
|
|
353
|
+
const response = await this.axiosInstance.get(`/customers/${id}/metafields.json`);
|
|
354
|
+
resolve(response.data.metafields);
|
|
355
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
356
|
+
});
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Count customers.
|
|
361
|
+
*
|
|
362
|
+
* @param {number} daysAgo - All customers created since that date.
|
|
363
|
+
* @returns Promise
|
|
364
|
+
*/
|
|
365
|
+
public count = async (daysAgo: number): Promise<number> => {
|
|
366
|
+
return new Promise<number>(async (resolve, reject) => {
|
|
367
|
+
try {
|
|
368
|
+
Logger.info(`Count customers created after ${daysAgo} days ago`);
|
|
369
|
+
const response = await this.axiosInstance.get(`/customers/count.json?created_at_min=${moment().subtract(daysAgo, 'days').format()}`);
|
|
370
|
+
resolve(response.data.count);
|
|
371
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
372
|
+
});
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Gets one concrete metafield for a customer or null if it does not exists.
|
|
377
|
+
*
|
|
378
|
+
* @param {number} id - Cusotmer Id
|
|
379
|
+
* @param {string} namespace
|
|
380
|
+
* @param {string} key
|
|
381
|
+
* @returns Promise
|
|
382
|
+
*/
|
|
383
|
+
public getMetafield = async (id: number, namespace: string, key: string): Promise<IMetafield> => {
|
|
384
|
+
return new Promise<IMetafield>(async (resolve, reject) => {
|
|
385
|
+
try {
|
|
386
|
+
Logger.info(`Getting metafield for customer id -> ${id} and namespace ${namespace} and key ${key}`);
|
|
387
|
+
const metafields = await this.getMetafields(id);
|
|
388
|
+
let foundMetafield: IMetafield = null;
|
|
389
|
+
if (metafields && metafields.length > 0) {
|
|
390
|
+
foundMetafield = metafields.find(m => m.namespace === namespace && m.key === key);
|
|
391
|
+
}
|
|
392
|
+
resolve(foundMetafield);
|
|
393
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
394
|
+
});
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Sends invite to a customer.
|
|
399
|
+
*
|
|
400
|
+
* @param {number} customerId
|
|
401
|
+
* @returns Promise
|
|
402
|
+
*/
|
|
403
|
+
public sendInvite = async (customerId: number): Promise<void> => {
|
|
404
|
+
return new Promise<void>(async (resolve, reject) => {
|
|
405
|
+
try {
|
|
406
|
+
Logger.info(`Send invite to customer -> ${customerId}`);
|
|
407
|
+
await this.axiosInstance.post(`/customers/${customerId}/send_invite.json`);
|
|
408
|
+
resolve();
|
|
409
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
410
|
+
});
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Creates a metafield for a customer and return the created metafield.
|
|
415
|
+
*
|
|
416
|
+
* @param {number} id
|
|
417
|
+
* @param {IMetafield} metafield
|
|
418
|
+
* @returns Promise
|
|
419
|
+
*/
|
|
420
|
+
public postMetafield = async (id: number, metafield: IMetafield): Promise<IMetafield> => {
|
|
421
|
+
return new Promise<IMetafield>(async (resolve, reject) => {
|
|
422
|
+
try {
|
|
423
|
+
Logger.info(`Posting metafield for customer id -> ${id}`);
|
|
424
|
+
const response = await this.axiosInstance.post(`/customers/${id}/metafields.json`, { metafield: metafield });
|
|
425
|
+
resolve(response.data.metafield);
|
|
426
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
427
|
+
});
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Updates a metafield for a customer and return the updated metafield. <br>
|
|
432
|
+
* The functionality first retrieves the customer metafield to get the ID and then updates it.
|
|
433
|
+
*
|
|
434
|
+
* @param {number} customerId
|
|
435
|
+
* @param {IMetafield} metafield.
|
|
436
|
+
* @returns Promise
|
|
437
|
+
*/
|
|
438
|
+
public putMetafield = async (customerId: number, metafield: IMetafield): Promise<IMetafield> => {
|
|
439
|
+
return new Promise<IMetafield>(async (resolve, reject) => {
|
|
440
|
+
try {
|
|
441
|
+
Logger.info(`Updating a metafield for customer id -> ${customerId}`);
|
|
442
|
+
const metafieldSaved = await this.getMetafield(customerId, metafield.namespace, metafield.key);
|
|
443
|
+
if (metafieldSaved && metafieldSaved.id) {
|
|
444
|
+
Logger.info(`Existing Metafield. Updating a metafield for customer id -> ${customerId}`);
|
|
445
|
+
const response = await this.axiosInstance.put(`/customers/${customerId}/metafields/${metafieldSaved.id}.json`, { metafield: { id: metafieldSaved.id, value: metafield.value } });
|
|
446
|
+
resolve(response.data.metafield);
|
|
447
|
+
} else {
|
|
448
|
+
Logger.info(`Metafield not found. Updating the metafield for customer id -> ${customerId}`);
|
|
449
|
+
const createdMetafield = await this.postMetafield(customerId, metafield);
|
|
450
|
+
resolve(createdMetafield);
|
|
451
|
+
}
|
|
452
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
453
|
+
});
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Deletes a metafield for a customer.
|
|
458
|
+
*
|
|
459
|
+
* @param {number} id - Customer Id
|
|
460
|
+
* @param {number} metafieldId
|
|
461
|
+
* @returns Promise
|
|
462
|
+
*/
|
|
463
|
+
public deleteMetafield = async (id: number, metafieldId: number): Promise<void> => {
|
|
464
|
+
return new Promise<void>(async (resolve, reject) => {
|
|
465
|
+
try {
|
|
466
|
+
Logger.info(`Posting metafield for customer id -> ${id}`);
|
|
467
|
+
await this.axiosInstance.delete(`/customers/${id}/metafields/${metafieldId}.json`);
|
|
468
|
+
resolve();
|
|
469
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
470
|
+
});
|
|
471
|
+
};
|
|
472
|
+
}
|