cloudcommerce 0.0.52 → 0.0.55
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/CHANGELOG.md +27 -0
- package/package.json +6 -6
- package/packages/api/lib/index.js +14 -3
- package/packages/api/lib/index.js.map +1 -1
- package/packages/api/lib/types.d.ts +1 -1
- package/packages/api/package.json +1 -1
- package/packages/api/src/index.ts +14 -3
- package/packages/api/src/types.ts +1 -1
- package/packages/apps/discounts/lib/discounts.d.ts +1 -1
- package/packages/apps/discounts/lib/discounts.js +2 -3
- package/packages/apps/discounts/lib/discounts.js.map +1 -1
- package/packages/apps/discounts/lib-cjs/apply-discount.cjs +330 -0
- package/packages/apps/discounts/lib-cjs/helpers.cjs +167 -0
- package/packages/apps/discounts/package.json +2 -1
- package/packages/apps/discounts/src/discounts.ts +2 -3
- package/packages/apps/tiny-erp/CHANGELOG.md +1 -0
- package/packages/apps/tiny-erp/README.md +1 -0
- package/packages/apps/tiny-erp/package.json +27 -0
- package/packages/apps/tiny-erp/src/index.ts +0 -0
- package/packages/apps/tiny-erp/tsconfig.json +3 -0
- package/packages/cli/lib/config-gcloud.js +9 -0
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/config-gcloud.ts +11 -4
- package/packages/events/package.json +1 -1
- package/packages/firebase/lib/config.d.ts +5 -0
- package/packages/firebase/lib/config.js +8 -0
- package/packages/firebase/lib/config.js.map +1 -1
- package/packages/firebase/lib/handlers/check-store-events.js +92 -15
- package/packages/firebase/lib/handlers/check-store-events.js.map +1 -1
- package/packages/firebase/package.json +1 -1
- package/packages/firebase/src/config.ts +9 -0
- package/packages/firebase/src/handlers/check-store-events.ts +98 -18
- package/packages/modules/lib/firebase/call-app-module.js +36 -2
- package/packages/modules/lib/firebase/call-app-module.js.map +1 -1
- package/packages/modules/lib/firebase/handle-module.js +6 -1
- package/packages/modules/lib/firebase/handle-module.js.map +1 -1
- package/packages/modules/package.json +1 -1
- package/packages/modules/src/firebase/call-app-module.ts +37 -3
- package/packages/modules/src/firebase/handle-module.ts +6 -1
- package/packages/passport/package.json +1 -1
- package/packages/ssr/package.json +1 -1
- package/packages/storefront/package.json +4 -4
- package/packages/types/index.ts +4 -1
- package/packages/types/package.json +1 -1
- package/packages/firebase/lib/types.d.ts +0 -6
- package/packages/firebase/lib/types.js +0 -2
- package/packages/firebase/lib/types.js.map +0 -1
- package/packages/firebase/src/types.ts +0 -11
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
const ecomUtils = require('@ecomplus/utils');
|
|
2
|
+
|
|
3
|
+
const validateDateRange = (rule) => {
|
|
4
|
+
// filter campaings by date
|
|
5
|
+
const timestamp = Date.now();
|
|
6
|
+
if (rule.date_range) {
|
|
7
|
+
if (rule.date_range.start && new Date(rule.date_range.start).getTime() > timestamp) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
if (rule.date_range.end && new Date(rule.date_range.end).getTime() < timestamp) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const validateCustomerId = (rule, params) => {
|
|
18
|
+
if (
|
|
19
|
+
Array.isArray(rule.customer_ids)
|
|
20
|
+
&& rule.customer_ids.length
|
|
21
|
+
&& rule.customer_ids.indexOf(params.customer && params.customer._id) === -1
|
|
22
|
+
) {
|
|
23
|
+
// unavailable for current customer
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const checkOpenPromotion = (rule) => {
|
|
30
|
+
return !rule.discount_coupon && !rule.utm_campaign
|
|
31
|
+
&& (!Array.isArray(rule.customer_ids) || !rule.customer_ids.length);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const getValidDiscountRules = (discountRules, params, items) => {
|
|
35
|
+
if (Array.isArray(discountRules) && discountRules.length) {
|
|
36
|
+
// validate rules objects
|
|
37
|
+
return discountRules.filter((rule) => {
|
|
38
|
+
if (!rule || !validateCustomerId(rule, params)) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (Array.isArray(rule.product_ids) && Array.isArray(items)) {
|
|
43
|
+
const checkProductId = (item) => {
|
|
44
|
+
return (!rule.product_ids.length || rule.product_ids.indexOf(item.product_id) > -1);
|
|
45
|
+
};
|
|
46
|
+
// set/add discount value from lowest item price
|
|
47
|
+
let value;
|
|
48
|
+
if (rule.discount_lowest_price) {
|
|
49
|
+
items.forEach((item) => {
|
|
50
|
+
const price = ecomUtils.price(item);
|
|
51
|
+
if (price > 0 && checkProductId(item) && (!value || value > price)) {
|
|
52
|
+
value = price;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
} else if (rule.discount_kit_subtotal) {
|
|
56
|
+
value = 0;
|
|
57
|
+
items.forEach((item) => {
|
|
58
|
+
const price = ecomUtils.price(item);
|
|
59
|
+
if (price > 0 && checkProductId(item)) {
|
|
60
|
+
value += price * item.quantity;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (value) {
|
|
65
|
+
if (rule.discount && rule.discount.value) {
|
|
66
|
+
if (rule.discount.type === 'percentage') {
|
|
67
|
+
value *= rule.discount.value / 100;
|
|
68
|
+
} else {
|
|
69
|
+
value += rule.discount.value;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
rule.discount = {
|
|
73
|
+
...rule.discount,
|
|
74
|
+
type: 'fixed',
|
|
75
|
+
value,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!rule.discount || !rule.discount.value) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return validateDateRange(rule);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// returns array anyway
|
|
88
|
+
return [];
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const matchDiscountRule = (discountRules, params) => {
|
|
92
|
+
// try to match a promotion
|
|
93
|
+
if (params.discount_coupon) {
|
|
94
|
+
// match only by discount coupon
|
|
95
|
+
return {
|
|
96
|
+
discountRule: discountRules.find((rule) => {
|
|
97
|
+
return rule.case_insensitive
|
|
98
|
+
? typeof rule.discount_coupon === 'string'
|
|
99
|
+
&& rule.discount_coupon.toUpperCase() === params.discount_coupon.toUpperCase()
|
|
100
|
+
: rule.discount_coupon === params.discount_coupon;
|
|
101
|
+
}),
|
|
102
|
+
discountMatchEnum: 'COUPON',
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// try to match by UTM campaign first
|
|
107
|
+
if (params.utm && params.utm.campaign) {
|
|
108
|
+
const discountRule = discountRules.find((rule) => {
|
|
109
|
+
return rule.case_insensitive
|
|
110
|
+
? typeof rule.utm_campaign === 'string'
|
|
111
|
+
&& rule.utm_campaign.toUpperCase() === params.utm.campaign.toUpperCase()
|
|
112
|
+
: rule.utm_campaign === params.utm.campaign;
|
|
113
|
+
});
|
|
114
|
+
if (discountRule) {
|
|
115
|
+
return {
|
|
116
|
+
discountRule,
|
|
117
|
+
discountMatchEnum: 'UTM',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// then try to match by customer
|
|
123
|
+
if (params.customer && params.customer._id) {
|
|
124
|
+
const discountRule = discountRules.find((rule) => Array.isArray(rule.customer_ids)
|
|
125
|
+
&& rule.customer_ids.indexOf(params.customer._id) > -1);
|
|
126
|
+
if (discountRule) {
|
|
127
|
+
return {
|
|
128
|
+
discountRule,
|
|
129
|
+
discountMatchEnum: 'CUSTOMER',
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// last try to match by open promotions
|
|
135
|
+
return {
|
|
136
|
+
discountRule: discountRules.find(checkOpenPromotion),
|
|
137
|
+
discountMatchEnum: 'OPEN',
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const checkCampaignProducts = (campaignProducts, params) => {
|
|
142
|
+
if (Array.isArray(campaignProducts) && campaignProducts.length) {
|
|
143
|
+
// must check at least one campaign product on cart
|
|
144
|
+
let hasProductMatch;
|
|
145
|
+
if (params.items && params.items.length) {
|
|
146
|
+
for (let i = 0; i < campaignProducts.length; i++) {
|
|
147
|
+
if (params.items.find((item) => item.quantity && item.product_id === campaignProducts[i])) {
|
|
148
|
+
hasProductMatch = true;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (!hasProductMatch) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return true;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
module.exports = {
|
|
161
|
+
validateDateRange,
|
|
162
|
+
validateCustomerId,
|
|
163
|
+
checkOpenPromotion,
|
|
164
|
+
getValidDiscountRules,
|
|
165
|
+
matchDiscountRule,
|
|
166
|
+
checkCampaignProducts,
|
|
167
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudcommerce/app-discounts",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.55",
|
|
5
5
|
"description": "E-Com Plus Cloud Commerce app for complex discount rules",
|
|
6
6
|
"main": "lib/discounts.js",
|
|
7
7
|
"repository": {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@cloudcommerce/api": "workspace:*",
|
|
23
23
|
"@cloudcommerce/firebase": "workspace:*",
|
|
24
|
+
"@ecomplus/utils": "^1.4.1",
|
|
24
25
|
"firebase-admin": "^11.0.1",
|
|
25
26
|
"firebase-functions": "^3.22.0"
|
|
26
27
|
},
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/* eslint-disable import/prefer-default-export */
|
|
2
2
|
import type { AppModuleBody } from '@cloudcommerce/types';
|
|
3
|
-
import
|
|
3
|
+
import * as handleApplyDiscount from '../lib-cjs/apply-discount.cjs';
|
|
4
4
|
|
|
5
5
|
export const applyDiscount = async (modBody: AppModuleBody) => {
|
|
6
|
-
|
|
7
|
-
return {};
|
|
6
|
+
return handleApplyDiscount(modBody);
|
|
8
7
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Please refer to GitHub [repository releases](https://github.com/ecomplus/cloud-commerce/releases) or monorepo unified [CHANGELOG.md](https://github.com/ecomplus/cloud-commerce/blob/main/CHANGELOG.md).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# `@cloudcommerce/tiny`
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cloudcommerce/app-tiny-erp",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.55",
|
|
5
|
+
"description": "E-Com Plus Cloud Commerce",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ecomplus/cloud-commerce.git",
|
|
10
|
+
"directory": "packages/tiny"
|
|
11
|
+
},
|
|
12
|
+
"author": "E-Com Club Softwares para E-commerce <ti@e-com.club>",
|
|
13
|
+
"license": "Apache 2.0 with Commons Clause",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/ecomplus/cloud-commerce/issues"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/ecomplus/cloud-commerce/tree/main/packages/tiny#readme",
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "echo '@ecomplus/tiny-erp'"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@cloudcommerce/api": "workspace:*"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@cloudcommerce/types": "workspace:*"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
File without changes
|
|
@@ -30,6 +30,7 @@ const siginGcloudAndSetIAM = async (projectId, pwd) => {
|
|
|
30
30
|
'roles/iam.serviceAccountUser',
|
|
31
31
|
'roles/run.viewer',
|
|
32
32
|
'roles/serviceusage.apiKeysViewer',
|
|
33
|
+
'roles/serviceusage.serviceUsageAdmin',
|
|
33
34
|
];
|
|
34
35
|
const serviceAccount = await checkServiceAccountExists(projectId);
|
|
35
36
|
if (!serviceAccount) {
|
|
@@ -53,6 +54,14 @@ const siginGcloudAndSetIAM = async (projectId, pwd) => {
|
|
|
53
54
|
],
|
|
54
55
|
role,
|
|
55
56
|
};
|
|
57
|
+
if (role === 'roles/serviceusage.serviceUsageAdmin') {
|
|
58
|
+
const roleExpiration = Date.now() + 1000 * 60 * 60 * 12;
|
|
59
|
+
newBinding.condition = {
|
|
60
|
+
expression: `request.time < timestamp("${new Date(roleExpiration).toISOString()}")`,
|
|
61
|
+
title: 'Enable APIs on first deploy',
|
|
62
|
+
description: null,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
56
65
|
bindings.push(newBinding);
|
|
57
66
|
mustUpdatePolicy = true;
|
|
58
67
|
} else {
|
|
@@ -32,6 +32,7 @@ const siginGcloudAndSetIAM = async (projectId: string, pwd: string) => {
|
|
|
32
32
|
'roles/iam.serviceAccountUser',
|
|
33
33
|
'roles/run.viewer',
|
|
34
34
|
'roles/serviceusage.apiKeysViewer',
|
|
35
|
+
'roles/serviceusage.serviceUsageAdmin',
|
|
35
36
|
];
|
|
36
37
|
const serviceAccount = await checkServiceAccountExists(projectId);
|
|
37
38
|
if (!serviceAccount) {
|
|
@@ -47,17 +48,23 @@ const siginGcloudAndSetIAM = async (projectId: string, pwd: string) => {
|
|
|
47
48
|
|
|
48
49
|
let mustUpdatePolicy = false;
|
|
49
50
|
roles.forEach((role) => {
|
|
50
|
-
const roleFound = bindings.find(
|
|
51
|
-
(binding: { [key: string]: string | string[] }) => binding.role === role,
|
|
52
|
-
);
|
|
51
|
+
const roleFound = bindings.find((binding) => binding.role === role);
|
|
53
52
|
const memberServiceAccount = `serviceAccount:${getAccountEmail(projectId)}`;
|
|
54
53
|
if (!roleFound) {
|
|
55
|
-
const newBinding = {
|
|
54
|
+
const newBinding: { [key: string]: any } = {
|
|
56
55
|
members: [
|
|
57
56
|
memberServiceAccount,
|
|
58
57
|
],
|
|
59
58
|
role,
|
|
60
59
|
};
|
|
60
|
+
if (role === 'roles/serviceusage.serviceUsageAdmin') {
|
|
61
|
+
const roleExpiration = Date.now() + 1000 * 60 * 60 * 12;
|
|
62
|
+
newBinding.condition = {
|
|
63
|
+
expression: `request.time < timestamp("${new Date(roleExpiration).toISOString()}")`,
|
|
64
|
+
title: 'Enable APIs on first deploy',
|
|
65
|
+
description: null,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
61
68
|
bindings.push(newBinding);
|
|
62
69
|
mustUpdatePolicy = true;
|
|
63
70
|
} else {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AppEventsTopic } from '@cloudcommerce/types';
|
|
1
2
|
declare const _default: {
|
|
2
3
|
get(): {
|
|
3
4
|
hello: string;
|
|
@@ -13,6 +14,10 @@ declare const _default: {
|
|
|
13
14
|
discounts: {
|
|
14
15
|
appId: number;
|
|
15
16
|
};
|
|
17
|
+
tinyErp: {
|
|
18
|
+
appId: number;
|
|
19
|
+
events: AppEventsTopic[];
|
|
20
|
+
};
|
|
16
21
|
};
|
|
17
22
|
};
|
|
18
23
|
set(config: any): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,aAAa;AACb,MAAM,GAAG,GAA8B,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,EAAE,GAAG,CAAC;OAC/E,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC;OACtC,EAAE,CAAC;AAER,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;AAE9B,MAAM,IAAI,GAAG;IACX,QAAQ,EAAE;QACR,KAAK,EAAE,8BAA8B;QACrC,IAAI,EAAE,GAAG,CAAC,SAAS,IAAI,YAAY;QACnC,QAAQ,EAAE,GAAG,CAAC,aAAa,IAAI,gBAAgB;QAC/C,cAAc,EAAE,GAAG,CAAC,oBAAoB,IAAI,uBAAuB;QACnE,WAAW,EAAE,GAAG,CAAC,iBAAiB,IAAI,oBAAoB;QAC1D,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC;QAClC,oBAAoB,EAAE;YACpB,MAAM,EAAE,GAAG,CAAC,aAAa,IAAI,aAAa;SAC3C;QACD,IAAI,EAAE;YACJ,SAAS,EAAE;gBACT,KAAK,EAAE,IAAI;aACZ;YACD,OAAO,EAAE;gBACP,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE;oBACN,qBAAqB;oBACrB,cAAc;oBACd,mBAAmB;iBACA;aACtB;SACF;KACF;CACF,CAAC;AAEF,eAAe;IACb,GAAG;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IACD,GAAG,CAAC,MAAM;QACR,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjD,IAAI,MAAM,CAAC,OAAO,EAAE;YAClB,GAAG,CAAC,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC;SACpC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -1,28 +1,105 @@
|
|
|
1
|
-
// eslint-disable-next-line import/no-unresolved
|
|
2
|
-
import { getFirestore } from 'firebase-admin/firestore';
|
|
3
1
|
import logger from 'firebase-functions/lib/logger';
|
|
4
2
|
import api from '@cloudcommerce/api';
|
|
5
3
|
import getEnv from '../env.js';
|
|
4
|
+
import config from '../config.js';
|
|
5
|
+
|
|
6
|
+
const parseEventsTopic = (eventsTopic) => {
|
|
7
|
+
const [resource, eventName] = eventsTopic.split('-');
|
|
8
|
+
const params = {};
|
|
9
|
+
const bodySet = {};
|
|
10
|
+
if (eventName === 'new') {
|
|
11
|
+
params.action = 'create';
|
|
12
|
+
} else {
|
|
13
|
+
switch (resource) {
|
|
14
|
+
case 'orders':
|
|
15
|
+
switch (eventName) {
|
|
16
|
+
case 'paid':
|
|
17
|
+
bodySet['financial_status.current'] = 'paid';
|
|
18
|
+
break;
|
|
19
|
+
case 'readyForShipping':
|
|
20
|
+
bodySet['fulfillment_status.current'] = 'ready_for_shipping';
|
|
21
|
+
break;
|
|
22
|
+
case 'shipped':
|
|
23
|
+
case 'delivered':
|
|
24
|
+
bodySet['fulfillment_status.current'] = eventName;
|
|
25
|
+
break;
|
|
26
|
+
case 'cancelled':
|
|
27
|
+
bodySet.status = 'cancelled';
|
|
28
|
+
break;
|
|
29
|
+
default: // anyStatusSet
|
|
30
|
+
params.modified_fields = [
|
|
31
|
+
'financial_status',
|
|
32
|
+
'fulfillment_status',
|
|
33
|
+
'status',
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
case 'products':
|
|
38
|
+
params.modified_fields = eventName === 'priceSet'
|
|
39
|
+
? ['price', 'variations.price']
|
|
40
|
+
: ['quantity']; // quantitySet
|
|
41
|
+
break;
|
|
42
|
+
case 'carts':
|
|
43
|
+
params.modified_fields = ['customers']; // customerSet
|
|
44
|
+
break;
|
|
45
|
+
default:
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
Object.keys(bodySet).forEach((field) => {
|
|
49
|
+
params[`body.${field}`] = bodySet[field];
|
|
50
|
+
});
|
|
51
|
+
return { resource, params };
|
|
52
|
+
};
|
|
6
53
|
|
|
7
54
|
export default async () => {
|
|
55
|
+
const { apps } = config.get();
|
|
8
56
|
const { apiAuth } = getEnv();
|
|
9
|
-
const
|
|
57
|
+
const subscribersApps = [];
|
|
58
|
+
Object.keys(apps).forEach((appName) => {
|
|
59
|
+
const appObj = apps[appName];
|
|
60
|
+
if (appObj.events && appObj.events.length) {
|
|
61
|
+
subscribersApps.push(appObj);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
const activeSubscribersApps = (await api.get('applications', {
|
|
65
|
+
params: {
|
|
66
|
+
state: 'active',
|
|
67
|
+
app_id: subscribersApps.map(({ appId }) => appId),
|
|
68
|
+
fields: 'app_id',
|
|
69
|
+
},
|
|
70
|
+
})).data.result;
|
|
71
|
+
logger.info({ activeSubscribersApps });
|
|
10
72
|
const listenedEvents = [];
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
73
|
+
subscribersApps.forEach(({ appId, events }) => {
|
|
74
|
+
if (activeSubscribersApps.find((app) => app.app_id === appId)) {
|
|
75
|
+
events.forEach((eventsTopic) => {
|
|
76
|
+
listenedEvents.push(eventsTopic);
|
|
77
|
+
});
|
|
15
78
|
}
|
|
16
79
|
});
|
|
17
80
|
logger.info({ listenedEvents });
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
81
|
+
listenedEvents.forEach(async (eventsTopic) => {
|
|
82
|
+
const { resource, params } = parseEventsTopic(eventsTopic);
|
|
83
|
+
let { data: { result } } = await api.get(`events/${resource}`, {
|
|
84
|
+
...apiAuth,
|
|
85
|
+
params,
|
|
86
|
+
});
|
|
87
|
+
/*
|
|
88
|
+
global.api_events_middleware = async (
|
|
89
|
+
resource: string,
|
|
90
|
+
result: EventsResult,
|
|
91
|
+
}) => {
|
|
92
|
+
if (resource === 'orders') {
|
|
93
|
+
await axios.port(url, result);
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
};
|
|
97
|
+
*/
|
|
98
|
+
const middleware = global.api_events_middleware;
|
|
99
|
+
if (typeof middleware === 'function') {
|
|
100
|
+
result = await middleware(resource, result);
|
|
101
|
+
}
|
|
102
|
+
logger.info(`> '${eventsTopic}' events: `, result);
|
|
26
103
|
});
|
|
27
104
|
return true;
|
|
28
105
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-store-events.js","sourceRoot":"","sources":["../../src/handlers/check-store-events.ts"],"names":[],"mappings":"AACA,
|
|
1
|
+
{"version":3,"file":"check-store-events.js","sourceRoot":"","sources":["../../src/handlers/check-store-events.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AppEventsTopic } from '@cloudcommerce/types';
|
|
1
2
|
import Deepmerge from '@fastify/deepmerge';
|
|
2
3
|
import {
|
|
3
4
|
DEFAULT_LANG,
|
|
@@ -28,6 +29,14 @@ const self = {
|
|
|
28
29
|
discounts: {
|
|
29
30
|
appId: 1252,
|
|
30
31
|
},
|
|
32
|
+
tinyErp: {
|
|
33
|
+
appId: 105922,
|
|
34
|
+
events: [
|
|
35
|
+
'orders-anyStatusSet',
|
|
36
|
+
'products-new',
|
|
37
|
+
'products-priceSet',
|
|
38
|
+
] as AppEventsTopic[],
|
|
39
|
+
},
|
|
31
40
|
},
|
|
32
41
|
},
|
|
33
42
|
};
|
|
@@ -1,29 +1,109 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
// eslint-disable-next-line import/no-unresolved
|
|
3
|
-
import { getFirestore } from 'firebase-admin/firestore';
|
|
1
|
+
import type { Resource, AppEventsTopic } from '@cloudcommerce/types';
|
|
4
2
|
import logger from 'firebase-functions/lib/logger';
|
|
5
|
-
import api from '@cloudcommerce/api';
|
|
3
|
+
import api, { ApiConfig } from '@cloudcommerce/api';
|
|
6
4
|
import getEnv from '../env';
|
|
5
|
+
import config from '../config';
|
|
6
|
+
|
|
7
|
+
const parseEventsTopic = (eventsTopic: AppEventsTopic) => {
|
|
8
|
+
const [resource, eventName] = eventsTopic.split('-');
|
|
9
|
+
const params: ApiConfig['params'] = {};
|
|
10
|
+
const bodySet: { [key: string]: any } = {};
|
|
11
|
+
if (eventName === 'new') {
|
|
12
|
+
params.action = 'create';
|
|
13
|
+
} else {
|
|
14
|
+
switch (resource) {
|
|
15
|
+
case 'orders':
|
|
16
|
+
switch (eventName) {
|
|
17
|
+
case 'paid':
|
|
18
|
+
bodySet['financial_status.current'] = 'paid';
|
|
19
|
+
break;
|
|
20
|
+
case 'readyForShipping':
|
|
21
|
+
bodySet['fulfillment_status.current'] = 'ready_for_shipping';
|
|
22
|
+
break;
|
|
23
|
+
case 'shipped':
|
|
24
|
+
case 'delivered':
|
|
25
|
+
bodySet['fulfillment_status.current'] = eventName;
|
|
26
|
+
break;
|
|
27
|
+
case 'cancelled':
|
|
28
|
+
bodySet.status = 'cancelled';
|
|
29
|
+
break;
|
|
30
|
+
default: // anyStatusSet
|
|
31
|
+
params.modified_fields = [
|
|
32
|
+
'financial_status',
|
|
33
|
+
'fulfillment_status',
|
|
34
|
+
'status',
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
break;
|
|
38
|
+
case 'products':
|
|
39
|
+
params.modified_fields = eventName === 'priceSet'
|
|
40
|
+
? ['price', 'variations.price']
|
|
41
|
+
: ['quantity']; // quantitySet
|
|
42
|
+
break;
|
|
43
|
+
case 'carts':
|
|
44
|
+
params.modified_fields = ['customers']; // customerSet
|
|
45
|
+
break;
|
|
46
|
+
default:
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
Object.keys(bodySet).forEach((field) => {
|
|
50
|
+
params[`body.${field}`] = bodySet[field];
|
|
51
|
+
});
|
|
52
|
+
return { resource, params } as {
|
|
53
|
+
resource: Resource;
|
|
54
|
+
params: ApiConfig['params'];
|
|
55
|
+
};
|
|
56
|
+
};
|
|
7
57
|
|
|
8
58
|
export default async () => {
|
|
59
|
+
const { apps } = config.get();
|
|
9
60
|
const { apiAuth } = getEnv();
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
61
|
+
const subscribersApps: Array<{ appId: number, events: AppEventsTopic[] }> = [];
|
|
62
|
+
Object.keys(apps).forEach((appName) => {
|
|
63
|
+
const appObj = apps[appName];
|
|
64
|
+
if (appObj.events && appObj.events.length) {
|
|
65
|
+
subscribersApps.push(appObj);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
const activeSubscribersApps = (await api.get('applications', {
|
|
69
|
+
params: {
|
|
70
|
+
state: 'active',
|
|
71
|
+
app_id: subscribersApps.map(({ appId }) => appId),
|
|
72
|
+
fields: 'app_id',
|
|
73
|
+
},
|
|
74
|
+
})).data.result;
|
|
75
|
+
logger.info({ activeSubscribersApps });
|
|
76
|
+
const listenedEvents: AppEventsTopic[] = [];
|
|
77
|
+
subscribersApps.forEach(({ appId, events }) => {
|
|
78
|
+
if (activeSubscribersApps.find((app) => app.app_id === appId)) {
|
|
79
|
+
events.forEach((eventsTopic) => {
|
|
80
|
+
listenedEvents.push(eventsTopic);
|
|
81
|
+
});
|
|
16
82
|
}
|
|
17
83
|
});
|
|
18
84
|
logger.info({ listenedEvents });
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
85
|
+
listenedEvents.forEach(async (eventsTopic) => {
|
|
86
|
+
const { resource, params } = parseEventsTopic(eventsTopic);
|
|
87
|
+
let { data: { result } } = await api.get(`events/${resource}`, {
|
|
88
|
+
...apiAuth,
|
|
89
|
+
params,
|
|
90
|
+
});
|
|
91
|
+
/*
|
|
92
|
+
global.api_events_middleware = async (
|
|
93
|
+
resource: string,
|
|
94
|
+
result: EventsResult,
|
|
95
|
+
}) => {
|
|
96
|
+
if (resource === 'orders') {
|
|
97
|
+
await axios.port(url, result);
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
};
|
|
101
|
+
*/
|
|
102
|
+
const middleware = global.api_events_middleware;
|
|
103
|
+
if (typeof middleware === 'function') {
|
|
104
|
+
result = await middleware(resource, result);
|
|
105
|
+
}
|
|
106
|
+
logger.info(`> '${eventsTopic}' events: `, result);
|
|
27
107
|
});
|
|
28
108
|
return true;
|
|
29
109
|
};
|