@chiper-inc/ecommerce-lib
Version:
Chiper Inc Ecommerce Lib
128 lines (113 loc) • 3.5 kB
text/typescript
import { count } from "console";
/**
* Finds the highest quantity that can be sold of an item adjusted to its `multipleQuantity`
* @param stock item stock
* @param maxQuantity maximum quantity of this item that can be added
* @param multipleQuantity `multipleQuantity` for the item
* @returns the highest quantity of the item that can be sold
*/
export const getMaximumValue = (
stock: number,
maxQuantity: number,
multipleQuantity: number
): number => {
const maxValue = Math.min(stock, maxQuantity);
const maxQuantityTimes = Math.floor(maxValue / multipleQuantity) ?? 1;
const maxStockMultipleQuantity = maxQuantityTimes * multipleQuantity;
return maxStockMultipleQuantity;
};
/**
* Find the `multipleQuantity` closest to `quantity`
* @param quantity amount you want to add
* @param multipleQuantity multipleQuantity of this item
* @param stock item stock
* @returns quantity that complies with the `multiple Quantity`
*/
export const roundToMultipleQuantity = (
quantity: number,
multipleQuantity: number,
stock: number
) => {
const roundNumber =
Math.round(quantity / multipleQuantity) * multipleQuantity;
const roundStock = Math.floor(stock / multipleQuantity) * multipleQuantity;
return stock < roundNumber ? roundStock : roundNumber;
};
export const getDiscount = (regularPrice: number, discountedPrice: number) =>
((regularPrice - discountedPrice) / regularPrice) * 100;
const min = (a?: number, b?: number): number | undefined => {
if (a === undefined) {
return b;
}
if (b === undefined) {
return a;
}
return a < b ? a : b;
};
class MaxCounter {
private _max?: number;
private _count = 0;
private _counter?: MaxCounter;
constructor(max?: number | null, counter?: MaxCounter) {
this._max = max ?? undefined;
this._counter = counter;
}
get max(): number | undefined {
return min(
this._max ? this._max - this._count : undefined,
this._counter?.max
);
}
get maxAndAdd(): number | undefined {
const maxQuantity = this.max;
this.add(maxQuantity || 0);
return maxQuantity;
}
set counter(counter: MaxCounter) {
this._counter = counter;
}
add(count: number) {
this._count += count;
this._counter?.add(count);
}
}
export class MaxQuantityHelper {
private readonly _quantity: MaxCounter;
private readonly _discounted: MaxCounter;
private readonly _scales = new Map();
constructor(
productMaxQuantity?: number | null,
discountedMaximumQuantity?: number | null
) {
this._quantity = new MaxCounter(productMaxQuantity);
this._discounted = new MaxCounter(
discountedMaximumQuantity,
this._quantity
);
}
private scaleMaxQuantity(counter: MaxCounter, startQuantity = 1, endQuantity?: number) {
if (endQuantity) {
const scale = this._scales.get(startQuantity);
if (scale) {
scale.counter = counter;
counter = scale;
} else {
counter = new MaxCounter(endQuantity - startQuantity + 1, counter);
this._scales.set(startQuantity, counter);
}
}
return counter.maxAndAdd;
}
public maxQuantity(
startQuantity = 1,
endQuantity?: number
): number | undefined {
return this.scaleMaxQuantity(this._quantity, startQuantity, endQuantity);
}
public discountedMaxQuantity(
startQuantity = 1,
endQuantity?: number
): number | undefined {
return this.scaleMaxQuantity(this._discounted, startQuantity, endQuantity);
}
}