@etsoo/appscript 1.3.90 → 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.
@@ -0,0 +1,285 @@
1
+ import { DataTypes, IStorage } from '@etsoo/shared';
2
+ /**
3
+ * Shopping cart owner
4
+ * 购物篮所有人
5
+ */
6
+ export type ShoppingCartOwner = DataTypes.IdNameItem & {
7
+ isSupplier?: boolean;
8
+ };
9
+ /**
10
+ * Shopping cart data
11
+ * 购物篮数据
12
+ */
13
+ export type ShoppingCartData<T extends ShoppingCartItem> = {
14
+ currency: string;
15
+ owner: ShoppingCartOwner;
16
+ items: T[];
17
+ promotions: ShoppingPromotion[];
18
+ formData?: any;
19
+ };
20
+ /**
21
+ * Shopping promotion
22
+ * 购物促销
23
+ */
24
+ export type ShoppingPromotion = {
25
+ /**
26
+ * Promotion id
27
+ * 促销编号
28
+ */
29
+ id: number;
30
+ /**
31
+ * Promotion title
32
+ * 促销标题
33
+ */
34
+ title: string;
35
+ /**
36
+ * Discount amount
37
+ * 折扣金额
38
+ */
39
+ amount: number;
40
+ };
41
+ /**
42
+ * Shopping cart base item
43
+ * 购物篮基础项目
44
+ */
45
+ export type ShoppingCartItemBase = {
46
+ /**
47
+ * Product id
48
+ * 产品编号
49
+ */
50
+ id: DataTypes.IdType;
51
+ /**
52
+ * Product title, default is name
53
+ * 产品标题,默认为name
54
+ */
55
+ title?: string;
56
+ /**
57
+ * Sale price
58
+ * 销售价格
59
+ */
60
+ price: number;
61
+ /**
62
+ * Qty
63
+ * 数量
64
+ */
65
+ qty: number;
66
+ /**
67
+ * Product level promotions
68
+ * 产品层次促销
69
+ */
70
+ promotions: ShoppingPromotion[];
71
+ };
72
+ /**
73
+ * Shopping cart item
74
+ * 购物篮项目
75
+ */
76
+ export type ShoppingCartItem = ShoppingCartItemBase & {
77
+ /**
78
+ * Product name
79
+ * 产品名称
80
+ */
81
+ name: string;
82
+ /**
83
+ * Current price for cache
84
+ * 当前缓存价格
85
+ */
86
+ currentPrice?: number;
87
+ /**
88
+ * Subtotal
89
+ * 小计
90
+ */
91
+ subtotal: number;
92
+ /**
93
+ * Total discount amount
94
+ * 总折扣金额
95
+ */
96
+ discount: number;
97
+ };
98
+ /**
99
+ * Shopping cart change reason
100
+ * 购物篮改变原因
101
+ */
102
+ export type ShoppingCartChangeReason = 'add' | 'clear' | 'remove' | 'title' | 'update';
103
+ /**
104
+ * Shopping cart
105
+ * 购物篮
106
+ */
107
+ export declare class ShoppingCart<T extends ShoppingCartItem> {
108
+ private readonly storage;
109
+ /**
110
+ * Create identifier key
111
+ * 创建识别键
112
+ * @param currency Currency
113
+ * @returns Result
114
+ */
115
+ static createKey(currency: string): string;
116
+ /**
117
+ * Clear shopping cart
118
+ * 清除购物篮
119
+ * @param identifier Identifier
120
+ * @param storage Storage
121
+ */
122
+ static clear(identifier: string, storage: IStorage): void;
123
+ /**
124
+ * Clear shopping cart
125
+ * 清除购物篮
126
+ * @param currency Currency
127
+ * @param storage Storage
128
+ */
129
+ static clearWith(currency: string, storage?: IStorage): void;
130
+ /**
131
+ * Owner data
132
+ * 所有者信息
133
+ */
134
+ owner?: ShoppingCartOwner;
135
+ /**
136
+ * ISO currency id
137
+ * 标准货币编号
138
+ */
139
+ readonly currency: string;
140
+ /**
141
+ * Items
142
+ * 项目
143
+ */
144
+ readonly items: T[];
145
+ /**
146
+ * Order level promotions
147
+ * 订单层面促销
148
+ */
149
+ readonly promotions: ShoppingPromotion[];
150
+ /**
151
+ * Related form data
152
+ * 关联的表单数据
153
+ */
154
+ formData: any;
155
+ /**
156
+ * Currency symbol
157
+ * 币种符号
158
+ */
159
+ readonly symbol: string | undefined;
160
+ /**
161
+ * Cart identifier
162
+ * 购物篮标识
163
+ */
164
+ private readonly identifier;
165
+ /**
166
+ * Lines count
167
+ * 项目数量
168
+ */
169
+ get lines(): number;
170
+ /**
171
+ * Total qty
172
+ * 总数量
173
+ */
174
+ get totalQty(): number;
175
+ /**
176
+ * Total amount
177
+ * 总金额
178
+ */
179
+ get totalAmount(): number;
180
+ /**
181
+ * Total amount string
182
+ * 总金额字符串
183
+ */
184
+ get totalAmountStr(): string;
185
+ /**
186
+ * Cached prices
187
+ * 缓存的价格
188
+ */
189
+ private readonly prices;
190
+ /**
191
+ * Onchange callback
192
+ * 改变时回调
193
+ */
194
+ onChange?: (reason: ShoppingCartChangeReason, changedItems: T[]) => void;
195
+ /**
196
+ * Constructor
197
+ * 构造函数
198
+ * @param currency Currency ISO code
199
+ * @param storage Data storage
200
+ */
201
+ constructor(currency: string, storage?: IStorage);
202
+ /**
203
+ * Constructor
204
+ * 构造函数
205
+ * @param state Initialization state
206
+ * @param storage Data storage
207
+ */
208
+ constructor(state: ShoppingCartData<T>, storage?: IStorage);
209
+ private doChange;
210
+ /**
211
+ * Add item
212
+ * 添加项目
213
+ * @param item New item
214
+ */
215
+ addItem(item: T): void;
216
+ /**
217
+ * Add items
218
+ * @param items New items
219
+ */
220
+ addItems(items: T[]): void;
221
+ /**
222
+ * Cache price
223
+ * @param id Item id
224
+ * @param price Price
225
+ */
226
+ cachePrice(id: T['id'], price: number): void;
227
+ /**
228
+ * Clear storage
229
+ * @param keepOwner Keep owner data
230
+ */
231
+ clear(keepOwner?: boolean): void;
232
+ /**
233
+ * Format amount
234
+ * @param amount Amount
235
+ * @returns Result
236
+ */
237
+ formatAmount(amount: number): string;
238
+ /**
239
+ * Get item
240
+ * @param id Item id
241
+ * @returns Result
242
+ */
243
+ getItem(id: T['id']): T | undefined;
244
+ /**
245
+ * Reset
246
+ * @param item Shopping cart item
247
+ */
248
+ reset(item: ShoppingCartItem): void;
249
+ /**
250
+ * Save cart data
251
+ * @param persisted For persisted storage
252
+ */
253
+ save(persisted?: boolean): ShoppingCartData<T> | undefined;
254
+ /**
255
+ * Trigger update
256
+ * 触发更新
257
+ */
258
+ update(): void;
259
+ /**
260
+ * Update discount
261
+ * @param item Shopping cart item
262
+ */
263
+ updateDiscount(item: ShoppingCartItem): void;
264
+ /**
265
+ * Update item
266
+ * 更新项目
267
+ * @param id Product id
268
+ * @param qty Qty
269
+ * @param itemCreator New item creator
270
+ * @returns Updated or not
271
+ */
272
+ updateItem(id: T['id'], qty: number | undefined, itemCreator?: () => Omit<T, 'id' | 'price' | 'qty' | 'subtotal' | 'discount' | 'promotions'>): boolean;
273
+ /**
274
+ * Update price
275
+ * @param id Item id
276
+ * @param price New price
277
+ */
278
+ updatePrice(id: T['id'], price: number): void;
279
+ /**
280
+ * Update title
281
+ * @param id Item id
282
+ * @param title New title
283
+ */
284
+ updateTitle(id: T['id'], title: string): void;
285
+ }
@@ -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
+ }
@@ -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.90",
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",