@chiper-inc/ecommerce-lib
Version:
Chiper Inc Ecommerce Lib
222 lines (210 loc) • 6.29 kB
text/typescript
import { EventSender, CartEvent } from "../event";
import {
getDiscount,
getMaximumValue,
roundToMultipleQuantity,
} from "./helpers";
import { ItemQuantityError } from "./itemQuantityError";
import { New } from './new';
export enum ItemType {
PRODUCT = "PRODUCT",
COMBO = "COMBO",
}
export type ItemOptions = {
id: number | string;
warehouseId: number;
name: string;
stock: number;
image: string;
packagingType: string;
minQuantity?: number;
multipleQuantity?: number;
quantity?: number;
measurement:{unit:string, quantity:number}
};
export abstract class Item extends EventSender {
public readonly id: number | string;
public readonly warehouseId: number;
public readonly type: ItemType;
public readonly name: string;
protected _quantity?: number;
protected _stock: number;
public readonly image: string;
public readonly packagingType: string;
public readonly minQuantity: number;
public readonly multipleQuantity: number;
public readonly rate: number;
private isBackend:boolean | undefined;
private isOffline: boolean | undefined;
constructor(
type: ItemType,
{
stock,
multipleQuantity,
name,
image,
id,
warehouseId,
packagingType,
minQuantity,
measurement
}: ItemOptions, rate:number, isBackend?: boolean, isOffline?: boolean
) {
super();
this.isOffline = isOffline;
this.isBackend = isBackend;
this.id = id;
this.warehouseId = warehouseId;
this.type = type;
this.name = name;
this._stock = stock;
this.image = image;
let complementPackaging = '';
if (measurement && measurement.quantity && measurement.unit) {
complementPackaging = `${measurement.quantity} ${measurement.unit}`
complementPackaging = packagingType.includes(complementPackaging) ? '' : ` ${complementPackaging}`;
}
this.packagingType = `${packagingType}${complementPackaging}`;
this.minQuantity = minQuantity ?? 1;
this.multipleQuantity = multipleQuantity ?? 1;
this.rate = rate;
}
get stock(): number {
return this._stock;
}
set stock(stock: number) {
this._stock = stock;
if (this.quantity && this.stock < this.quantity) {
this.emit(CartEvent.NEWS, {
id: this.id,
cardType: this.stock === 0 ? "unavailable" : "lowStock",
productType: this.type,
medium: this.image,
name: this.name,
packagingType: this.packagingType,
previousTotal: this.regularPrice,
quantity: this.quantity,
stock: this.stock,
total: this.regularPrice,
warehouseId: this.warehouseId
} as New);
}
}
abstract clone(): Item;
set quantity(quantity: number | undefined) {
if(quantity == null) {
this._quantity = undefined;
return;
}
if (quantity < this.minQuantity && !this.isOffline) {
this.emit(CartEvent.BELOW_MIN_QUANTITY, {
id: this.id,
quantity: quantity,
minQuantity: this.minQuantity,
});
throw new ItemQuantityError(
`Quantity can't be less than minQuantity(${this.minQuantity})`,
this.minQuantity,
"MinQuantity"
);
}
if (quantity > this.stock && !this.isOffline) {
const newQuantity = getMaximumValue(
this.stock,
this.maxQuantity ?? this.stock,
this.multipleQuantity
);
this.emit(CartEvent.OUT_OF_STOCK, {
id: this.id,
quantity: quantity,
stock: this.stock,
});
throw new ItemQuantityError(
`Quantity can't be more than stock(${this.stock})`,
newQuantity,
"Stock"
);
}
if (this.maxQuantity && quantity > this.maxQuantity && !this.isOffline) {
const newQuantity = getMaximumValue(
this.stock,
this.maxQuantity,
this.multipleQuantity
);
if (this.isBackend === true) {
this.quantity = newQuantity;
}else{
this.emit(CartEvent.EXCEEDS_MAX_QUANTITY, {
id: this.id,
quantity: quantity,
maxQuantity: this.maxQuantity,
});
throw new ItemQuantityError(
`Quantity can't be more than maxQuantity(${this.maxQuantity})`,
newQuantity,
"MaxQuantity"
);
}
}
if (quantity % this.multipleQuantity !== 0 && !this.isOffline) {
const newQuantity = roundToMultipleQuantity(
quantity,
this.multipleQuantity,
this.stock
);
this.emit(CartEvent.NOT_MULTIPLE_QUANTITY, {
id: this.id,
quantity: quantity,
multipleQuantity: this.multipleQuantity,
});
throw new ItemQuantityError(
`Quantity can't be different of a multipleQuantity(${this.multipleQuantity})`,
newQuantity,
"MultipleQuantity"
);
}
this._quantity = quantity;
}
get quantity(): number | undefined{
return this._quantity;
}
/** `discount` is the difference between `regularPrice` and `discountedPrice` in %*/
get discount(): number {
return this.discountedPrice
? getDiscount(this.regularPrice, this.discountedPrice)
: 0;
}
abstract get maxQuantity(): number | undefined;
abstract get regularPrice(): number;
abstract get discountedPrice(): number | undefined;
abstract get total(): number | null;
abstract get subtotal(): number | null;
abstract get chiperPrice(): number;
abstract get price(): number;
abstract get totalDollars(): number | null;
abstract get regularPriceDolar(): number;
// create toJson method
toJSON() {
return {
id: this.id,
warehouseId: this.warehouseId,
type: this.type,
name: this.name,
stock: this.stock,
quantity: this.quantity,
image: this.image,
medium: this.image, // deprecated
packagingType: this.packagingType,
minQuantity: this.minQuantity,
multipleQuantity: this.multipleQuantity,
total: this.total,
subtotal: this.subtotal,
maxQuantity: this.maxQuantity,
maximumQuantity: this.maxQuantity, // deprecated
regularPrice: this.regularPrice,
discountedPrice: this.discountedPrice,
totalDollars: this.totalDollars,
regularPriceDolar: this.regularPriceDolar
};
}
}