@chiper-inc/ecommerce-lib
Version:
Chiper Inc Ecommerce Lib
192 lines (178 loc) • 4.56 kB
text/typescript
import { Price } from "./price";
import { Item, ItemType } from "./item";
import { Product, Measurement } from "./product";
import { Promotion } from "./promotion";
import { ItemQuantityError } from "./itemQuantityError";
import { New } from './new';
import { MaxQuantityHelper } from './helpers';
type CartOptions = {
items: Item[];
storeId: number;
warehouseId: number;
locationId: number;
status: "OK" | "IN_PROGRESS";
rate?: number
};
class Cart {
private _items: Item[];
private _rate: number;
public readonly storeId: number;
public readonly warehouseId: number;
public readonly locationId: number;
public readonly status: "OK" | "IN_PROGRESS";
public news: New[] = [];
constructor({
items,
storeId,
warehouseId,
status,
locationId,
rate
}: CartOptions) {
this._items = items;
this.storeId = storeId;
this.warehouseId = warehouseId;
this.status = status;
this.locationId = locationId;
this._rate = 1
if (rate) {
this._rate = rate;
}
}
get rate(): number {
return this._rate;
}
get items(): Item[] {
return this._items;
}
get totalDollars(): number{
return +this.items
.reduce((total: number, item: Item) => total + (item.totalDollars ?? 0), 0)
.toFixed(2);
}
get total(): number {
return +this.items
.reduce((total: number, item: Item) => total + (item.total ?? 0), 0)
.toFixed(2);
}
get subtotal(): number {
return +this.items
.reduce(
(subtotal: number, item: Item) => subtotal + (item.subtotal ?? 0),
0
)
.toFixed(2);
}
removeItem(id: number | string) {
this._items = this._items.filter((item) => item.id !== id);
}
addItem(item: Item) {
this._items.push(item);
}
get margin(): number {
const profit = +this.items
.reduce((total: number, item: Item) =>
((item.price - item.chiperPrice) * (item.quantity || 0) + total),
0);
return +(profit / this.subtotal).toFixed(2);
}
getCartForWarehouse(warehouseId: number): Cart {
return new Cart({
items: this.itemsByWarehouseId(warehouseId),
storeId: this.storeId,
warehouseId: warehouseId,
status: this.status,
locationId: this.locationId,
});
}
itemsByWarehouseId(warehouseId: number): Item[]{
return this._items.filter((item) => item.warehouseId === warehouseId)
}
/* eslint-disable @typescript-eslint/no-explicit-any */
static from({ items, storeId, warehouseId, status, locationId }: any, rate:number, isBackend?: boolean, isOffline?: boolean): Cart {
return new Cart({
items: items.map((itemRaw: any) => {
let item: Item;
switch (itemRaw.type) {
case ItemType.PRODUCT:
{
item = Product.from(itemRaw, rate, isBackend, isOffline);
break;
}
case ItemType.COMBO:
item = Promotion.from(itemRaw, rate);
break;
default:
throw new Error("invalid productType: " + itemRaw.productType);
}
return item;
}),
storeId,
warehouseId,
status,
locationId,
rate
});
}
static fromShopCart({
carts,
storeId,
warehouseId,
status,
locationId,
rate
}: any): Cart {
return new Cart({
items: carts[0].items.map((itemRaw: any) => {
let item: Item;
switch (itemRaw.productType) {
case ItemType.PRODUCT:
{
item = Product.fromShopCart(
Object.assign({}, itemRaw, { prices: itemRaw.products[0].prices }),
rate
);
break;
}
case ItemType.COMBO:
item = Promotion.fromShopCart(itemRaw, rate);
break;
default:
throw new Error("invalid productType: " + itemRaw.productType);
}
return item;
}),
storeId,
warehouseId,
status,
locationId,
rate
});
}
// toJSON function
toJSON() {
return {
items: this.items.map((item) => item.toJSON()),
storeId: this.storeId,
warehouseId: this.warehouseId,
status: this.status,
locationId: this.locationId,
total: this.total,
totalDollars: this.totalDollars,
subtotal: this.subtotal,
news: this.news,
rate: this.rate
};
}
}
export {
Price,
Item,
Product,
Promotion,
Cart,
CartOptions,
ItemQuantityError,
Measurement,
MaxQuantityHelper,
};