@etsoo/appscript 1.3.89 → 1.3.91
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/__tests__/app/CoreApp.ts +15 -0
- package/lib/cjs/app/CoreApp.d.ts +3 -1
- package/lib/cjs/app/CoreApp.js +5 -2
- package/lib/cjs/app/IApp.d.ts +3 -1
- package/lib/cjs/business/EntityStatus.d.ts +5 -1
- package/lib/cjs/business/EntityStatus.js +5 -1
- package/lib/cjs/business/ShoppingCart.d.ts +285 -0
- package/lib/cjs/business/ShoppingCart.js +306 -0
- package/lib/cjs/i18n/en.json +1 -0
- package/lib/cjs/i18n/zh-Hans.json +1 -0
- package/lib/cjs/i18n/zh-Hant.json +1 -0
- package/lib/cjs/index.d.ts +1 -0
- package/lib/cjs/index.js +1 -0
- package/lib/mjs/app/CoreApp.d.ts +3 -1
- package/lib/mjs/app/CoreApp.js +5 -2
- package/lib/mjs/app/IApp.d.ts +3 -1
- package/lib/mjs/business/EntityStatus.d.ts +5 -1
- package/lib/mjs/business/EntityStatus.js +5 -1
- package/lib/mjs/business/ShoppingCart.d.ts +285 -0
- package/lib/mjs/business/ShoppingCart.js +302 -0
- package/lib/mjs/i18n/en.json +1 -0
- package/lib/mjs/i18n/zh-Hans.json +1 -0
- package/lib/mjs/i18n/zh-Hant.json +1 -0
- package/lib/mjs/index.d.ts +1 -0
- package/lib/mjs/index.js +1 -0
- package/package.json +2 -2
- package/src/app/CoreApp.ts +9 -2
- package/src/app/IApp.ts +3 -1
- package/src/business/EntityStatus.ts +6 -1
- package/src/business/ShoppingCart.ts +524 -0
- package/src/i18n/en.json +1 -0
- package/src/i18n/zh-Hans.json +1 -0
- package/src/i18n/zh-Hant.json +1 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { NumberUtils, WindowStorage } from '@etsoo/shared';
|
|
2
|
+
/**
|
|
3
|
+
* Shopping cart
|
|
4
|
+
* 购物篮
|
|
5
|
+
*/
|
|
6
|
+
export class ShoppingCart {
|
|
7
|
+
/**
|
|
8
|
+
* Create identifier key
|
|
9
|
+
* 创建识别键
|
|
10
|
+
* @param currency Currency
|
|
11
|
+
* @returns Result
|
|
12
|
+
*/
|
|
13
|
+
static createKey(currency) {
|
|
14
|
+
return `ETSOO-CART-${currency}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Clear shopping cart
|
|
18
|
+
* 清除购物篮
|
|
19
|
+
* @param identifier Identifier
|
|
20
|
+
* @param storage Storage
|
|
21
|
+
*/
|
|
22
|
+
static clear(identifier, storage) {
|
|
23
|
+
try {
|
|
24
|
+
storage.setData(identifier, null);
|
|
25
|
+
storage.setPersistedData(identifier, null);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
console.log('ShoppingCart clear', error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Clear shopping cart
|
|
33
|
+
* 清除购物篮
|
|
34
|
+
* @param currency Currency
|
|
35
|
+
* @param storage Storage
|
|
36
|
+
*/
|
|
37
|
+
static clearWith(currency, storage = new WindowStorage()) {
|
|
38
|
+
const identifier = this.createKey(currency);
|
|
39
|
+
this.clear(identifier, storage);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Lines count
|
|
43
|
+
* 项目数量
|
|
44
|
+
*/
|
|
45
|
+
get lines() {
|
|
46
|
+
return this.items.length;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Total qty
|
|
50
|
+
* 总数量
|
|
51
|
+
*/
|
|
52
|
+
get totalQty() {
|
|
53
|
+
return this.items.map((item) => item.qty).sum();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Total amount
|
|
57
|
+
* 总金额
|
|
58
|
+
*/
|
|
59
|
+
get totalAmount() {
|
|
60
|
+
const subtotal = this.items
|
|
61
|
+
.map((item) => item.subtotal - item.discount)
|
|
62
|
+
.sum();
|
|
63
|
+
const discount = this.promotions.sum('amount');
|
|
64
|
+
return subtotal - discount;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Total amount string
|
|
68
|
+
* 总金额字符串
|
|
69
|
+
*/
|
|
70
|
+
get totalAmountStr() {
|
|
71
|
+
return this.formatAmount(this.totalAmount);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Constructor
|
|
75
|
+
* 构造函数
|
|
76
|
+
* @param currency Currency ISO code
|
|
77
|
+
* @param storage Data storage
|
|
78
|
+
* @param state Initialization state
|
|
79
|
+
*/
|
|
80
|
+
constructor(currencyOrState, storage = new WindowStorage()) {
|
|
81
|
+
var _a;
|
|
82
|
+
this.storage = storage;
|
|
83
|
+
/**
|
|
84
|
+
* Cached prices
|
|
85
|
+
* 缓存的价格
|
|
86
|
+
*/
|
|
87
|
+
this.prices = {};
|
|
88
|
+
const isCurrency = typeof currencyOrState === 'string';
|
|
89
|
+
this.currency = isCurrency ? currencyOrState : currencyOrState.currency;
|
|
90
|
+
const key = ShoppingCart.createKey(this.currency);
|
|
91
|
+
this.identifier = key;
|
|
92
|
+
this.symbol = NumberUtils.getCurrencySymbol(this.currency);
|
|
93
|
+
let state;
|
|
94
|
+
if (isCurrency) {
|
|
95
|
+
try {
|
|
96
|
+
state =
|
|
97
|
+
(_a = storage.getPersistedObject(key)) !== null && _a !== void 0 ? _a : storage.getObject(key);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
console.log('ShoppingCart constructor', error);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
state = currencyOrState;
|
|
105
|
+
}
|
|
106
|
+
const { owner, items = [], promotions = [], formData } = state !== null && state !== void 0 ? state : {};
|
|
107
|
+
this.owner = owner;
|
|
108
|
+
this.items = items;
|
|
109
|
+
this.promotions = promotions;
|
|
110
|
+
this.formData = formData;
|
|
111
|
+
}
|
|
112
|
+
doChange(reason, changedItems) {
|
|
113
|
+
if (this.onChange)
|
|
114
|
+
this.onChange(reason, changedItems);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Add item
|
|
118
|
+
* 添加项目
|
|
119
|
+
* @param item New item
|
|
120
|
+
*/
|
|
121
|
+
addItem(item) {
|
|
122
|
+
this.addItems([item]);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Add items
|
|
126
|
+
* @param items New items
|
|
127
|
+
*/
|
|
128
|
+
addItems(items) {
|
|
129
|
+
this.items.push(...items);
|
|
130
|
+
this.doChange('add', items);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Cache price
|
|
134
|
+
* @param id Item id
|
|
135
|
+
* @param price Price
|
|
136
|
+
*/
|
|
137
|
+
cachePrice(id, price) {
|
|
138
|
+
this.prices[id] = price;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Clear storage
|
|
142
|
+
* @param keepOwner Keep owner data
|
|
143
|
+
*/
|
|
144
|
+
clear(keepOwner) {
|
|
145
|
+
this.items.length = 0;
|
|
146
|
+
this.promotions.length = 0;
|
|
147
|
+
if (keepOwner) {
|
|
148
|
+
this.save();
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
ShoppingCart.clear(this.identifier, this.storage);
|
|
152
|
+
}
|
|
153
|
+
this.doChange('clear', []);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Format amount
|
|
157
|
+
* @param amount Amount
|
|
158
|
+
* @returns Result
|
|
159
|
+
*/
|
|
160
|
+
formatAmount(amount) {
|
|
161
|
+
return NumberUtils.formatMoney(amount, this.currency);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get item
|
|
165
|
+
* @param id Item id
|
|
166
|
+
* @returns Result
|
|
167
|
+
*/
|
|
168
|
+
getItem(id) {
|
|
169
|
+
return this.items.find((item) => item.id === id);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Reset
|
|
173
|
+
* @param item Shopping cart item
|
|
174
|
+
*/
|
|
175
|
+
reset(item) {
|
|
176
|
+
item.discount = 0;
|
|
177
|
+
item.currentPrice = undefined;
|
|
178
|
+
item.promotions = [];
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Save cart data
|
|
182
|
+
* @param persisted For persisted storage
|
|
183
|
+
*/
|
|
184
|
+
save(persisted = true) {
|
|
185
|
+
if (this.owner == null)
|
|
186
|
+
return;
|
|
187
|
+
const { currency, owner, items, promotions, formData } = this;
|
|
188
|
+
const data = {
|
|
189
|
+
currency,
|
|
190
|
+
owner,
|
|
191
|
+
items,
|
|
192
|
+
promotions,
|
|
193
|
+
formData
|
|
194
|
+
};
|
|
195
|
+
try {
|
|
196
|
+
if (persisted) {
|
|
197
|
+
this.storage.setPersistedData(this.identifier, data);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
this.storage.setData(this.identifier, data);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
console.log('ShoppingCart save', error);
|
|
205
|
+
}
|
|
206
|
+
return data;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Trigger update
|
|
210
|
+
* 触发更新
|
|
211
|
+
*/
|
|
212
|
+
update() {
|
|
213
|
+
this.doChange('update', []);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Update discount
|
|
217
|
+
* @param item Shopping cart item
|
|
218
|
+
*/
|
|
219
|
+
updateDiscount(item) {
|
|
220
|
+
item.discount = item.promotions.sum('amount');
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Update item
|
|
224
|
+
* 更新项目
|
|
225
|
+
* @param id Product id
|
|
226
|
+
* @param qty Qty
|
|
227
|
+
* @param itemCreator New item creator
|
|
228
|
+
* @returns Updated or not
|
|
229
|
+
*/
|
|
230
|
+
updateItem(id, qty, itemCreator) {
|
|
231
|
+
const index = this.items.findIndex((item) => item.id === id);
|
|
232
|
+
if (qty == null) {
|
|
233
|
+
// Remove the item
|
|
234
|
+
if (index !== -1) {
|
|
235
|
+
const removedItems = this.items.splice(index, 1);
|
|
236
|
+
this.doChange('remove', removedItems);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
else if (index === -1) {
|
|
240
|
+
// New
|
|
241
|
+
if (itemCreator) {
|
|
242
|
+
const price = this.prices[id];
|
|
243
|
+
const newItem = {
|
|
244
|
+
...itemCreator(),
|
|
245
|
+
id,
|
|
246
|
+
price,
|
|
247
|
+
qty,
|
|
248
|
+
subtotal: price * qty,
|
|
249
|
+
discount: 0
|
|
250
|
+
};
|
|
251
|
+
this.addItem(newItem);
|
|
252
|
+
}
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
// Update
|
|
257
|
+
const item = this.items[index];
|
|
258
|
+
const price = item.price;
|
|
259
|
+
const newItem = {
|
|
260
|
+
...item,
|
|
261
|
+
qty,
|
|
262
|
+
subtotal: price * qty,
|
|
263
|
+
discount: 0
|
|
264
|
+
};
|
|
265
|
+
this.items.splice(index, 1, newItem);
|
|
266
|
+
this.doChange('update', [item, newItem]);
|
|
267
|
+
}
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Update price
|
|
272
|
+
* @param id Item id
|
|
273
|
+
* @param price New price
|
|
274
|
+
*/
|
|
275
|
+
updatePrice(id, price) {
|
|
276
|
+
this.cachePrice(id, price);
|
|
277
|
+
const index = this.items.findIndex((item) => item.id === id);
|
|
278
|
+
if (index !== -1) {
|
|
279
|
+
const item = this.items[index];
|
|
280
|
+
const qty = item.qty;
|
|
281
|
+
const newItem = { ...item, price, subtotal: price * qty };
|
|
282
|
+
this.items.splice(index, 1, newItem);
|
|
283
|
+
this.doChange('update', [item, newItem]);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Update title
|
|
288
|
+
* @param id Item id
|
|
289
|
+
* @param title New title
|
|
290
|
+
*/
|
|
291
|
+
updateTitle(id, title) {
|
|
292
|
+
const index = this.items.findIndex((item) => item.id === id);
|
|
293
|
+
if (index !== -1) {
|
|
294
|
+
const item = this.items[index];
|
|
295
|
+
const newItem = { ...item, title };
|
|
296
|
+
if (newItem.name === newItem.title)
|
|
297
|
+
newItem.title = undefined;
|
|
298
|
+
this.items.splice(index, 1, newItem);
|
|
299
|
+
this.doChange('title', [item, newItem]);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
package/lib/mjs/i18n/en.json
CHANGED
package/lib/mjs/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export * from './business/DataPrivacy';
|
|
|
22
22
|
export * from './business/EntityStatus';
|
|
23
23
|
export * from './business/ProductUnit';
|
|
24
24
|
export * from './business/RepeatOption';
|
|
25
|
+
export * from './business/ShoppingCart';
|
|
25
26
|
export * from './def/ListItem';
|
|
26
27
|
export * from './erp/dto/AuditLineDto';
|
|
27
28
|
export * from './erp/dto/CurrencyDto';
|
package/lib/mjs/index.js
CHANGED
|
@@ -26,6 +26,7 @@ export * from './business/DataPrivacy';
|
|
|
26
26
|
export * from './business/EntityStatus';
|
|
27
27
|
export * from './business/ProductUnit';
|
|
28
28
|
export * from './business/RepeatOption';
|
|
29
|
+
export * from './business/ShoppingCart';
|
|
29
30
|
// def
|
|
30
31
|
export * from './def/ListItem';
|
|
31
32
|
// erp dto
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/appscript",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.91",
|
|
4
4
|
"description": "Applications shared TypeScript framework",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/mjs/index.js",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@etsoo/notificationbase": "^1.1.24",
|
|
56
56
|
"@etsoo/restclient": "^1.0.87",
|
|
57
|
-
"@etsoo/shared": "^1.
|
|
57
|
+
"@etsoo/shared": "^1.2.0",
|
|
58
58
|
"@types/crypto-js": "^4.1.1",
|
|
59
59
|
"crypto-js": "^4.1.1"
|
|
60
60
|
},
|
package/src/app/CoreApp.ts
CHANGED
|
@@ -1319,10 +1319,17 @@ export abstract class CoreApp<
|
|
|
1319
1319
|
|
|
1320
1320
|
/**
|
|
1321
1321
|
* Get status list
|
|
1322
|
+
* @param ids Limited ids
|
|
1322
1323
|
* @returns list
|
|
1323
1324
|
*/
|
|
1324
|
-
getStatusList() {
|
|
1325
|
-
return this.getEnumList(
|
|
1325
|
+
getStatusList(ids: EntityStatus[] = []) {
|
|
1326
|
+
return this.getEnumList(
|
|
1327
|
+
EntityStatus,
|
|
1328
|
+
'status',
|
|
1329
|
+
ids.length > 0
|
|
1330
|
+
? (id, _key) => (ids.includes(id) ? id : undefined)
|
|
1331
|
+
: undefined
|
|
1332
|
+
);
|
|
1326
1333
|
}
|
|
1327
1334
|
|
|
1328
1335
|
/**
|
package/src/app/IApp.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { IActionResult } from '../result/IActionResult';
|
|
|
18
18
|
import { IUser } from '../state/User';
|
|
19
19
|
import { IAppSettings } from './AppSettings';
|
|
20
20
|
import { UserRole } from './UserRole';
|
|
21
|
+
import { EntityStatus } from '../business/EntityStatus';
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Detect IP callback interface
|
|
@@ -466,9 +467,10 @@ export interface IApp {
|
|
|
466
467
|
|
|
467
468
|
/**
|
|
468
469
|
* Get status list
|
|
470
|
+
* @param ids Limited ids
|
|
469
471
|
* @returns list
|
|
470
472
|
*/
|
|
471
|
-
getStatusList(): ListType[];
|
|
473
|
+
getStatusList(ids?: EntityStatus[]): ListType[];
|
|
472
474
|
|
|
473
475
|
/**
|
|
474
476
|
* Get refresh token from response headers
|