Merge branch 'discounts' into 'dev'

add discount creating

See merge request frontend/admin!23
This commit is contained in:
Mikhail 2023-06-30 19:41:33 +00:00
commit a815229da0
16 changed files with 653 additions and 423 deletions

@ -6,16 +6,6 @@
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",

106
src/api/discounts.ts Normal file

@ -0,0 +1,106 @@
import { CreateDiscountBody, Discount, DiscountType } from "@root/model/discount";
import { ServiceType } from "@root/model/tariff";
import { authStore } from "@root/stores/auth";
const makeRequest = authStore.getState().makeRequest;
type CreateDiscount = (props: {
purchasesAmount: number;
cartPurchasesAmount: number;
discountMinValue: number;
discountFactor: number;
discountDescription: string;
discountName: string;
/** ISO string */
startDate: string;
/** ISO string */
endDate: string;
serviceType: ServiceType;
discountType: DiscountType;
privilegeId: string;
}) => Promise<Discount>;
export const createDiscountJSON: CreateDiscount = ({
endDate,
startDate,
discountName,
cartPurchasesAmount,
discountDescription,
discountFactor,
discountMinValue,
purchasesAmount,
serviceType,
discountType,
privilegeId,
}) => {
const discount: CreateDiscountBody = {
Name: discountName,
Layer: 1,
Description: discountDescription,
Condition: {
Period: {
From: startDate,
To: endDate,
},
User: "",
UserType: "",
Coupon: "",
Usage: 0,
PurchasesAmount: 0,
CartPurchasesAmount: 0,
Product: "",
Term: 0,
PriceFrom: 0,
Group: "",
},
Target: {
Factor: discountFactor,
TargetScope: "Sum",
Overhelm: false,
TargetGroup: "",
Products: [{
ID: "",
Factor: 0,
Overhelm: false,
}],
},
};
switch (discountType) {
case "privilege":
discount.Layer = 1;
discount.Condition.Product = privilegeId;
discount.Condition.Term = discountMinValue;
discount.Target.Products = [{
Factor: discountFactor,
ID: privilegeId,
Overhelm: false,
}];
break;
case "service":
discount.Layer = 2;
discount.Condition.PriceFrom = discountMinValue;
discount.Condition.Group = serviceType;
discount.Target.TargetGroup = serviceType;
break;
case "cartPurchasesAmount":
discount.Layer = 3;
discount.Condition.CartPurchasesAmount = cartPurchasesAmount;
break;
case "purchasesAmount":
discount.Layer = 4;
discount.Condition.PurchasesAmount = purchasesAmount;
break;
}
console.log("Constructed discount", discount);
return makeRequest<CreateDiscountBody, Discount>({
url: "https://admin.pena.digital/price/discount",
method: "post",
useToken: true,
bearer: true,
body: discount,
});
};

@ -19,11 +19,12 @@ import { useCartStore } from "@root/stores/cart";
import { useEffect, useState } from "react";
import { GridSelectionModel } from "@mui/x-data-grid";
import { testUser } from "@root/stores/mocks/user";
import { useDiscountStore } from "@root/stores/discounts";
import { useMockDiscountStore } from "@root/stores/discounts";
import { calcCartData, createCartItem, findDiscountFactor, formatDiscountFactor } from "./calc";
import { useTariffStore } from "@root/stores/tariffs";
import { AnyDiscount, CartItemTotal } from "@root/model/cart";
import { findPrivilegeById } from "@root/stores/privileges";
import { Privilege } from "@root/model/tariff";
interface Props {
selectedTariffs: GridSelectionModel;
@ -46,7 +47,7 @@ interface MergedTariff {
}
export default function Cart({ selectedTariffs }: Props) {
const discounts = useDiscountStore((store) => store.discounts);
const discounts = useMockDiscountStore((store) => store.discounts);
const cartTotal = useCartStore((state) => state.cartTotal);
const setCartTotal = useCartStore((store) => store.setCartTotal);
const [couponField, setCouponField] = useState<string>("");

@ -10,9 +10,9 @@ import {
ServiceDiscount,
UserDiscount,
} from "@root/model/cart";
import { Tariff_BACKEND } from "@root/model/tariff";
import { User } from "../../model/user";
import { findPrivilegeById } from "@root/stores/privileges";
import { SERVICE_LIST, ServiceType, Tariff } from "@root/model/tariff";
export function calcCartData({
user,

@ -1,3 +1,6 @@
import { ServiceType } from "./tariff";
export type Discount = {
ID: string;
Name: string;
@ -39,6 +42,50 @@ export type Discount = {
Deprecated: boolean;
};
export type DiscountData = {
export type GetDiscountResponse = {
Discounts: Discount[];
};
export const discountTypes = {
"purchasesAmount": "Лояльность",
"cartPurchasesAmount": "Корзина",
"service": "Сервис",
"privilege": "Товар",
} as const;
export type DiscountType = keyof typeof discountTypes;
export type CreateDiscountBody = {
Name: string;
Layer: 1 | 2 | 3 | 4;
Description: string;
Condition: {
Period: {
/** ISO string */
From: string;
/** ISO string */
To: string;
};
User: string;
UserType: string;
Coupon: string;
PurchasesAmount: number;
CartPurchasesAmount: number;
Product: string;
Term: number;
Usage: number;
PriceFrom: number;
Group: ServiceType | "";
};
Target: {
Factor: number;
TargetScope: "Sum" | "Group" | "Each";
Overhelm: boolean;
TargetGroup: ServiceType | "";
Products: [{
ID: string;
Factor: number;
Overhelm: false;
}];
};
};

21
src/model/privilege.ts Normal file

@ -0,0 +1,21 @@
export interface RealPrivilege {
_id: string;
name: string;
privilegeId: string;
serviceKey: string;
description: string;
type: "day" | "count";
value: PrivilegeValueType;
price: number;
updatedAt?: string;
isDeleted?: boolean;
createdAt?: string;
};
export type PrivilegeMap = Record<string, RealPrivilege[]>;
export type PrivilegeValueType = "шаблон" | "день" | "МБ";
export type PrivilegeWithAmount = Omit<RealPrivilege, "_id"> & { amount: number; };
export type PrivilegeWithoutPrice = Omit<PrivilegeWithAmount, "price">;

@ -38,13 +38,36 @@ export type Tariff_BACKEND = {
privilegies: Privilege_BACKEND[],
isDeleted: boolean,
createdAt: string,
updatedAt: string
}
updatedAt: string;
};
export type Tariff_FRONTEND = {
id: string,
name: string,
amount: number,
isFront: boolean,
privilegeId: string,
customPricePerUnit: number
customPricePerUnit?: number;
};
/** @deprecated */
export interface Privilege {
serviceKey: ServiceType;
name: PrivilegeType;
privilegeId: string;
description: string;
/** Единица измерения привелегии: время в днях/кол-во */
type: "day" | "count";
/** Стоимость одной единицы привелегии */
price: number;
}
/** @deprecated */
export interface Tariff {
id: string;
name: string;
privilegeId: string;
/** Количество единиц привелегии */
amount: number;
/** Кастомная цена, если есть, то используется вместо privilege.price */
customPricePerUnit?: number;
isFront?: boolean;
}

@ -4,34 +4,29 @@ import Select, { SelectChangeEvent } from "@mui/material/Select";
import { useState } from "react";
import { SERVICE_LIST, ServiceType } from "@root/model/tariff";
import { CustomTextField } from "@root/kitUI/CustomTextField";
import { usePrivilegeStore } from "@root/stores/privileges";
import { AnyDiscount } from "@root/model/cart";
import { nanoid } from "nanoid";
import { addRealPrivileges, useRealPrivilegeStore } from "@root/stores/privileges";
import { addDiscounts } from "@root/stores/discounts";
import { enqueueSnackbar } from "notistack";
import { DiscountType, discountTypes } from "@root/model/discount";
import { createDiscountJSON } from "@root/api/discounts";
import usePrivileges from "@root/utils/hooks/usePrivileges";
const discountTypes = {
"Лояльность": "purchasesAmount",
"Корзина": "cartPurchasesAmount",
"Сервис": "service",
"Товар": "privilege",
} as const;
type DiscountType = keyof typeof discountTypes;
export default function CreateDiscount() {
const theme = useTheme();
const privileges = usePrivilegeStore(state => state.privileges);
const privileges = useRealPrivilegeStore(state => state.privileges);
const [serviceType, setServiceType] = useState<ServiceType>("templategen");
const [discountType, setDiscountType] = useState<DiscountType>("Лояльность");
const [discountType, setDiscountType] = useState<DiscountType>("purchasesAmount");
const [discountNameField, setDiscountNameField] = useState<string>("");
const [discountDescription, setDiscountDescription] = useState<string>("");
const [discountDescriptionField, setDiscountDescriptionField] = useState<string>("");
const [privilegeIdField, setPrivilegeIdField] = useState<string | "">("");
const [discountFactorField, setDiscountFactorField] = useState<string>("0");
const [purchasesAmountField, setPurchasesAmountField] = useState<string>("0");
const [cartPurchasesAmountField, setCartPurchasesAmountField] = useState<string>("0");
const [discountMinValueField, setDiscountMinValueField] = useState<string>("0");
usePrivileges({ onNewPrivileges: addRealPrivileges });
const handleDiscountTypeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setDiscountType(event.target.value as DiscountType);
};
@ -40,9 +35,9 @@ export default function CreateDiscount() {
setServiceType(event.target.value as ServiceType);
};
function handleCreateDiscount() {
async function handleCreateDiscount() {
const purchasesAmount = parseFloat(purchasesAmountField.replace(",", "."));
const discountFactor = 1 - parseFloat(discountFactorField.replace(",", ".")) / 100;
const discountFactor = (100 - parseFloat(discountFactorField.replace(",", "."))) / 100;
const cartPurchasesAmount = parseFloat(cartPurchasesAmountField.replace(",", "."));
const discountMinValue = parseFloat(discountMinValueField.replace(",", "."));
@ -50,82 +45,28 @@ export default function CreateDiscount() {
if (!isFinite(discountFactor)) return enqueueSnackbar("Поле discountFactor не число");
if (!isFinite(cartPurchasesAmount)) return enqueueSnackbar("Поле cartPurchasesAmount не число");
if (!isFinite(discountMinValue)) return enqueueSnackbar("Поле discountMinValue не число");
if (discountType === "privilege" && !privilegeIdField) return enqueueSnackbar("Привилегия не выбрана");
let discount: AnyDiscount;
switch (discountType) {
case "Лояльность": {
discount = {
_id: nanoid(6),
name: discountNameField,
description: discountDescription,
disabled: false,
conditionType: "purchasesAmount",
condition: {
purchasesAmount: purchasesAmount,
},
factor: discountFactor,
};
break;
}
case "Корзина": {
discount = {
_id: nanoid(6),
name: discountNameField,
description: discountDescription,
disabled: false,
conditionType: "cartPurchasesAmount",
condition: {
cartPurchasesAmount: cartPurchasesAmount,
},
factor: discountFactor,
};
break;
}
case "Сервис": {
discount = {
_id: nanoid(6),
name: discountNameField,
description: discountDescription,
disabled: false,
conditionType: "service",
condition: {
service: {
id: serviceType,
value: discountMinValue,
},
},
target: {
service: serviceType,
factor: discountFactor,
},
};
break;
}
case "Товар": {
discount = {
_id: nanoid(6),
name: discountNameField,
description: discountDescription,
disabled: false,
conditionType: "privilege",
condition: {
privilege: {
id: privilegeIdField,
value: discountMinValue,
},
},
target: {
products: [{
try {
const createdDiscount = await createDiscountJSON({
cartPurchasesAmount,
discountFactor,
discountMinValue,
purchasesAmount,
discountDescription: discountDescriptionField,
discountName: discountNameField,
startDate: new Date().toISOString(),
endDate: new Date(Date.now() + 1000 * 3600 * 24 * 30).toISOString(),
serviceType,
discountType,
privilegeId: privilegeIdField,
factor: discountFactor,
}],
},
};
break;
}
}
});
addDiscounts([discount]);
addDiscounts([createdDiscount]);
} catch (error) {
console.log("Error creating discount", error);
enqueueSnackbar("Ошибка при создании скидки");
}
}
return (
@ -149,8 +90,8 @@ export default function CreateDiscount() {
<CustomTextField
id="discount-desc"
label="Описание"
value={discountDescription}
onChange={e => setDiscountDescription(e.target.value)}
value={discountDescriptionField}
onChange={e => setDiscountDescriptionField(e.target.value)}
/>
<Typography
variant="h4"
@ -187,11 +128,16 @@ export default function CreateDiscount() {
onChange={handleDiscountTypeChange}
>
{Object.keys(discountTypes).map(type =>
<FormControlLabel key={type} value={type} control={<Radio color="secondary" />} label={type} />
<FormControlLabel
key={type}
value={type}
control={<Radio color="secondary" />}
label={discountTypes[type as DiscountType]}
/>
)}
</RadioGroup>
</FormControl>
{discountType === "Лояльность" &&
{discountType === "purchasesAmount" &&
<CustomTextField
id="discount-purchases"
label="Внесено больше"
@ -203,7 +149,7 @@ export default function CreateDiscount() {
onChange={e => setPurchasesAmountField(e.target.value)}
/>
}
{discountType === "Корзина" &&
{discountType === "cartPurchasesAmount" &&
<CustomTextField
id="discount-cart-purchases"
label="Объем в корзине"
@ -215,7 +161,7 @@ export default function CreateDiscount() {
onChange={e => setCartPurchasesAmountField(e.target.value)}
/>
}
{discountType === "Сервис" &&
{discountType === "service" &&
<>
<Select
labelId="discount-service-label"
@ -249,7 +195,7 @@ export default function CreateDiscount() {
/>
</>
}
{discountType === "Товар" &&
{discountType === "privilege" &&
<>
<FormControl
fullWidth

@ -1,17 +1,9 @@
import { useEffect, useState } from "react";
import { enqueueSnackbar } from "notistack";
import { Box, Button, styled, useTheme } from "@mui/material";
import { DataGrid, GridColDef, GridRowsProp, GridToolbar } from "@mui/x-data-grid";
import { findDiscountFactor, formatDiscountFactor } from "@root/kitUI/Cart/calc";
import {
activateDiscounts,
deactivateDiscounts,
setSelectedDiscountIds,
useDiscountStore,
} from "@root/stores/discounts";
import axios from "axios";
import { activateMockDiscounts, addDiscounts, deactivateMockDiscounts, setMockSelectedDiscountIds, useDiscountStore, useMockDiscountStore, } from "@root/stores/discounts";
import useDiscounts from "@root/utils/hooks/useDiscounts";
import type { DiscountData } from "@root/model/discount";
const BoxButton = styled("div")(({ theme }) => ({
[theme.breakpoints.down(400)]: {
@ -66,31 +58,11 @@ const columns: GridColDef[] = [
export default function DiscountDataGrid() {
const theme = useTheme();
const exampleDiscounts = useDiscountStore((state) => state.discounts);
const selectedDiscountIds = useDiscountStore((state) => state.selectedDiscountIds);
const exampleDiscounts = useMockDiscountStore((state) => state.discounts);
const selectedDiscountIds = useMockDiscountStore((state) => state.selectedDiscountIds);
const realDiscounts = useDiscountStore(state => state.discounts);
const [discount, setDiscount] = useState<DiscountData>();
const mergeDiscount = [...(discount?.Discounts ?? []), ...exampleDiscounts];
console.log(mergeDiscount);
useEffect(() => {
const axiosDiscount = async () => {
try {
const { data } = await axios({
method: "get",
url: "https://admin.pena.digital/price/discounts",
});
setDiscount(data);
console.log(data);
} catch (error) {
enqueueSnackbar("Ошибка получения скидок");
}
};
axiosDiscount();
}, []);
useDiscounts({ onNewDiscounts: addDiscounts });
const discountsGridData: GridRowsProp = exampleDiscounts.map((discount) => {
const value =
@ -119,7 +91,7 @@ export default function DiscountDataGrid() {
rows={discountsGridData}
columns={columns}
selectionModel={selectedDiscountIds}
onSelectionModelChange={setSelectedDiscountIds}
onSelectionModelChange={setMockSelectedDiscountIds}
sx={{
color: theme.palette.secondary.main,
"& .MuiDataGrid-iconSeparator": {
@ -165,7 +137,7 @@ export default function DiscountDataGrid() {
>
<Button
variant="contained"
onClick={deactivateDiscounts}
onClick={deactivateMockDiscounts}
sx={{
backgroundColor: theme.palette.menu.main,
width: "200px",
@ -182,7 +154,7 @@ export default function DiscountDataGrid() {
</Button>
<Button
variant="contained"
onClick={activateDiscounts}
onClick={activateMockDiscounts}
sx={{
backgroundColor: theme.palette.menu.main,
width: "200px",

@ -1,3 +1,4 @@
// @ts-nocheck
import React, { useEffect, useState } from "react";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
@ -48,6 +49,7 @@ interface Props {
getTariffs: () => void
}
/** @deprecated */
export default function EditModal({tariff, getTariffs}:Props) {
const [open, setOpen] = useState(false);

@ -1,3 +1,4 @@
// @ts-nocheck
import React from "react";
import { useEffect, useState } from "react";
import { GridColDef, GridSelectionModel, GridToolbar } from "@mui/x-data-grid";
@ -24,6 +25,7 @@ interface Props {
getTariffs: () => void;
}
/** @deprecated */
export default function TariffsDG({ selectedTariffs, handleSelectionChange, getTariffs }: Props) {
const { token } = authStore();

1
src/react-app-env.d.ts vendored Normal file

@ -0,0 +1 @@
/// <reference types="react-scripts" />

@ -3,14 +3,40 @@ import { AnyDiscount } from "@root/model/cart";
import { create } from "zustand";
import { devtools } from "zustand/middleware";
import { exampleCartValues } from "./mocks/exampleCartValues";
import { Discount } from "@root/model/discount";
interface DiscountStore {
discounts: AnyDiscount[];
discounts: Discount[];
selectedDiscountIds: GridSelectionModel,
}
export const useDiscountStore = create<DiscountStore>()(
devtools(
(set, get) => ({
discounts: [],
selectedDiscountIds: [],
}),
{
name: "Real discount store",
enabled: process.env.NODE_ENV === "development"
}
)
);
export const addDiscounts = (newDiscounts: DiscountStore["discounts"]) => useDiscountStore.setState(state => ({ discounts: [...state.discounts, ...newDiscounts] }));
export const setSelectedDiscountIds = (selectedDiscountIds: DiscountStore["selectedDiscountIds"]) => useDiscountStore.setState({ selectedDiscountIds });
/** @deprecated */
interface MockDiscountStore {
discounts: AnyDiscount[];
selectedDiscountIds: GridSelectionModel,
}
/** @deprecated */
export const useMockDiscountStore = create<MockDiscountStore>()(
devtools(
(set, get) => ({
discounts: exampleCartValues.discounts,
@ -22,11 +48,14 @@ export const useDiscountStore = create<DiscountStore>()(
)
);
export const addDiscounts = (newDiscounts: AnyDiscount[]) => useDiscountStore.setState(state => ({ discounts: [...state.discounts, ...newDiscounts] }));
/** @deprecated */
export const addMockDiscounts = (newDiscounts: AnyDiscount[]) => useMockDiscountStore.setState(state => ({ discounts: [...state.discounts, ...newDiscounts] }));
export const setSelectedDiscountIds = (selectedDiscountIds: DiscountStore["selectedDiscountIds"]) => useDiscountStore.setState({ selectedDiscountIds });
/** @deprecated */
export const setMockSelectedDiscountIds = (selectedDiscountIds: MockDiscountStore["selectedDiscountIds"]) => useMockDiscountStore.setState({ selectedDiscountIds });
export const activateDiscounts = () => useDiscountStore.setState(state => {
/** @deprecated */
export const activateMockDiscounts = () => useMockDiscountStore.setState(state => {
const discounts: AnyDiscount[] = [];
state.discounts.forEach(discount => {
if (!state.selectedDiscountIds.includes(discount._id)) return discounts.push(discount);
@ -40,7 +69,8 @@ export const activateDiscounts = () => useDiscountStore.setState(state => {
return { discounts };
});
export const deactivateDiscounts = () => useDiscountStore.setState(state => {
/** @deprecated */
export const deactivateMockDiscounts = () => useMockDiscountStore.setState(state => {
const discounts: AnyDiscount[] = [];
state.discounts.forEach(discount => {
if (!state.selectedDiscountIds.includes(discount._id)) return discounts.push(discount);

@ -2,7 +2,27 @@ import { Privilege } from "@root/model/tariff";
import { create } from "zustand";
import { devtools } from "zustand/middleware";
import { exampleCartValues } from "./mocks/exampleCartValues";
import { RealPrivilege } from "@root/model/privilege";
interface RealPrivilegeStore {
privileges: RealPrivilege[];
}
export const useRealPrivilegeStore = create<RealPrivilegeStore>()(
devtools(
(set, get) => ({
privileges: [],
}),
{
name: "Privilege store",
}
)
);
export const addRealPrivileges = (privileges: RealPrivilegeStore["privileges"]) => useRealPrivilegeStore.setState({ privileges });
/** @deprecated */
interface PrivilegeStore {
privileges: Privilege[];
isModalOpen: boolean;
@ -11,6 +31,7 @@ interface PrivilegeStore {
addPrivileges: (newPrivileges: Privilege[]) => void;
}
/** @deprecated */
export const usePrivilegeStore = create<PrivilegeStore>()(
devtools(
(set, get) => ({
@ -21,12 +42,15 @@ export const usePrivilegeStore = create<PrivilegeStore>()(
addPrivileges: (newPrivileges) => set((state) => ({ privileges: [...state.privileges, ...newPrivileges] })),
}),
{
name: "Privilege store",
name: "Mock Privilege store",
}
)
);
/** @deprecated */
export const closePrivilegePriceModal = () => usePrivilegeStore.setState({ isModalOpen: false });
/** @deprecated */
export const openPrivilegePriceModal = (modalPrivilegeId: string | null, defaultPrice: number) =>
usePrivilegeStore.setState({
isModalOpen: true,
@ -34,8 +58,10 @@ export const openPrivilegePriceModal = (modalPrivilegeId: string | null, default
modalPrivilegeId,
});
/** @deprecated */
export const changeModalPriceField = (modalPriceField: string) => usePrivilegeStore.setState({ modalPriceField });
/** @deprecated */
export const changePrivilegePrice = () => {
const { privileges, modalPrivilegeId, modalPriceField } = usePrivilegeStore.getState();
@ -59,6 +85,7 @@ export const changePrivilegePrice = () => {
});
};
/** @deprecated */
export const findPrivilegeById = (privilegeId: string) => {
return usePrivilegeStore.getState().privileges.find((privilege) => privilege.privilegeId === privilegeId) ?? null;
};

@ -0,0 +1,31 @@
import { Discount, GetDiscountResponse } from "@root/model/discount";
import { authStore } from "@root/stores/auth";
import { useEffect } from "react";
const makeRequest = authStore.getState().makeRequest;
export default function useDiscounts({ onError, onNewDiscounts }: {
onNewDiscounts: (response: Discount[]) => void;
onError?: (error: any) => void;
}) {
useEffect(() => {
const controller = new AbortController();
makeRequest<never, GetDiscountResponse>({
url: "https://admin.pena.digital/price/discounts",
method: "get",
useToken: true,
bearer: true,
signal: controller.signal,
}).then(result => {
console.log("New discounts", result);
onNewDiscounts(result.Discounts);
}).catch(error => {
console.log("Error fetching discounts", error);
onError?.(error);
});
return () => controller.abort();
}, [onError, onNewDiscounts]);
}

@ -0,0 +1,31 @@
import { RealPrivilege } from "@root/model/privilege";
import { authStore } from "@root/stores/auth";
import { useEffect } from "react";
const makeRequest = authStore.getState().makeRequest;
export default function usePrivileges({ onError, onNewPrivileges }: {
onNewPrivileges: (response: RealPrivilege[]) => void;
onError?: (error: any) => void;
}) {
useEffect(() => {
const controller = new AbortController();
makeRequest<never, RealPrivilege[]>({
url: "https://admin.pena.digital/strator/privilege",
method: "get",
useToken: true,
bearer: true,
signal: controller.signal,
}).then(result => {
console.log("New privileges", result);
onNewPrivileges(result);
}).catch(error => {
console.log("Error fetching privileges", error);
onError?.(error);
});
return () => controller.abort();
}, [onError, onNewPrivileges]);
}