ts-glitter 20.4.6 → 20.4.8
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/lowcode/Entry.js +1 -1
- package/lowcode/Entry.ts +1 -1
- package/lowcode/backend-manager/bg-widget.js +19 -17
- package/lowcode/backend-manager/bg-widget.ts +19 -17
- package/lowcode/cms-plugin/stock-history.js +1 -0
- package/lowcode/cms-plugin/stock-history.ts +10 -0
- package/lowcode/cms-plugin/user/user-module.js +28 -28
- package/lowcode/cms-plugin/user/user-module.ts +29 -31
- package/lowcode/cms-plugin/user-list.js +55 -42
- package/lowcode/cms-plugin/user-list.ts +71 -47
- package/lowcode/glitter-base/route/progress.js +32 -0
- package/lowcode/glitter-base/route/progress.ts +36 -0
- package/lowcode/glitter-base/route/user.js +37 -1
- package/lowcode/glitter-base/route/user.ts +40 -1
- package/lowcode/glitterBundle/dialog/ShareDialog.ts +0 -1
- package/package.json +3 -1
- package/src/api-public/controllers/ai-chat.js.map +1 -1
- package/src/api-public/controllers/app-release.js.map +1 -1
- package/src/api-public/controllers/delivery.js.map +1 -1
- package/src/api-public/controllers/graph-api.js.map +1 -1
- package/src/api-public/controllers/index.js +9 -8
- package/src/api-public/controllers/index.js.map +1 -1
- package/src/api-public/controllers/index.ts +171 -169
- package/src/api-public/controllers/lambda.js.map +1 -1
- package/src/api-public/controllers/manager.js.map +1 -1
- package/src/api-public/controllers/post.js.map +1 -1
- package/src/api-public/controllers/progress.d.ts +3 -0
- package/src/api-public/controllers/progress.js +29 -0
- package/src/api-public/controllers/progress.js.map +1 -0
- package/src/api-public/controllers/progress.ts +25 -0
- package/src/api-public/controllers/sql_api.js.map +1 -1
- package/src/api-public/controllers/track.js.map +1 -1
- package/src/api-public/controllers/user.js +47 -1
- package/src/api-public/controllers/user.js.map +1 -1
- package/src/api-public/controllers/user.ts +44 -3
- package/src/api-public/services/checkout.d.ts +1 -0
- package/src/api-public/services/checkout.js +16 -6
- package/src/api-public/services/checkout.js.map +1 -1
- package/src/api-public/services/checkout.ts +28 -18
- package/src/api-public/services/customer-sessions.js.map +1 -1
- package/src/api-public/services/fake-data-model/fake-order.d.ts +6 -1
- package/src/api-public/services/fake-data-model/fake-order.js +159 -155
- package/src/api-public/services/fake-data-model/fake-order.js.map +1 -1
- package/src/api-public/services/fake-data-model/fake-order.ts +186 -179
- package/src/api-public/services/fake-data-model/fake-product.js +94 -94
- package/src/api-public/services/fake-data-model/fake-product.js.map +1 -1
- package/src/api-public/services/fake-data-model/fake-product.ts +109 -114
- package/src/api-public/services/fake-data-model/fake-user.d.ts +17 -1
- package/src/api-public/services/fake-data-model/fake-user.js +70 -384
- package/src/api-public/services/fake-data-model/fake-user.js.map +1 -1
- package/src/api-public/services/fake-data-model/fake-user.ts +111 -394
- package/src/api-public/services/initial-fake-data.js +50 -10
- package/src/api-public/services/initial-fake-data.js.map +1 -1
- package/src/api-public/services/initial-fake-data.ts +92 -22
- package/src/api-public/services/invoice.js.map +1 -1
- package/src/api-public/services/manager.js.map +1 -1
- package/src/api-public/services/notify.js +234 -213
- package/src/api-public/services/notify.js.map +1 -1
- package/src/api-public/services/notify.ts +520 -494
- package/src/api-public/services/phone-verify.js +1 -1
- package/src/api-public/services/phone-verify.js.map +1 -1
- package/src/api-public/services/phone-verify.ts +1 -1
- package/src/api-public/services/pos.js.map +1 -1
- package/src/api-public/services/post.js.map +1 -1
- package/src/api-public/services/rebate.d.ts +1 -0
- package/src/api-public/services/rebate.js +15 -8
- package/src/api-public/services/rebate.js.map +1 -1
- package/src/api-public/services/rebate.ts +24 -15
- package/src/api-public/services/recommend.js.map +1 -1
- package/src/api-public/services/schedule.js +7 -4
- package/src/api-public/services/schedule.js.map +1 -1
- package/src/api-public/services/schedule.ts +344 -335
- package/src/api-public/services/shopee.js.map +1 -1
- package/src/api-public/services/shopping.d.ts +1 -1
- package/src/api-public/services/shopping.js +28 -25
- package/src/api-public/services/shopping.js.map +1 -1
- package/src/api-public/services/shopping.ts +89 -76
- package/src/api-public/services/stock.js.map +1 -1
- package/src/api-public/services/user.d.ts +10 -1
- package/src/api-public/services/user.js +245 -42
- package/src/api-public/services/user.js.map +1 -1
- package/src/api-public/services/user.ts +325 -45
- package/src/api-public/services/voucher.js.map +1 -1
- package/src/api-public/services/workers.js.map +1 -1
- package/src/api-public/utils/ut-permission.d.ts +0 -1
- package/src/api-public/utils/ut-permission.js.map +1 -1
- package/src/config.d.ts +2 -1
- package/src/config.js +2 -1
- package/src/config.js.map +1 -1
- package/src/config.ts +142 -142
- package/src/controllers/app.js.map +1 -1
- package/src/controllers/backend-server.js.map +1 -1
- package/src/controllers/filemanager.js.map +1 -1
- package/src/controllers/index.js.map +1 -1
- package/src/controllers/user.js.map +1 -1
- package/src/domain-check.js.map +1 -1
- package/src/index.js.map +1 -1
- package/src/index.ts +3 -12
- package/src/modules/AWSLib.js +2 -3
- package/src/modules/AWSLib.js.map +1 -1
- package/src/modules/database.d.ts +1 -2
- package/src/modules/database.js.map +1 -1
- package/src/modules/firebase.js.map +1 -1
- package/src/modules/logger.js.map +1 -1
- package/src/modules/redis.d.ts +1 -1
- package/src/modules/redis.js.map +1 -1
- package/src/run.js +1 -2
- package/src/run.js.map +1 -1
- package/src/services/backend-service.js.map +1 -1
- package/src/services/create-instance.js +3 -4
- package/src/services/create-instance.js.map +1 -1
- package/src/services/global-event.js.map +1 -1
- package/src/services/ios-release.js.map +1 -1
- package/src/services/page.js.map +1 -1
- package/src/services/private_config.js.map +1 -1
- package/src/services/release.js.map +1 -1
- package/src/services/seo.js.map +1 -1
- package/src/services/tool.js +2 -3
- package/src/services/tool.js.map +1 -1
- package/src/services/user.js.map +1 -1
- package/src/services/web-socket.js.map +1 -1
- package/src/update-progress-track.d.ts +14 -0
- package/src/update-progress-track.js +28 -0
- package/src/update-progress-track.js.map +1 -0
- package/src/update-progress-track.ts +34 -0
- package/j4enepo67p.json +0 -1
|
@@ -15,69 +15,68 @@ import { App } from '../../services/app.js';
|
|
|
15
15
|
import { UserUpdate } from './user-update.js';
|
|
16
16
|
|
|
17
17
|
type ScheduleItem = {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
second: number;
|
|
19
|
+
status: boolean;
|
|
20
|
+
func: keyof Schedule;
|
|
21
|
+
desc: string;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
export class Schedule {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
25
|
+
static app: string[] = [];
|
|
26
|
+
|
|
27
|
+
async perload(app: string) {
|
|
28
|
+
const brand_type = await App.checkBrandAndMemberType(app);
|
|
29
|
+
if (brand_type.brand === 'shopnex' && brand_type.domain) {
|
|
30
|
+
if (!(await this.isDatabasePass(app))) return false;
|
|
31
|
+
await ApiPublic.createScheme(app);
|
|
32
|
+
return true;
|
|
33
|
+
} else {
|
|
34
|
+
return false;
|
|
37
35
|
}
|
|
36
|
+
}
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
async isDatabaseExists(app: string) {
|
|
39
|
+
return (await db.query(`SHOW DATABASES LIKE \'${app}\';`, [])).length > 0;
|
|
40
|
+
}
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
async isDatabasePass(app: string) {
|
|
43
|
+
const SQL = `
|
|
45
44
|
SELECT *
|
|
46
45
|
FROM ${saasConfig.SAAS_NAME}.app_config
|
|
47
46
|
WHERE appName = \'${app}\'
|
|
48
47
|
AND (refer_app is null OR refer_app = appName);
|
|
49
48
|
`;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
} catch (e) {
|
|
66
|
-
throw exception.BadRequestError('BAD_REQUEST', 'Example Error: ' + e, null);
|
|
49
|
+
return (await db.query(SQL, [])).length > 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async isTableExists(table: string, app: string) {
|
|
53
|
+
return (await db.query(`SHOW TABLES IN \`${app}\` LIKE \'${table}\';`, [])).length > 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async example(sec: number) {
|
|
57
|
+
try {
|
|
58
|
+
for (const app of Schedule.app) {
|
|
59
|
+
if (await this.perload(app)) {
|
|
60
|
+
// 排程範例
|
|
61
|
+
// await
|
|
67
62
|
}
|
|
68
|
-
|
|
63
|
+
}
|
|
64
|
+
} catch (e) {
|
|
65
|
+
throw exception.BadRequestError('BAD_REQUEST', 'Example Error: ' + e, null);
|
|
69
66
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
67
|
+
setTimeout(() => this.example(sec), sec * 1000);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async autoCancelOrder(sec: number) {
|
|
71
|
+
let clock = new Date();
|
|
72
|
+
console.log(`autoCancelOrder`);
|
|
73
|
+
for (const app of Schedule.app) {
|
|
74
|
+
try {
|
|
75
|
+
if (await this.perload(app)) {
|
|
76
|
+
const config = await new User(app).getConfigV2({ key: 'login_config', user_id: 'manager' });
|
|
77
|
+
if (config?.auto_cancel_order_timer && config.auto_cancel_order_timer > 0) {
|
|
78
|
+
const orders = await db.query(
|
|
79
|
+
`SELECT * FROM \`${app}\`.t_checkout
|
|
81
80
|
WHERE
|
|
82
81
|
status = 0
|
|
83
82
|
AND created_time < NOW() - INTERVAL ${config.auto_cancel_order_timer} HOUR
|
|
@@ -86,332 +85,342 @@ export class Schedule {
|
|
|
86
85
|
AND progress='wait'
|
|
87
86
|
AND payment_method != 'cash_on_delivery'
|
|
88
87
|
ORDER BY id DESC;`,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
} catch (e) {
|
|
105
|
-
console.error(`autoCancelOrder-Error`,e)
|
|
106
|
-
}
|
|
88
|
+
[]
|
|
89
|
+
);
|
|
90
|
+
await Promise.all(
|
|
91
|
+
orders.map(async (order: any) => {
|
|
92
|
+
order.orderData.orderStatus = '-1';
|
|
93
|
+
order.orderData.archived = 'true';
|
|
94
|
+
return new Shopping(app).putOrder({
|
|
95
|
+
id: order.id,
|
|
96
|
+
orderData: order.orderData,
|
|
97
|
+
status: '0',
|
|
98
|
+
});
|
|
99
|
+
})
|
|
100
|
+
);
|
|
101
|
+
}
|
|
107
102
|
}
|
|
108
|
-
|
|
109
|
-
console.
|
|
103
|
+
} catch (e) {
|
|
104
|
+
console.error(`autoCancelOrder-Error`, e);
|
|
105
|
+
}
|
|
110
106
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
107
|
+
setTimeout(() => this.autoCancelOrder(sec), sec * 1000);
|
|
108
|
+
console.log(`autoCancelOrder-Stop`, (new Date().getTime() - clock.getTime()) / 1000);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async renewMemberLevel(sec: number) {
|
|
112
|
+
let clock = new Date();
|
|
113
|
+
console.log(`renewMemberLevel`);
|
|
114
|
+
try {
|
|
115
|
+
for (const app of Schedule.app) {
|
|
115
116
|
try {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
},50)
|
|
128
|
-
})
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
console.log(`renewMemberLevel-finish->`,app)
|
|
132
|
-
}catch (e) {
|
|
133
|
-
console.log(`renewMemberLevel-error-continue`)
|
|
134
|
-
}
|
|
117
|
+
if (await this.perload(app)) {
|
|
118
|
+
const users = await db.query(`select * from \`${app}\`.t_user `, []);
|
|
119
|
+
for (const user of users) {
|
|
120
|
+
await new User(app).checkMember(user, true);
|
|
121
|
+
await UserUpdate.update(app, user.userID);
|
|
122
|
+
//限制速率每秒最多100筆更新
|
|
123
|
+
await new Promise((resolve, reject) => {
|
|
124
|
+
setTimeout(() => {
|
|
125
|
+
resolve(true);
|
|
126
|
+
}, 50);
|
|
127
|
+
});
|
|
135
128
|
}
|
|
129
|
+
}
|
|
130
|
+
console.log(`renewMemberLevel-finish->`, app);
|
|
136
131
|
} catch (e) {
|
|
137
|
-
|
|
132
|
+
console.log(`renewMemberLevel-error-continue`);
|
|
138
133
|
}
|
|
139
|
-
|
|
140
|
-
|
|
134
|
+
}
|
|
135
|
+
} catch (e) {
|
|
136
|
+
console.error('BAD_REQUEST', 'renewMemberLevel Error: ' + e, null);
|
|
141
137
|
}
|
|
138
|
+
setTimeout(() => this.renewMemberLevel(sec), sec * 1000);
|
|
139
|
+
console.log(`renewMemberLevel-Stop`, (new Date().getTime() - clock.getTime()) / 1000);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async birthRebate(sec: number) {
|
|
143
|
+
let clock = new Date();
|
|
144
|
+
console.log(`resetVoucherHistory`);
|
|
145
|
+
for (const app of Schedule.app) {
|
|
146
|
+
try {
|
|
147
|
+
if (await this.perload(app)) {
|
|
148
|
+
const rebateClass = new Rebate(app);
|
|
149
|
+
const userClass = new User(app);
|
|
150
|
+
|
|
151
|
+
if (await rebateClass.mainStatus()) {
|
|
152
|
+
const getRS = await userClass.getConfig({ key: 'rebate_setting', user_id: 'manager' });
|
|
153
|
+
const rgs = getRS[0] && getRS[0].value.birth ? getRS[0].value.birth : {};
|
|
154
|
+
if (rgs && rgs.switch) {
|
|
155
|
+
async function postUserRebate(id: number, value: number) {
|
|
156
|
+
const used = await rebateClass.canUseRebate(id, 'birth');
|
|
157
|
+
if (used?.result) {
|
|
158
|
+
if (value !== 0) {
|
|
159
|
+
await rebateClass.insertRebate(id, value, '生日禮', {
|
|
160
|
+
type: 'birth',
|
|
161
|
+
deadTime: rgs.unlimited ? undefined : moment().add(rgs.date, 'd').format('YYYY-MM-DD HH:mm:ss'),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
142
166
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
console.log(`resetVoucherHistory`)
|
|
146
|
-
for (const app of Schedule.app) {
|
|
147
|
-
try {
|
|
148
|
-
if (await this.perload(app)) {
|
|
149
|
-
const rebateClass = new Rebate(app);
|
|
150
|
-
const userClass = new User(app);
|
|
151
|
-
|
|
152
|
-
if (await rebateClass.mainStatus()) {
|
|
153
|
-
const getRS = await userClass.getConfig({ key: 'rebate_setting', user_id: 'manager' });
|
|
154
|
-
const rgs = getRS[0] && getRS[0].value.birth ? getRS[0].value.birth : {};
|
|
155
|
-
if (rgs && rgs.switch) {
|
|
156
|
-
async function postUserRebate(id: number, value: number) {
|
|
157
|
-
const used = await rebateClass.canUseRebate(id, 'birth');
|
|
158
|
-
if (used?.result) {
|
|
159
|
-
if (value !== 0) {
|
|
160
|
-
await rebateClass.insertRebate(id, value, '生日禮', {
|
|
161
|
-
type: 'birth',
|
|
162
|
-
deadTime: rgs.unlimited ? undefined : moment().add(rgs.date, 'd').format('YYYY-MM-DD HH:mm:ss'),
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const users = await db.query(
|
|
169
|
-
`SELECT *
|
|
167
|
+
const users = await db.query(
|
|
168
|
+
`SELECT *
|
|
170
169
|
FROM \`${app}\`.t_user
|
|
171
170
|
WHERE MONTH (JSON_EXTRACT(userData, '$.birth')) = MONTH (CURDATE());`,
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
if (rgs.type === 'base') {
|
|
176
|
-
for (const user of users) {
|
|
177
|
-
await postUserRebate(user.userID, rgs.value);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const levelData = await userClass.getConfigV2({ key: 'member_level_config', user_id: 'manager' });
|
|
182
|
-
levelData.levels = levelData.levels || [];
|
|
171
|
+
[]
|
|
172
|
+
);
|
|
183
173
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return { userId: item.userID };
|
|
188
|
-
})
|
|
189
|
-
);
|
|
190
|
-
for (const user of users) {
|
|
191
|
-
const member = usersLevel.find((item) => item.id == user.userID);
|
|
192
|
-
if (member && member.data.id === '') {
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
const data = rgs.level.find((item: { id: string }) => item.id == member?.data.id);
|
|
196
|
-
if (!data) {
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
await postUserRebate(user.userID, data.value);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
174
|
+
if (rgs.type === 'base') {
|
|
175
|
+
for (const user of users) {
|
|
176
|
+
await postUserRebate(user.userID, rgs.value);
|
|
204
177
|
}
|
|
205
|
-
|
|
206
|
-
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const levelData = await userClass.getConfigV2({ key: 'member_level_config', user_id: 'manager' });
|
|
181
|
+
levelData.levels = levelData.levels || [];
|
|
182
|
+
|
|
183
|
+
if (rgs.type === 'levels') {
|
|
184
|
+
const usersLevel = await userClass.getUserLevel(
|
|
185
|
+
users.map((item: { userID: number }) => {
|
|
186
|
+
return { userId: item.userID };
|
|
187
|
+
})
|
|
188
|
+
);
|
|
189
|
+
for (const user of users) {
|
|
190
|
+
const member = usersLevel.find(item => item.id == user.userID);
|
|
191
|
+
if (member && member.data.id === '') {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const data = rgs.level.find((item: { id: string }) => item.id == member?.data.id);
|
|
195
|
+
if (!data) {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
await postUserRebate(user.userID, data.value);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
207
201
|
}
|
|
202
|
+
}
|
|
208
203
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
204
|
+
} catch (e) {
|
|
205
|
+
console.error('BAD_REQUEST', 'birthRebate Error: ' + e, null);
|
|
206
|
+
}
|
|
212
207
|
}
|
|
213
208
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
209
|
+
setTimeout(() => this.birthRebate(sec), sec * 1000);
|
|
210
|
+
console.log(`birthRebate-Stop`, (new Date().getTime() - clock.getTime()) / 1000);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async birthBlessMail(sec: number) {
|
|
214
|
+
let clock = new Date();
|
|
215
|
+
console.log(`resetVoucherHistory`);
|
|
216
|
+
for (const app of Schedule.app) {
|
|
217
|
+
try {
|
|
218
|
+
if (await this.perload(app)) {
|
|
219
|
+
const mailType = 'auto-email-birthday';
|
|
220
|
+
const customerMail = await AutoSendEmail.getDefCompare(app, mailType, 'zh-TW');
|
|
221
|
+
if (customerMail.toggle) {
|
|
222
|
+
// 歷史生日祝福寄件紀錄
|
|
223
|
+
const mailClass = new Mail(app);
|
|
224
|
+
const sendRecords = await mailClass.getMail({
|
|
225
|
+
type: 'download',
|
|
226
|
+
page: 0,
|
|
227
|
+
limit: 0,
|
|
228
|
+
mailType: mailType,
|
|
229
|
+
});
|
|
231
230
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
231
|
+
// 當月生日之顧客
|
|
232
|
+
const users = await db.query(
|
|
233
|
+
`SELECT *
|
|
235
234
|
FROM \`${app}\`.t_user
|
|
236
235
|
WHERE MONTH (JSON_EXTRACT(userData, '$.birth')) = MONTH (CURDATE());`,
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
// 一年內曾寄信過的顧客信箱陣列
|
|
250
|
-
let hasBless: string[] = [];
|
|
251
|
-
filteredData.map((item: { content: { email: string } }) => {
|
|
252
|
-
hasBless = hasBless.concat(item.content.email);
|
|
253
|
-
});
|
|
254
|
-
hasBless = [...new Set(hasBless)];
|
|
236
|
+
[]
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
// 篩選出一年內曾寄信過的顧客
|
|
240
|
+
const now = new Date();
|
|
241
|
+
const oneYearAgo = new Date(now);
|
|
242
|
+
oneYearAgo.setFullYear(now.getFullYear() - 1);
|
|
243
|
+
const filteredData = sendRecords.data.filter((item: { trigger_time: string }) => {
|
|
244
|
+
const triggerTime = new Date(item.trigger_time);
|
|
245
|
+
return triggerTime > oneYearAgo;
|
|
246
|
+
});
|
|
255
247
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
248
|
+
// 一年內曾寄信過的顧客信箱陣列
|
|
249
|
+
let hasBless: string[] = [];
|
|
250
|
+
filteredData.map((item: { content: { email: string } }) => {
|
|
251
|
+
hasBless = hasBless.concat(item.content.email);
|
|
252
|
+
});
|
|
253
|
+
hasBless = [...new Set(hasBless)];
|
|
254
|
+
|
|
255
|
+
// 進入寄信程序
|
|
256
|
+
for (const user of users) {
|
|
257
|
+
if (!hasBless.includes(user.userData.email)) {
|
|
258
|
+
await mailClass.postMail({
|
|
259
|
+
name: customerMail.name,
|
|
260
|
+
title: customerMail.title.replace(/@\{\{user_name\}\}/g, user.userData.name),
|
|
261
|
+
content: customerMail.content.replace(/@\{\{user_name\}\}/g, user.userData.name),
|
|
262
|
+
email: [user.userData.email],
|
|
263
|
+
type: mailType,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
272
266
|
}
|
|
267
|
+
}
|
|
273
268
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
269
|
+
} catch (e) {
|
|
270
|
+
console.error('BAD_REQUEST', 'birthBlessMail Error: ' + e, null);
|
|
271
|
+
}
|
|
277
272
|
}
|
|
278
273
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
274
|
+
setTimeout(() => this.birthBlessMail(sec), sec * 1000);
|
|
275
|
+
console.log(`birthBlessMail-Stop`, (new Date().getTime() - clock.getTime()) / 1000);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async resetVoucherHistory(sec: number) {
|
|
279
|
+
let clock = new Date();
|
|
280
|
+
console.log(`resetVoucherHistory`);
|
|
281
|
+
for (const app of Schedule.app) {
|
|
282
|
+
try {
|
|
283
|
+
if (await this.perload(app)) {
|
|
284
|
+
await new Shopping(app).resetVoucherHistory();
|
|
290
285
|
}
|
|
291
|
-
|
|
292
|
-
console.
|
|
286
|
+
} catch (e) {
|
|
287
|
+
console.error('BAD_REQUEST', 'resetVoucherHistory Error: ' + e, null);
|
|
288
|
+
}
|
|
293
289
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
290
|
+
setTimeout(() => this.resetVoucherHistory(sec), sec * 1000);
|
|
291
|
+
console.log(`resetVoucherHistory-Stop`, (new Date().getTime() - clock.getTime()) / 1000);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async autoSendMail(sec: number) {
|
|
295
|
+
let clock = new Date();
|
|
296
|
+
console.log(`autoSendLine`);
|
|
297
|
+
for (const app of Schedule.app) {
|
|
298
|
+
try {
|
|
299
|
+
if (await this.perload(app)) {
|
|
300
|
+
const emails = await db.query(
|
|
301
|
+
`SELECT * FROM \`${app}\`.t_triggers
|
|
303
302
|
WHERE
|
|
304
303
|
tag = 'sendMailBySchedule' AND
|
|
305
304
|
status = 0 AND
|
|
306
305
|
DATE_FORMAT(trigger_time, '%Y-%m-%d %H:%i') = DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i');`,
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
} catch (e) {
|
|
316
|
-
console.error('BAD_REQUEST', 'autoSendMail Error: ' + e, null);
|
|
306
|
+
[]
|
|
307
|
+
);
|
|
308
|
+
for (const email of emails) {
|
|
309
|
+
if (email.status === 0) {
|
|
310
|
+
new Mail(app).chunkSendMail(email.content, email.id);
|
|
317
311
|
}
|
|
312
|
+
}
|
|
318
313
|
}
|
|
319
|
-
|
|
320
|
-
console.
|
|
314
|
+
} catch (e) {
|
|
315
|
+
console.error('BAD_REQUEST', 'autoSendMail Error: ' + e, null);
|
|
316
|
+
}
|
|
321
317
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
318
|
+
setTimeout(() => this.autoSendMail(sec), sec * 1000);
|
|
319
|
+
console.log(`autoSendMail-Stop`, (new Date().getTime() - clock.getTime()) / 1000);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
async autoSendLine(sec: number) {
|
|
323
|
+
let clock = new Date();
|
|
324
|
+
console.log(`autoSendLine`);
|
|
325
|
+
for (const app of Schedule.app) {
|
|
326
|
+
try {
|
|
327
|
+
if (await this.perload(app)) {
|
|
328
|
+
const emails = await db.query(
|
|
329
|
+
`SELECT * FROM \`${app}\`.t_triggers
|
|
331
330
|
WHERE
|
|
332
331
|
tag = 'sendLineBySchedule' AND
|
|
333
332
|
DATE_FORMAT(trigger_time, '%Y-%m-%d %H:%i') = DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i');`,
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
} catch (e) {
|
|
352
|
-
console.error('BAD_REQUEST', 'autoSendLine Error: ' + e, null);
|
|
333
|
+
[]
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
for (const email of emails) {
|
|
337
|
+
if (email.status === 0) {
|
|
338
|
+
new LineMessage(app).chunkSendLine(
|
|
339
|
+
email.userList,
|
|
340
|
+
{
|
|
341
|
+
data: {
|
|
342
|
+
text: email.content,
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
email.id
|
|
346
|
+
);
|
|
353
347
|
}
|
|
348
|
+
}
|
|
354
349
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
async initialSampleApp(sec: number) {
|
|
361
|
-
await new InitialFakeData(`t_1725992531001`).run();
|
|
362
|
-
setTimeout(() => this.initialSampleApp(sec), sec * 1000);
|
|
350
|
+
} catch (e) {
|
|
351
|
+
console.error('BAD_REQUEST', 'autoSendLine Error: ' + e, null);
|
|
352
|
+
}
|
|
363
353
|
}
|
|
364
354
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
}
|
|
355
|
+
setTimeout(() => this.autoSendLine(sec), sec * 1000);
|
|
356
|
+
console.log(`autoSendLine-Stop`, (new Date().getTime() - clock.getTime()) / 1000);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
async initialSampleApp(sec: number) {
|
|
360
|
+
await new InitialFakeData('t_1725992531001').run();
|
|
361
|
+
setTimeout(() => this.initialSampleApp(sec), sec * 1000);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
async currenciesUpdate(sec: number) {
|
|
365
|
+
const date = new Date();
|
|
366
|
+
const date_index = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
|
|
367
|
+
let clock = new Date();
|
|
368
|
+
console.log(`currenciesUpdate-Start`);
|
|
369
|
+
if (
|
|
370
|
+
(
|
|
371
|
+
await db.query(
|
|
372
|
+
`select count(1) from \`${saasConfig.SAAS_NAME}\`.currency_config where updated='${date_index}'`,
|
|
373
|
+
[]
|
|
374
|
+
)
|
|
375
|
+
)[0]['count(1)'] === 0
|
|
376
|
+
) {
|
|
377
|
+
let config = {
|
|
378
|
+
method: 'get',
|
|
379
|
+
maxBodyLength: Infinity,
|
|
380
|
+
url: 'https://data.fixer.io/api/latest?access_key=0ced797dd1cc136b22d6cfee7e2d6476',
|
|
381
|
+
headers: {},
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
axios
|
|
385
|
+
.request(config)
|
|
386
|
+
.then(async (response: any) => {
|
|
387
|
+
await db.query(`insert into \`${saasConfig.SAAS_NAME}\`.currency_config (\`json\`,updated) values (?,?)`, [
|
|
388
|
+
JSON.stringify(response.data),
|
|
389
|
+
date_index,
|
|
390
|
+
]);
|
|
391
|
+
setTimeout(() => this.currenciesUpdate(sec), sec * 1000);
|
|
392
|
+
})
|
|
393
|
+
.catch((error: any) => {
|
|
394
|
+
console.error(error);
|
|
395
|
+
setTimeout(() => this.currenciesUpdate(sec), sec * 1000);
|
|
396
|
+
});
|
|
397
|
+
} else {
|
|
398
|
+
setTimeout(() => this.currenciesUpdate(sec), sec * 1000);
|
|
399
|
+
console.log(`currenciesUpdate-Stop`, (new Date().getTime() - clock.getTime()) / 1000);
|
|
392
400
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
});
|
|
413
|
-
} catch (e) {
|
|
414
|
-
throw exception.BadRequestError('BAD_REQUEST', 'Init Schedule Error: ' + e, null);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
main() {
|
|
404
|
+
const scheduleList: ScheduleItem[] = [
|
|
405
|
+
// { second: 10, status: false, func: 'example', desc: '排程啟用範例' },
|
|
406
|
+
{ second: 3600, status: true, func: 'birthRebate', desc: '生日禮發放購物金' },
|
|
407
|
+
{ second: 3600, status: true, func: 'birthBlessMail', desc: '生日祝福信件' },
|
|
408
|
+
{ second: 600, status: true, func: 'renewMemberLevel', desc: '更新會員分級' },
|
|
409
|
+
{ second: 30, status: true, func: 'resetVoucherHistory', desc: '未付款歷史優惠券重設' },
|
|
410
|
+
{ second: 30, status: true, func: 'autoSendMail', desc: '自動排程寄送信件' },
|
|
411
|
+
{ second: 30, status: true, func: 'autoSendLine', desc: '自動排程寄送line訊息' },
|
|
412
|
+
{ second: 3600 * 24, status: true, func: 'currenciesUpdate', desc: '多國貨幣的更新排程' },
|
|
413
|
+
// { second: 3600 * 24, status: false, func: 'initialSampleApp', desc: '重新刷新示範商店' },
|
|
414
|
+
{ second: 30, status: true, func: 'autoCancelOrder', desc: '自動取消未付款未出貨訂單' },
|
|
415
|
+
];
|
|
416
|
+
try {
|
|
417
|
+
scheduleList.forEach(schedule => {
|
|
418
|
+
if (schedule.status && typeof this[schedule.func] === 'function') {
|
|
419
|
+
(this[schedule.func] as (sec: number) => void)(schedule.second);
|
|
415
420
|
}
|
|
421
|
+
});
|
|
422
|
+
} catch (e) {
|
|
423
|
+
throw exception.BadRequestError('BAD_REQUEST', 'Init Schedule Error: ' + e, null);
|
|
416
424
|
}
|
|
425
|
+
}
|
|
417
426
|
}
|