diff --git a/src/pages/dashboard/Content/Tariffs/cartCalcs.ts b/src/pages/dashboard/Content/Tariffs/cartCalcs.ts new file mode 100644 index 0000000..40a4207 --- /dev/null +++ b/src/pages/dashboard/Content/Tariffs/cartCalcs.ts @@ -0,0 +1,163 @@ +import { Cart } from "../../../../model/cart"; +import { Tariffs } from "../../../../model/tariff"; +import { User } from "../../../../model/user"; + + +export function calcCartData( + user: User, + cartItems: Cart.CartItem[], + discounts: Cart.AnyDiscount[], + privileges: Cart.Privilege[], + promocode?: Cart.Promocode, +): Cart.CartTotal { + const cartTotal: Cart.CartTotal = { + items: [], + totalPrice: 0, + priceByService: { + templategen: 0, + squiz: 0, + dwarfener: 0, + }, + }; + + for (const discount of discounts) { + if (discount.conditionType !== "userType" || discount.condition.userType !== user.Type) continue; + + cartItems.forEach(cartItem => { + cartTotal.items.push({ + envolvedDiscounts: [], + item: cartItem.item, + totalPrice: cartItem.price, + }); + cartTotal.totalPrice += cartItem.price; + }); + + return cartTotal; + } + + if (promocode) { + for (const discount of discounts) { + if (discount.conditionType !== "user" || discount.condition.user !== user.ID || discount.condition.coupon !== promocode.name) continue; + + for (const cartItem of cartItems) { + const cartItemTotal = calcCartItemWithPromocode(cartItem, discount, cartTotal.priceByService); + + cartTotal.items.push(cartItemTotal); + cartTotal.totalPrice += cartItemTotal.totalPrice; + } + + return cartTotal; + } + } + + for (const cartItem of cartItems) { + const cartItemTotal: Cart.CartItemTotal = { + item: cartItem.item, + envolvedDiscounts: [], + totalPrice: cartItem.price, + }; + + if (isPackage(cartItem.item)) { + // TODO implement for package + + throw new Error("unimplemented"); + } + + const tariff = cartItem.item; + + const discountsForTariffService = discounts.filter((discount): discount is Cart.ServiceDiscount => ( + discount.conditionType === "service" && discount.condition.service.id === tariff.service + )); + const maxValueServiceDiscount = discountsForTariffService.reduce((prev, current) => { + return current.condition.service.value > prev.condition.service.value ? current : prev; + }); + + cartItemTotal.totalPrice *= maxValueServiceDiscount.target.factor; + cartItemTotal.envolvedDiscounts.push(maxValueServiceDiscount._id); + + + const maxPrivilegeDiscount = findMaxApplicablePrivilegeDiscount(tariff, discounts); + if (maxPrivilegeDiscount) { + maxPrivilegeDiscount.target.products.forEach(product => { + if (product.productId === tariff.id) { // TODO productId - ид продукта(тариф или пакет тарифов) или привилегии? Если второе, то откуда берется привилегия? + cartItemTotal.totalPrice *= product.factor; + cartItemTotal.envolvedDiscounts.push(maxPrivilegeDiscount._id); + } + }); + } + + cartTotal.items.push(cartItemTotal); + cartTotal.totalPrice += cartItemTotal.totalPrice; + cartTotal.priceByService[tariff.service] += cartItemTotal.totalPrice; + } + + return cartTotal; +} + +function findMaxApplicablePrivilegeDiscount( + tariff: Tariffs.Tariff, + discounts: Cart.AnyDiscount[], +): Cart.PrivilegeDiscount | null { + const applicablePrivilegeDiscounts = discounts.filter((discount): discount is Cart.PrivilegeDiscount => { + return discount.conditionType === "privilege" && tariff.amount >= discount.condition.privilege.value; + }); + + if (!applicablePrivilegeDiscounts.length) return null; + + const maxValueDiscount = applicablePrivilegeDiscounts.reduce( + (prev, current) => current.condition.privilege.value > prev.condition.privilege.value ? current : prev + ); + + return maxValueDiscount; +}; + +function calcCartItemWithPromocode( + cartItem: Cart.CartItem, + discount: Cart.UserDiscount, + priceByService: { [Key in Tariffs.ServiceType]: number; }, +): Cart.CartItemTotal { + const cartItemTotal: Cart.CartItemTotal = { + item: cartItem.item, + envolvedDiscounts: [], + totalPrice: 0, + }; + + if (isPackage(cartItem.item)) { + // TODO implement for package + + throw new Error("unimplemented"); + } + + const tariff = cartItem.item; + + discount.target.products.forEach(product => { + if (product.productId === tariff.id) { // TODO productId - ид продукта(тариф или пакет тарифов) или привилегии? Если второе, то откуда берется привилегия? + cartItemTotal.totalPrice *= product.factor; + cartItemTotal.envolvedDiscounts.push(discount._id); + } + }); + + priceByService[tariff.service] = cartItemTotal.totalPrice; + + return cartItemTotal; +} + +export function packTariffs(tariffs: Tariffs.Tariff[]): Tariffs.Package { + const id = Date.now().toString(); // TODO actual id + const name = "Package"; // TODO actual name + const services: Tariffs.ServiceType[] = []; + tariffs.forEach(tariff => { + if (!services.includes(tariff.service)) services.push(tariff.service); + }); + + return { + id, + name, + services, + tariffs, + }; +} + +export function isPackage(item: Tariffs.Tariff | Tariffs.Package): item is Tariffs.Package { + return "tariffs" in item; +} \ No newline at end of file