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

@ -1,6 +1,6 @@
import { CartItem, AnyDiscount, CartTotal, CartItemTotal, PrivilegeDiscount, CartPurchasesAmountDiscount, PurchasesAmountDiscount, ServiceToPriceMap, ServiceDiscount, UserDiscount } from "@root/model/cart"; 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 { ServiceType, SERVICE_LIST, Tariff } from "../../model/tariff";
import { User } from "@root/model/user"; import { User } from "../../model/user";
export function calcCartData( export function calcCartData(
@ -13,20 +13,16 @@ export function calcCartData(
items: [], items: [],
totalPrice: 0, totalPrice: 0,
priceByService: { priceByService: {
templategen: { templategen: 0,
defaultTariffs: 0, squiz: 0,
customTariffs: 0, dwarfener: 0,
},
squiz: {
defaultTariffs: 0,
customTariffs: 0,
},
dwarfener: {
defaultTariffs: 0,
customTariffs: 0,
},
}, },
envolvedCartDiscounts: [], discountsByService: {
templategen: null,
squiz: null,
dwarfener: null,
},
envolvedCartDiscountIds: [],
}; };
// layer 0 // layer 0
@ -35,17 +31,17 @@ export function calcCartData(
cartItems.forEach(cartItem => { cartItems.forEach(cartItem => {
cartTotal.items.push({ cartTotal.items.push({
envolvedDiscounts: [], envolvedDiscountIds: [],
tariff: cartItem.tariff, tariff: cartItem.tariff,
totalPrice: cartItem.price, 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 += cartItem.price;
}); });
cartTotal.totalPrice *= discount.target.factor; cartTotal.totalPrice *= discount.target.factor;
cartTotal.envolvedCartDiscounts.push(discount._id); cartTotal.envolvedCartDiscountIds.push(discount._id);
return cartTotal; return cartTotal;
} }
@ -56,7 +52,7 @@ export function calcCartData(
for (const cartItem of cartItems) { for (const cartItem of cartItems) {
const cartItemTotal: CartItemTotal = { const cartItemTotal: CartItemTotal = {
tariff: cartItem.tariff, tariff: cartItem.tariff,
envolvedDiscounts: [], envolvedDiscountIds: [],
totalPrice: cartItem.price, totalPrice: cartItem.price,
}; };
@ -64,58 +60,52 @@ export function calcCartData(
const privilegesAffectedByCoupon: string[] = []; const privilegesAffectedByCoupon: string[] = [];
couponDiscount?.target.products.forEach(product => { couponDiscount?.target.products.forEach(product => {
if ( if (product.privilegeId !== tariff.privilege.privilegeId) return;
product.privilegeId === tariff.privilege.privilegeId && if (tariff.customPricePerUnit !== undefined && !couponDiscount.overwhelm) return;
(tariff.customPricePerUnit === undefined || couponDiscount.overwhelm)
) { cartItemTotal.totalPrice *= product.factor;
cartItemTotal.totalPrice *= product.factor; cartItemTotal.envolvedDiscountIds.push(couponDiscount._id);
cartItemTotal.envolvedDiscounts.push(couponDiscount._id); privilegesAffectedByCoupon.push(product.privilegeId);
privilegesAffectedByCoupon.push(product.privilegeId);
}
}); });
const privilegeDiscount = findMaxApplicablePrivilegeDiscount(discounts, tariff); const privilegeDiscount = findMaxApplicablePrivilegeDiscount(discounts, tariff);
privilegeDiscount?.target.products.forEach(product => { privilegeDiscount?.target.products.forEach(product => {
if ( if (product.privilegeId !== tariff.privilege.privilegeId) return;
product.privilegeId === tariff.privilege.privilegeId && if (tariff.customPricePerUnit !== undefined) return;
tariff.customPricePerUnit === undefined && if (privilegesAffectedByCoupon.includes(privilegeDiscount.condition.privilege.id)) return;
!privilegesAffectedByCoupon.includes(privilegeDiscount.condition.privilege.id)
) { cartItemTotal.totalPrice *= product.factor;
cartItemTotal.totalPrice *= product.factor; cartItemTotal.envolvedDiscountIds.push(privilegeDiscount._id);
cartItemTotal.envolvedDiscounts.push(privilegeDiscount._id);
}
}); });
cartTotal.items.push(cartItemTotal); cartTotal.items.push(cartItemTotal);
if (tariff.customPricePerUnit === undefined) cartTotal.priceByService[tariff.privilege.serviceKey].defaultTariffs += cartItemTotal.totalPrice; cartTotal.priceByService[tariff.privilege.serviceKey] += cartItemTotal.totalPrice;
else cartTotal.priceByService[tariff.privilege.serviceKey].customTariffs += cartItemTotal.totalPrice;
} }
// layer 2 // layer 2
SERVICE_LIST.map(service => service.serviceKey).forEach(service => { SERVICE_LIST.map(service => service.serviceKey).forEach(service => {
const serviceDiscount = findMaxServiceDiscount(service, discounts, cartTotal.priceByService); const serviceDiscount = findMaxServiceDiscount(service, discounts, cartTotal.priceByService);
if (serviceDiscount) { if (serviceDiscount) {
cartTotal.priceByService[service].defaultTariffs *= serviceDiscount.target.factor; cartTotal.priceByService[service] *= serviceDiscount.target.factor;
if (cartTotal.priceByService[service].defaultTariffs > 0) cartTotal.envolvedCartDiscounts.push(serviceDiscount._id); cartTotal.discountsByService[service] = serviceDiscount;
} }
cartTotal.totalPrice += cartTotal.priceByService[service].defaultTariffs; cartTotal.totalPrice += cartTotal.priceByService[service];
cartTotal.totalPrice += cartTotal.priceByService[service].customTariffs;
}); });
// layer 3 // layer 3
const cartPurchasesAmountDiscount = findMaxCartPurchasesAmountDiscount(discounts, cartTotal); const cartPurchasesAmountDiscount = findMaxCartPurchasesAmountDiscount(discounts, cartTotal);
if (cartPurchasesAmountDiscount) { if (cartPurchasesAmountDiscount) {
cartTotal.totalPrice *= cartPurchasesAmountDiscount.factor; cartTotal.totalPrice *= cartPurchasesAmountDiscount.factor;
cartTotal.envolvedCartDiscounts.push(cartPurchasesAmountDiscount._id); cartTotal.envolvedCartDiscountIds.push(cartPurchasesAmountDiscount._id);
} }
// layer 4 // layer 4
const totalPurchasesAmountDiscount = findMaxTotalPurchasesAmountDiscount(discounts, user); const totalPurchasesAmountDiscount = findMaxTotalPurchasesAmountDiscount(discounts, user);
if (totalPurchasesAmountDiscount) { if (totalPurchasesAmountDiscount) {
cartTotal.totalPrice *= totalPurchasesAmountDiscount.factor; cartTotal.totalPrice *= totalPurchasesAmountDiscount.factor;
cartTotal.envolvedCartDiscounts.push(totalPurchasesAmountDiscount._id); cartTotal.envolvedCartDiscountIds.push(totalPurchasesAmountDiscount._id);
} }
return cartTotal; return cartTotal;
@ -176,7 +166,7 @@ function findMaxServiceDiscount(
return ( return (
discount.conditionType === "service" && discount.conditionType === "service" &&
discount.condition.service.id === 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 { export interface CartItemTotal {
/** Массив с id примененных скидок */ /** Массив с id примененных скидок */
envolvedDiscounts: string[]; envolvedDiscountIds: string[]; // TODO заменить на ссылки на скидки
totalPrice: number; totalPrice: number;
tariff: Tariff; tariff: Tariff;
} }
export type ServiceToPriceMap = { export type ServiceToPriceMap = {
[Key in ServiceType]: { [Key in ServiceType]: number;
customTariffs: number; };
defaultTariffs: number;
} export type ServiceToDiscountMap = {
[Key in ServiceType]: ServiceDiscount | null;
}; };
export interface CartTotal { export interface CartTotal {
items: CartItemTotal[]; items: CartItemTotal[];
totalPrice: number; totalPrice: number;
priceByService: ServiceToPriceMap; priceByService: ServiceToPriceMap;
envolvedCartDiscounts: string[]; /** Скидки по сервисам */
discountsByService: ServiceToDiscountMap;
/** Учтенные скидки типов userType, cartPurchasesAmount, totalPurchasesAmount */
envolvedCartDiscountIds: string[]; // TODO заменить на ссылки на скидки
} }