This commit is contained in:
nflnkr 2023-03-08 13:52:16 +03:00
parent 834617e526
commit f6a6c54ae6
3 changed files with 77 additions and 61 deletions

@ -14,6 +14,7 @@ interface Props {
selectedTariffs: GridSelectionModel;
}
// TODO реализовать правило "если взят готовый тариф, то кастомный на этот сервис сделать уже нельзя"
export default function Cart({ selectedTariffs }: Props) {
const tariffs = useTariffStore(store => store.tariffs);
const discounts = useDiscountStore(store => store.discounts);
@ -23,29 +24,50 @@ export default function Cart({ selectedTariffs }: Props) {
// const [coupon, setCoupon] = useState<string | undefined>();
const cartRows = cartTotal?.items.map(cartItemTotal => {
const service = cartItemTotal.tariff.privilege.serviceKey;
const serviceDiscount = cartTotal.discountsByService[service];
const envolvedDiscountsElement = (
<Box>
{cartItemTotal.envolvedDiscounts.map(discountId => (
<DiscountTooltip
key={discountId}
discount={findDiscountById(discounts, discountId)}
cartItemTotal={cartItemTotal}
/>
))}
{cartItemTotal.envolvedDiscountIds.map((discountId, index, arr) => {
const discount = findDiscountById(discounts, discountId);
return (
<span key={discount._id}>
<DiscountTooltip
discount={discount}
cartItemTotal={cartItemTotal}
/>
{index < arr.length - (discount ? 0 : 1) &&
<span>,&nbsp;</span>
}
</span>
);
})}
{serviceDiscount &&
<span>
<DiscountTooltip
discount={serviceDiscount}
cartItemTotal={cartItemTotal}
/>
</span>
}
</Box>
);
const totalIncludingServiceDiscount = cartItemTotal.totalPrice * (serviceDiscount?.target.factor || 1);
return {
id: cartItemTotal.tariff.id,
tariffName: cartItemTotal.tariff.name,
privilegeDesc: cartItemTotal.tariff.privilege.description,
envolvedDiscounts: envolvedDiscountsElement,
price: cartItemTotal.totalPrice,
price: totalIncludingServiceDiscount,
};
});
const cartDiscounts = cartTotal?.envolvedCartDiscounts.map(discountId => findDiscountById(discounts, discountId));
const cartDiscountsResultFactor = cartDiscounts && 1 - cartDiscounts.reduce((acc, discount) => acc * findDiscountFactor(discount), 1);
const cartDiscounts = cartTotal?.envolvedCartDiscountIds.map(discountId => findDiscountById(discounts, discountId));
const cartDiscountsResultFactor = cartDiscounts && cartDiscounts.reduce((acc, discount) => acc * findDiscountFactor(discount), 1);
const envolvedCartDiscountsElement = cartDiscounts && (
<Box sx={{

@ -1,6 +1,6 @@
import { CartItem, AnyDiscount, CartTotal, CartItemTotal, PrivilegeDiscount, CartPurchasesAmountDiscount, PurchasesAmountDiscount, ServiceToPriceMap, ServiceDiscount, UserDiscount } from "@root/model/cart";
import { ServiceType, SERVICE_LIST, Tariff } from "@root/model/tariff";
import { User } from "@root/model/user";
import { ServiceType, SERVICE_LIST, Tariff } from "../../model/tariff";
import { User } from "../../model/user";
export function calcCartData(
@ -13,20 +13,16 @@ export function calcCartData(
items: [],
totalPrice: 0,
priceByService: {
templategen: {
defaultTariffs: 0,
customTariffs: 0,
},
squiz: {
defaultTariffs: 0,
customTariffs: 0,
},
dwarfener: {
defaultTariffs: 0,
customTariffs: 0,
},
templategen: 0,
squiz: 0,
dwarfener: 0,
},
envolvedCartDiscounts: [],
discountsByService: {
templategen: null,
squiz: null,
dwarfener: null,
},
envolvedCartDiscountIds: [],
};
// layer 0
@ -35,17 +31,17 @@ export function calcCartData(
cartItems.forEach(cartItem => {
cartTotal.items.push({
envolvedDiscounts: [],
envolvedDiscountIds: [],
tariff: cartItem.tariff,
totalPrice: cartItem.price,
});
cartTotal.priceByService[cartItem.tariff.privilege.serviceKey].defaultTariffs += cartItem.price;
cartTotal.priceByService[cartItem.tariff.privilege.serviceKey] += cartItem.price;
cartTotal.totalPrice += cartItem.price;
});
cartTotal.totalPrice *= discount.target.factor;
cartTotal.envolvedCartDiscounts.push(discount._id);
cartTotal.envolvedCartDiscountIds.push(discount._id);
return cartTotal;
}
@ -56,7 +52,7 @@ export function calcCartData(
for (const cartItem of cartItems) {
const cartItemTotal: CartItemTotal = {
tariff: cartItem.tariff,
envolvedDiscounts: [],
envolvedDiscountIds: [],
totalPrice: cartItem.price,
};
@ -64,58 +60,52 @@ export function calcCartData(
const privilegesAffectedByCoupon: string[] = [];
couponDiscount?.target.products.forEach(product => {
if (
product.privilegeId === tariff.privilege.privilegeId &&
(tariff.customPricePerUnit === undefined || couponDiscount.overwhelm)
) {
cartItemTotal.totalPrice *= product.factor;
cartItemTotal.envolvedDiscounts.push(couponDiscount._id);
privilegesAffectedByCoupon.push(product.privilegeId);
}
if (product.privilegeId !== tariff.privilege.privilegeId) return;
if (tariff.customPricePerUnit !== undefined && !couponDiscount.overwhelm) return;
cartItemTotal.totalPrice *= product.factor;
cartItemTotal.envolvedDiscountIds.push(couponDiscount._id);
privilegesAffectedByCoupon.push(product.privilegeId);
});
const privilegeDiscount = findMaxApplicablePrivilegeDiscount(discounts, tariff);
privilegeDiscount?.target.products.forEach(product => {
if (
product.privilegeId === tariff.privilege.privilegeId &&
tariff.customPricePerUnit === undefined &&
!privilegesAffectedByCoupon.includes(privilegeDiscount.condition.privilege.id)
) {
cartItemTotal.totalPrice *= product.factor;
cartItemTotal.envolvedDiscounts.push(privilegeDiscount._id);
}
if (product.privilegeId !== tariff.privilege.privilegeId) return;
if (tariff.customPricePerUnit !== undefined) return;
if (privilegesAffectedByCoupon.includes(privilegeDiscount.condition.privilege.id)) return;
cartItemTotal.totalPrice *= product.factor;
cartItemTotal.envolvedDiscountIds.push(privilegeDiscount._id);
});
cartTotal.items.push(cartItemTotal);
if (tariff.customPricePerUnit === undefined) cartTotal.priceByService[tariff.privilege.serviceKey].defaultTariffs += cartItemTotal.totalPrice;
else cartTotal.priceByService[tariff.privilege.serviceKey].customTariffs += cartItemTotal.totalPrice;
cartTotal.priceByService[tariff.privilege.serviceKey] += cartItemTotal.totalPrice;
}
// layer 2
SERVICE_LIST.map(service => service.serviceKey).forEach(service => {
const serviceDiscount = findMaxServiceDiscount(service, discounts, cartTotal.priceByService);
if (serviceDiscount) {
cartTotal.priceByService[service].defaultTariffs *= serviceDiscount.target.factor;
if (cartTotal.priceByService[service].defaultTariffs > 0) cartTotal.envolvedCartDiscounts.push(serviceDiscount._id);
cartTotal.priceByService[service] *= serviceDiscount.target.factor;
cartTotal.discountsByService[service] = serviceDiscount;
}
cartTotal.totalPrice += cartTotal.priceByService[service].defaultTariffs;
cartTotal.totalPrice += cartTotal.priceByService[service].customTariffs;
cartTotal.totalPrice += cartTotal.priceByService[service];
});
// layer 3
const cartPurchasesAmountDiscount = findMaxCartPurchasesAmountDiscount(discounts, cartTotal);
if (cartPurchasesAmountDiscount) {
cartTotal.totalPrice *= cartPurchasesAmountDiscount.factor;
cartTotal.envolvedCartDiscounts.push(cartPurchasesAmountDiscount._id);
cartTotal.envolvedCartDiscountIds.push(cartPurchasesAmountDiscount._id);
}
// layer 4
const totalPurchasesAmountDiscount = findMaxTotalPurchasesAmountDiscount(discounts, user);
if (totalPurchasesAmountDiscount) {
cartTotal.totalPrice *= totalPurchasesAmountDiscount.factor;
cartTotal.envolvedCartDiscounts.push(totalPurchasesAmountDiscount._id);
cartTotal.envolvedCartDiscountIds.push(totalPurchasesAmountDiscount._id);
}
return cartTotal;
@ -176,7 +166,7 @@ function findMaxServiceDiscount(
return (
discount.conditionType === "service" &&
discount.condition.service.id === service &&
priceByService[service].defaultTariffs + priceByService[service].customTariffs >= discount.condition.service.value
priceByService[service] >= discount.condition.service.value
);
});

@ -119,21 +119,25 @@ export interface CartItem {
/** Пункт корзины с уже примененными скидками */
export interface CartItemTotal {
/** Массив с id примененных скидок */
envolvedDiscounts: string[];
envolvedDiscountIds: string[]; // TODO заменить на ссылки на скидки
totalPrice: number;
tariff: Tariff;
}
export type ServiceToPriceMap = {
[Key in ServiceType]: {
customTariffs: number;
defaultTariffs: number;
}
[Key in ServiceType]: number;
};
export type ServiceToDiscountMap = {
[Key in ServiceType]: ServiceDiscount | null;
};
export interface CartTotal {
items: CartItemTotal[];
totalPrice: number;
priceByService: ServiceToPriceMap;
envolvedCartDiscounts: string[];
/** Скидки по сервисам */
discountsByService: ServiceToDiscountMap;
/** Учтенные скидки типов userType, cartPurchasesAmount, totalPurchasesAmount */
envolvedCartDiscountIds: string[]; // TODO заменить на ссылки на скидки
}