push rasad front on new repo

This commit is contained in:
2026-01-18 14:32:49 +03:30
commit 4fe6e70525
2139 changed files with 303150 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
import { SPACING } from "../../../../data/spacing";
import UploadIcon from "@mui/icons-material/Upload";
import { Grid } from "../../../../components/grid/Grid";
import { Button, Card, TextField, Typography } from "@mui/material";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import { useEffect, useState } from "react";
export const AvicultureBarForm = () => {
const [barWeight, setbarWeight] = useState(0);
const formik = useFormik({
initialValues: {
firstweight: "",
lastweight: "",
},
validationSchema: Yup.object({
firstweight: Yup.number()
.required("این فیلد اجباری است!")
.typeError("لطفا عدد وارد کنید!"),
lastweight: Yup.number()
.required("این فیلد اجباری است!")
.typeError("لطفا وزن را وارد کنید!"),
}),
});
useEffect(() => {
formik.validateForm();
}, []);
useEffect(() => {
const numFirstWeight = Number(formik.values.firstweight);
const numLastWeight = Number(formik.values.lastweight);
if (numFirstWeight && numLastWeight) {
if (numFirstWeight < numLastWeight) {
setbarWeight(numLastWeight - numFirstWeight);
} else {
setbarWeight(0);
}
}
}, [formik.values.firstweight, formik.values.lastweight]);
return (
<>
<Card>
<Grid
sx={{ alignItems: "baseline" }}
container
direction={"column"}
alignItems="center"
justifyContent={"center"}
gap={SPACING.SMALL}
p={SPACING.MEDIUM}
>
<Grid container gap={SPACING.SMALL}>
<TextField
id="firstweight"
label="وزن ماشین بدون بار باسکول شده"
variant="outlined"
value={formik.values.firstweight}
error={
formik.touched.firstweight
? Boolean(formik.errors.firstweight)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.firstweight && Boolean(formik.errors.firstweight)
? formik.errors.firstweight
: null
}
/>
<Button variant="outlined" startIcon={<UploadIcon />}>
بارگذاری
</Button>
<TextField
id="lastweight"
label="وزن ماشین با بار باسکول شده"
variant="outlined"
value={formik.values.lastweight}
error={
formik.touched.lastweight
? Boolean(formik.errors.lastweight)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.lastweight && Boolean(formik.errors.lastweight)
? formik.errors.lastweight
: null
}
/>
<Button variant="outlined" startIcon={<UploadIcon />}>
بارگذاری
</Button>
<Typography>وزن بار: {barWeight} کیلوگرم</Typography>
</Grid>
</Grid>
<Button
sx={{ marginBottom: "30px" }}
variant="outlined"
disabled={!formik.isValid}
>
ثبت
</Button>
</Card>
</>
);
};

View File

@@ -0,0 +1,87 @@
import { PropTypes } from "prop-types";
// import { Typography } from "@mui/material";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import BankCard from "../../../../components/bank-card/BankCard";
// import { Typography } from "@mui/material";
export const BankAccountInformation = ({
card,
shaba,
info,
price,
priceText,
bankName,
bankUser,
}) => {
return (
<Grid
container
alignItems={"start"}
pl={SPACING.SMALL}
gap={SPACING.SMALL}
mt={SPACING.SMALL}
>
<Grid>
<BankCard
bankName={"بانک " + bankName}
bankUser={bankUser}
cardNumber={card}
expirationDate={"IR" + shaba}
/>
</Grid>
{/* <Grid>
<Grid>
<Typography variant={"body1"} fontWeight={"bold"} color={"primary"}>
اطلاعات بانکی جهت واریز مبلغ:
</Typography>
</Grid>
<Grid container gap={SPACING.MEDIUM}>
<Grid>
<Typography variant={"body2"}>شماره کارت</Typography>
<Typography variant={"body2"} fontWeight={"bold"}>
{card}
</Typography>
</Grid>
<Grid>
<Typography variant={"body2"}>شماره شبا</Typography>
<Typography variant={"body2"} fontWeight={"bold"}>
{shaba}
</Typography>
</Grid>
<Grid>
<Typography variant={"body2"} color="primary">
مبلغ قابل پرداخت
</Typography>
<Typography variant={"body2"} color="primary" fontWeight={"bold"}>
{price?.toLocaleString()} ریال
</Typography>
</Grid>
<Grid>
<Typography variant={"body2"} color="primary">
مبلغ قابل پرداخت به حروف
</Typography>
<Typography variant={"body2"} color="primary" fontWeight={"bold"}>
{priceText}
</Typography>
</Grid>
</Grid>
<Grid>
<Typography variant={"body1"} fontWeight={"bold"}>
{info}
</Typography>
</Grid>
</Grid> */}
</Grid>
);
};
BankAccountInformation.propTypes = {
card: PropTypes.string,
shaba: PropTypes.string,
info: PropTypes.string,
price: PropTypes.any,
priceText: PropTypes.any,
};

View File

@@ -0,0 +1,297 @@
import { Button, TextField, Typography } from "@mui/material";
import React, { useState } from "react";
import { SPACING } from "../../../../data/spacing";
import { AnimatePresence, motion } from "framer-motion";
import {
CLOSE_MODAL,
DRAWER,
LOADING_END,
LOADING_START,
OPEN_MODAL,
} from "../../../../lib/redux/slices/appSlice";
import { checkRequestBySlaughter } from "../../services/checkRequestBySlaughter";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import { useDispatch, useSelector } from "react-redux";
import { PropTypes } from "prop-types";
import { getAllocationInformation } from "../../services/get-allocation-information";
import { Grid } from "../../../../components/grid/Grid";
import { useParams } from "react-router-dom";
import { getAcceptedSlaughterRequest } from "../../services/getAcceptedSlaughterRequest";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { slaughterGetActiveRequests } from "../../../slaughter-house/services/slaughter-get-active-requests";
import { checkPathStartsWith } from "../../../../utils/checkPathStartsWith";
export default function CheckRequestItem({ reqKey, poultryRequestKey }) {
const [openNotif] = useContext(AppContext);
const [isDenyed, setisDenyed] = useState(false);
const dispatch = useDispatch();
const { id } = useParams();
const selectedSubUser = useSelector(
(state) => state.userSlice.selectedSubUser
);
const [, , selectedDate1, , selectedDate2] = useContext(AppContext);
const formik = useFormik({
initialValues: {
rejectText: "",
},
validationSchema: Yup.object({
rejectText: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا دلیل خود را بیان کنید."),
}),
});
const acceptButtonText =
getRoleFromUrl() === "ProvinceOperator"
? "ثبت اطلاعات بجای کشتارگاه"
: "ثبت اطلاعات و ارسال به استان";
const rejectButtonText =
getRoleFromUrl() === "ProvinceOperator"
? "رد اطلاعات بجای کشتارگاه"
: "رد اطلاعات و پیام به استان";
return (
<Grid>
<Grid container gap={SPACING.SMALL} padding={SPACING.SMALL}>
<AnimatePresence>
{isDenyed ? (
<motion.div
animate={{ x: -10, opacity: 1 }}
transition={{ duration: 0.3 }}
initial={{ opacity: 0 }}
exit={{ opacity: 0 }}
>
<Grid flexDirection={"column"} container gap={SPACING.SMALL}>
<Grid>
<TextField
multiline
rows={4}
fullWidth
id="rejectText"
label="پیام خود را وارد کنید"
variant="outlined"
value={formik.values.rejectText}
error={
formik.touched.rejectText
? Boolean(formik.errors.rejectText)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.rejectText &&
Boolean(formik.errors.rejectText)
? formik.errors.rejectText
: null
}
/>
</Grid>
<Grid container gap={SPACING.SMALL}>
<Grid>
<Button
variant="outlined"
color="secondary"
onClick={() => {
setisDenyed(false);
}}
>
لغو
</Button>
</Grid>
<Grid>
<Button
variant="outlined"
onClick={() => {
dispatch(LOADING_START());
dispatch(
checkRequestBySlaughter({
message: formik.values.rejectText,
province_kill_request_key: reqKey,
state: "rejected",
})
).then((r) => {
dispatch(LOADING_END());
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
dispatch(
DRAWER({
right: false,
bottom: false,
top: false,
content: null,
})
);
// getFileFromApi(roles, id, dispatch);
dispatch(
getAcceptedSlaughterRequest({
id,
role_key: checkPathStartsWith("slaughter")
? selectedSubUser?.key || ""
: "",
})
);
setisDenyed(false);
dispatch(
getAllocationInformation({
key: poultryRequestKey,
role_key: checkPathStartsWith("slaughter")
? selectedSubUser?.key || ""
: "",
})
);
dispatch(
slaughterGetActiveRequests({
selectedDate1,
selectedDate2,
role_key: checkPathStartsWith("slaughter")
? selectedSubUser?.key || ""
: "",
})
);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
}}
>
رد اطلاعات و پیام به استان
</Button>
</Grid>
</Grid>
</Grid>
</motion.div>
) : (
<Grid container gap={SPACING.SMALL}>
<Button
variant="outlined"
color="secondary"
onClick={() => {
setisDenyed(true);
}}
>
{rejectButtonText}
</Button>
<Button
variant="outlined"
onClick={() => {
dispatch(LOADING_START());
dispatch(
checkRequestBySlaughter({
province_kill_request_key: reqKey,
state: "accepted",
role: getRoleFromUrl(),
})
).then((r) => {
dispatch(LOADING_END());
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
dispatch(
DRAWER({
right: false,
bottom: false,
top: false,
content: null,
})
);
dispatch(
getAcceptedSlaughterRequest({
id,
role_key: checkPathStartsWith("slaughter")
? selectedSubUser?.key || ""
: "",
})
);
dispatch(
getAllocationInformation({
key: poultryRequestKey,
role_key: checkPathStartsWith("slaughter")
? selectedSubUser?.key || ""
: "",
})
);
dispatch(
slaughterGetActiveRequests({
selectedDate1,
selectedDate2,
role_key: checkPathStartsWith("slaughter")
? selectedSubUser?.key || ""
: "",
})
);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
dispatch(
OPEN_MODAL({
title: "عملیات با موفقیت انجام شد.",
content: (
<Grid
container
direction="column"
gap={SPACING.MEDIUM}
alignItems="center"
justifyContent="center"
>
<Grid>
<Typography color={"green"}>
پرونده به کارتابل (تخصیص خودرو) انتقال پیدا
کرد.
</Typography>
</Grid>
<Grid>
<Button
variant="contained"
color="success"
onClick={() => {
dispatch(CLOSE_MODAL());
}}
>
تایید
</Button>
</Grid>
</Grid>
),
})
);
}
});
}}
>
{acceptButtonText}
</Button>
</Grid>
)}
</AnimatePresence>
</Grid>
</Grid>
);
}
CheckRequestItem.propTypes = {
reqKey: PropTypes.string,
poultryRequestKey: PropTypes.string,
};

View File

@@ -0,0 +1,439 @@
import {
TimelineConnector,
TimelineContent,
// TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import {
Button,
// FormControl,
// FormControlLabel,
// FormLabel,
// Radio,
// RadioGroup,
TextField,
Typography,
} from "@mui/material";
import React, { useState } from "react";
// import { formatTime } from "../../../../utils/formatTime";
import { PropTypes } from "prop-types";
import { SPACING } from "../../../../data/spacing";
import { Grid } from "../../../../components/grid/Grid";
import { AnimatePresence, motion } from "framer-motion";
import { useDispatch } from "react-redux";
import { checkRequestByCity } from "../../services/checkRequestByCity";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import {
CLOSE_MODAL,
DRAWER,
LOADING_END,
LOADING_START,
OPEN_MODAL,
} from "../../../../lib/redux/slices/appSlice";
import useUserProfile from "../../../authentication/hooks/useUserProfile";
import { getFileFromApi } from "../../hooks/useRequestFile";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { avicultureGetRequests } from "../../../aviculture/services/aviculture-requests";
import { getProvinceNewRequests } from "../../../province/services/get-province-new-requests";
import { avicultureRequestsStateProcessService } from "../../../aviculture/services/aviculture-requests-state-process";
const CityFileOperations = ({ id, file, updateTable }) => {
// const myFile = useRequestFile(id);
// const file = myFile?.file?.process;
const [openNotif, , selectedDate1, , selectedDate2, ,] =
useContext(AppContext);
const [isSubmited] = useState(false);
const [roles] = useUserProfile();
// useEffect(() => {
// if (file?.city !== null) {
// setIsSubmited(true);
// }
// }, []);
const formik = useFormik({
initialValues: {
rejectText: "",
canHaching: "False",
},
validationSchema: Yup.object({
rejectText: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا دلیل خود را بیان کنید."),
}),
});
const [isDenyed, setisDenyed] = useState(false);
const showHatchingAllowed =
file?.hatching?.allowHatching === "pending" &&
file?.hatching?.leftOver !== 0;
const buttonState = !formik.values.canHaching && showHatchingAllowed;
// const animationControl = useAnimation();
// useEffect(() => {
// if (isDenyed) {
// animationControl.start({
// x: -10,
// display: "block",
// transition: { duration: 0.3 },
// });
// }
// }, [isDenyed]);
// const MotionInput = motion(TextField);
const dispatch = useDispatch();
const acceptButtonText =
getRoleFromUrl() === "ProvinceOperator"
? "تایید اطلاعات بجای شهرستان"
: "ثبت اطلاعات و ارسال به استان";
return (
<>
{!isSubmited && (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color="secondary" />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1" xs={12}>
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
انجام عملیات
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Typography variant="body2">
در این مرحله درخواست را تایید یا رد کنید.
</Typography>
</TimelineContent>
</Grid>
</Grid>
<Grid container xs={12}>
<Grid xs={12}>
<Grid
container
gap={SPACING.SMALL}
padding={SPACING.SMALL}
xs={12}
>
<AnimatePresence>
{isDenyed ? (
<motion.div
animate={{ x: -10, opacity: 1 }}
transition={{ duration: 0.3 }}
initial={{ opacity: 0 }}
exit={{ opacity: 0 }}
>
<Grid
flexDirection={"column"}
container
gap={SPACING.SMALL}
xs={12}
>
<Grid>
<TextField
multiline
rows={4}
fullWidth
id="rejectText"
label="پیام خود را وارد کنید"
variant="outlined"
value={formik.values.rejectText}
error={
formik.touched.rejectText
? Boolean(formik.errors.rejectText)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.rejectText &&
Boolean(formik.errors.rejectText)
? formik.errors.rejectText
: null
}
/>
</Grid>
<Grid container gap={SPACING.SMALL} xs={12}>
<Grid>
<Button
fullWidth
variant="outlined"
color="secondary"
onClick={() => {
setisDenyed(false);
}}
>
لغو
</Button>
</Grid>
<Grid container xs={12}>
<Button
fullWidth
disabled={!formik.values.rejectText}
variant="outlined"
onClick={() => {
dispatch(LOADING_START());
dispatch(
checkRequestByCity({
message: formik.values.rejectText,
key: file?.key,
allow_hatching: formik.values.canHaching,
state: "reject",
role: getRoleFromUrl(),
})
).then((r) => {
if (updateTable) {
updateTable();
}
dispatch(
getProvinceNewRequests({
selectedDate1,
selectedDate2,
})
);
dispatch(
avicultureGetRequests({
selectedDate1,
selectedDate2,
})
);
getFileFromApi(roles, id, dispatch);
dispatch(LOADING_END());
// if (r.error) {
// } else {
// }
});
}}
>
رد اطلاعات و پیام به مرغدار
</Button>
</Grid>
</Grid>
</Grid>
</motion.div>
) : (
<Grid
container
direction="column"
alignItems="start"
gap={SPACING.SMALL}
>
<Grid
container
gap={SPACING.TINY}
direction="column"
alignItems="start"
>
<Grid container gap={SPACING.TINY}>
<Typography variant="body2" fontWeight="bold">
تعداد درخواست کشتار:
</Typography>
<Typography>
{file?.quantity?.toLocaleString()} قطعه
</Typography>
</Grid>
<Grid container gap={SPACING.TINY}>
<Typography variant="body2" fontWeight="bold">
تعداد باقی مانده از جوجه ریزی:
</Typography>
<Typography>
{file?.hatching?.leftOver?.toLocaleString()} قطعه
</Typography>
</Grid>
{!!showHatchingAllowed && (
<Grid
container
gap={SPACING.TINY}
alignItems="start"
>
{/* <Grid container textAlign="start">
<FormControl>
<FormLabel id="demo-row-radio-buttons-group-label">
مرغدار اجازه جوجه ریزی ......
</FormLabel>
<RadioGroup
row
aria-labelledby="demo-row-radio-buttons-group-label"
name="row-radio-buttons-group"
onChange={(event) => {
formik.setFieldValue(
"canHaching",
event.currentTarget.value
);
}}
value={formik.values.canHaching}
>
<FormControlLabel
value="True"
control={<Radio />}
label="دارد"
/>
<FormControlLabel
value="False"
control={<Radio />}
label="ندارد"
/>
</RadioGroup>
<Grid>
<Typography variant="button">
مرغ دار اجازه جوجه ریزی دارد بدین معناست
که باقی مانده مرغ صفر در نظر گرفته می شود
و مرغ دار اجازه جوجه ریزی برای سالن خود را
خواهد داشت.
</Typography>
</Grid>
</FormControl>
</Grid> */}
</Grid>
)}
</Grid>
<Grid container gap={SPACING.SMALL} xs={12}>
<Button
fullWidth
disabled={buttonState}
variant="outlined"
color="error"
onClick={() => {
setisDenyed(true);
}}
>
رد اطلاعات و پیام به مرغدار
</Button>
<Grid xs={12}>
<Button
fullWidth
disabled={buttonState}
variant="outlined"
onClick={() => {
dispatch(LOADING_START());
dispatch(
checkRequestByCity({
key: file?.key,
allow_hatching: formik.values.canHaching,
state: "accept",
role: getRoleFromUrl(),
})
).then((r) => {
getFileFromApi(roles, id, dispatch);
dispatch(LOADING_END());
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
if (updateTable) {
updateTable();
}
dispatch(
getProvinceNewRequests({
selectedDate1,
selectedDate2,
})
);
dispatch(
avicultureGetRequests({
selectedDate1,
selectedDate2,
})
);
dispatch(
avicultureRequestsStateProcessService({
selectedDate1,
selectedDate2,
})
);
dispatch(
DRAWER({
right: false,
bottom: false,
content: null,
})
);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
if (
getRoleFromUrl() === "ProvinceOperator"
) {
dispatch(
OPEN_MODAL({
title: "عملیات با موفقیت انجام شد.",
content: (
<Grid
xs={12}
container
direction="column"
gap={SPACING.MEDIUM}
alignItems="center"
justifyContent="center"
>
<Grid>
<Typography color={"green"}>
پرونده به کارتابل (در انتظار
تخصیص) انتقال پیدا کرد.
</Typography>
</Grid>
<Grid>
<Button
variant="contained"
color="success"
onClick={() => {
dispatch(CLOSE_MODAL());
}}
>
تایید
</Button>
</Grid>
</Grid>
),
})
);
}
}
});
}}
>
{acceptButtonText}
</Button>
</Grid>
</Grid>
</Grid>
)}
</AnimatePresence>
</Grid>
</Grid>
</Grid>
</Grid>
</TimelineItem>
)}
</>
);
};
CityFileOperations.propTypes = {
file: PropTypes.object,
};
export default CityFileOperations;

View File

@@ -0,0 +1,153 @@
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { PropTypes } from "prop-types";
import { useEffect, useState } from "react";
import TimelineSeparator from "@mui/lab/TimelineSeparator";
import TimelineDot from "@mui/lab/TimelineDot";
import TimelineConnector from "@mui/lab/TimelineConnector";
import { Grid } from "../../../../components/grid/Grid";
import TimelineOppositeContent from "@mui/lab/TimelineOppositeContent";
import { Typography } from "@mui/material";
import TimelineContent from "@mui/lab/TimelineContent";
import { SPACING } from "../../../../data/spacing";
import TimelineItem from "@mui/lab/TimelineItem";
import { formatTime } from "../../../../utils/formatTime";
import { format } from "date-fns-jalali";
export const CityInformation = ({ file }) => {
const [cityInfoData, setCityInfo] = useState({
cityOperatorName: "اپراتور شهرستان",
cityOperatorMobile: "-",
cityUnionName: "-",
acceptedRejectedDate: "",
cityState: "در انتظار تایید",
});
const { city, cityOperator } = file;
useEffect(() => {
let cityOperatorName,
cityOperatorMobile,
acceptedRejectedDate,
cityState,
cityUnionName;
if (city) {
cityOperatorName = city.cityOperatorName;
cityOperatorMobile = city.cityOperatorMobile;
acceptedRejectedDate = city.acceptedRejectedDate;
cityUnionName = city.unitName;
cityState = city.cityState === "accept" ? "تایید شده" : "رد شده";
} else {
cityOperatorName = cityOperator?.cityOperatorName;
cityOperatorMobile = cityOperator.cityOperatorMobile;
cityUnionName = cityOperator.unitName;
acceptedRejectedDate = null;
cityState = "در انتظار تایید";
}
setCityInfo({
cityOperatorName,
cityOperatorMobile,
acceptedRejectedDate,
cityUnionName,
cityState,
});
}, [city]);
return (
<>
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
مرحله شهرستان
</Typography>
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Grid container gap={SPACING.SMALL}>
<Grid container gap={SPACING.SMALL}>
{cityInfoData.cityState === "در انتظار تایید" ? (
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
درخواست منتظر انجام عملیات توسط اپراتور می باشد.
</Typography>
) : (
<>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
درخواست در تاریخ
</Typography>
<Typography variant="body2" fontWeight="bold">
{cityInfoData.acceptedRejectedDate
? formatTime(cityInfoData.acceptedRejectedDate)
: "-"}
</Typography>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
{cityInfoData.cityState} است.
</Typography>
</>
)}
</Grid>
</Grid>
</TimelineContent>
</Grid>
</Grid>
<Grid>
<Grid xs={12}>
<SimpleTable
columns={[
"نام اپراتور",
"نام اتحادیه",
"تلفن",
"استان",
"شهر",
"تاریخ بررسی",
"وضعیت",
city?.cityOperatorMessage ? "دلیل رد" : "",
]}
data={[
[
cityInfoData.cityOperatorName,
cityInfoData.cityUnionName,
cityInfoData.cityOperatorMobile,
cityOperator.cityOperatorProvince,
cityOperator.cityOperatorCity,
cityInfoData?.acceptedRejectedDate
? format(
new Date(cityInfoData?.acceptedRejectedDate),
"yyyy/MM/dd"
)
: "",
city?.provinceAccept
? "تایید شده توسط استان"
: cityInfoData.cityState,
city?.cityOperatorMessage ? city?.cityOperatorMessage : "",
],
]}
/>
</Grid>
</Grid>
</Grid>
</TimelineItem>
</>
);
};
CityInformation.propTypes = {
file: PropTypes.any,
};

View File

@@ -0,0 +1,79 @@
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { PropTypes } from "prop-types";
import { useEffect, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { format } from "date-fns-jalali";
export const CityInformationContent = ({ file }) => {
const [cityInfoData, setCityInfo] = useState({
cityOperatorName: "اپراتور شهرستان",
cityOperatorMobile: "-",
cityUnionName: "-",
acceptedRejectedDate: "",
cityState: "در انتظار تایید",
});
const { city, cityOperator } = file;
useEffect(() => {
let cityOperatorName,
cityOperatorMobile,
acceptedRejectedDate,
cityState,
cityUnionName;
if (city) {
cityOperatorName = city.cityOperatorName;
cityOperatorMobile = city.cityOperatorMobile;
acceptedRejectedDate = city.acceptedRejectedDate;
cityUnionName = city.unitName;
cityState = city.cityState === "accept" ? "تایید شده" : "رد شده";
} else {
cityOperatorName = cityOperator?.cityOperatorName;
cityOperatorMobile = cityOperator.cityOperatorMobile;
cityUnionName = cityOperator.unitName;
acceptedRejectedDate = null;
cityState = "در انتظار تایید";
}
setCityInfo({
cityOperatorName,
cityOperatorMobile,
acceptedRejectedDate,
cityUnionName,
cityState,
});
}, [city]);
return (
<Grid xs={12}>
<SimpleTable
columns={[
"نام اپراتور",
"نام اتحادیه",
"تلفن",
"استان",
"شهر",
"تاریخ بررسی",
"وضعیت",
city?.cityOperatorMessage ? "دلیل رد" : "",
]}
data={[
[
cityInfoData.cityOperatorName,
cityInfoData.cityUnionName,
cityInfoData.cityOperatorMobile,
cityOperator.cityOperatorProvince,
cityOperator.cityOperatorCity,
format(new Date(cityInfoData.acceptedRejectedDate), "yyyy/MM/dd"),
city?.provinceAccept
? "تایید شده توسط استان"
: cityInfoData.cityState,
city?.cityOperatorMessage ? city?.cityOperatorMessage : "",
],
]}
/>
</Grid>
);
};
CityInformationContent.propTypes = {
file: PropTypes.any,
};

View File

@@ -0,0 +1,96 @@
import { PropTypes } from "prop-types";
import { useEffect, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import TimelineOppositeContent from "@mui/lab/TimelineOppositeContent";
import { Typography } from "@mui/material";
import TimelineContent from "@mui/lab/TimelineContent";
import { SPACING } from "../../../../data/spacing";
import { formatTime } from "../../../../utils/formatTime";
export const CityInformationTitle = ({ file }) => {
const [cityInfoData, setCityInfo] = useState({
cityOperatorName: "اپراتور شهرستان",
cityOperatorMobile: "-",
acceptedRejectedDate: "",
cityState: "در انتظار تایید",
});
const { city, cityOperator } = file;
useEffect(() => {
let cityOperatorName, cityOperatorMobile, acceptedRejectedDate, cityState;
if (city) {
cityOperatorName = city.cityOperatorName;
cityOperatorMobile = city.cityOperatorMobile;
acceptedRejectedDate = city.acceptedRejectedDate;
cityState = city.cityState === "accept" ? "تایید شده" : "رد شده";
} else {
cityOperatorName = cityOperator?.cityOperatorName;
cityOperatorMobile = cityOperator.cityOperatorMobile;
acceptedRejectedDate = null;
cityState = "در انتظار تایید";
}
setCityInfo({
cityOperatorName,
cityOperatorMobile,
acceptedRejectedDate,
cityState,
});
}, [city]);
return (
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
مرحله شهرستان
</Typography>
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Grid container gap={SPACING.SMALL}>
<Grid container gap={SPACING.SMALL}>
{cityInfoData.cityState === "در انتظار تایید" ? (
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
درخواست منتظر انجام عملیات توسط اپراتور می باشد.
</Typography>
) : (
<>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
درخواست در تاریخ
</Typography>
<Typography variant="body2" fontWeight="bold">
{cityInfoData.acceptedRejectedDate
? formatTime(cityInfoData.acceptedRejectedDate)
: "-"}
</Typography>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
{cityInfoData.cityState} است.
</Typography>
</>
)}
</Grid>
</Grid>
</TimelineContent>
</Grid>
</Grid>
</Grid>
);
};
CityInformationTitle.propTypes = {
file: PropTypes.any,
};

View File

@@ -0,0 +1,424 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Button, Typography } from "@mui/material";
import React, { useEffect } from "react";
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { SPACING } from "../../../../data/spacing";
import { formatTime } from "../../../../utils/formatTime";
import moment from "moment";
import { Timer } from "../../../../components/timer/Timer";
import { useDispatch, useSelector } from "react-redux";
import { avicultureGetChickenPrice } from "../../../aviculture/services/aviculture-get-chicken-price";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
// import { useSelector } from "react-redux";
import CloseIcon from "@mui/icons-material/Close";
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
import { CloseFileSubmitInfo } from "../close-file-submit-info/CloseFileSubmitInfo";
const CloseFileFinancialInfo = ({ data, auction }) => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(avicultureGetChickenPrice());
}, []);
const { avicultureChickenPrice } = useSelector(
(state) => state.avicultureSlice
);
const liveChickenPrice = avicultureChickenPrice?.liveChickenPrice;
let barInfoColumns,
barInfoData,
financialColumns,
financialColumnsCash,
financialData,
financialDataCash;
const paymentDate = moment(new Date(data.paymentDeadLine));
const currentDate = moment();
const diff = paymentDate.diff(currentDate);
const paymentRemainedSeconds = moment.duration(diff).asSeconds();
if (auction) {
// columns = [
// "کشتارگاه",
// "تعداد",
// "نام راننده",
// "ماشین",
// "وزن بار",
// "سند خودرو بدون بار",
// "سند خودرو با بار",
// "وضعیت",
// ];
// item = [
// [
// data.quantity + " قطعه",
// data.cars.driverName + ` (${data.cars.driverMobile})`,
// `${data.cars.typeCar} با پلاک ${data.cars.pelak}`,
// data.barInfo.killHouseNetWeight + " کیلوگرم",
// data.barInfo.killHouseNetWeight + " کیلوگرم",
// <a
// href={data.barInfo.killHouseImageWithoutLoad}
// alt="دانلود سند خودرو بدون بار"
// key="provinceKillRequests"
// >
// <img
// src={data.barInfo.killHouseImageWithoutLoad}
// width="50"
// height="50"
// alt="بدون بار"
// className="images-file"
// />
// </a>,
// <a
// href={data.barInfo.killHouseImageWithLoad}
// alt="دانلود سند خودرو با بار"
// key="provinceKillRequests"
// >
// <img
// src={data.barInfo.killHouseImageWithLoad}
// width="50"
// height="50"
// alt="بدون بار"
// className="images-file"
// key="provinceKillRequests"
// />
// </a>,
// !data.killHouseFactorToProvince && data.provinceFactorToKillHouse
// ? "در انتظار پرداخت کشتارگاه"
// : "پرداخت شده توسط کشتارگاه",
// ],
// ];
} else {
let state;
state =
!data.killHouseFactorToProvince && !data.provinceFactorToKillHouse
? "در انتظار تایید مالی"
: state;
state =
!data.killHouseFactorToProvince && data.provinceFactorToKillHouse
? "در انتظار پرداخت کشتارگاه"
: state;
state =
data.killHouseFactorToProvince && data.provinceFactorToKillHouse
? "پرداخت شده توسط کشتارگاه"
: state;
let timerState;
const isFactorPayed =
data.killHouseFactorToProvince?.factorState === "accepted" ||
data.killHouseFactorToPoultry?.factorState === "accepted";
const timer = data && (
<Timer
key="finincalTimer"
isFilePaymentTime={true}
seconds={paymentRemainedSeconds}
/>
);
const isPaymentFactorPending =
!data.killHouseFactorToProvince &&
!data.provinceFactorToKillHouseForPoultry;
const isPaymentPendingAndTimerEnabled = Boolean(data.paymentDeadLine);
// if (
// !data.provinceFactorToKillHouse ||
// !data.provinceFactorToKillHouseForPoultry
// ) {
// timerState = "در انتظار تایید مالی";
// } else if (isFactorPayed) {
// timerState = "پرداخت شده ✔";
// } else if (isPaymentPendingAndTimerEnabled) {
// timerState = timer;
// } else if (isPaymentPending) {
// timerState = "در انتظار صدور تمامی فاکتورها";
// }
if (isPaymentPendingAndTimerEnabled) {
timerState = timer;
} else if (isPaymentFactorPending) {
timerState = "در انتظار تایید مالی";
} else {
timerState = "در انتظار صدور تمامی فاکتورها";
}
if (isFactorPayed) {
timerState = "پرداخت شده ✔";
}
barInfoColumns = [
"کشتارگاه",
"نام راننده",
"ماشین",
"نوع خرید",
"سند خودرو بدون بار",
"سند خودرو با بار",
"تعداد",
"وزن بار",
"میانگین وزن",
"عملیات",
];
barInfoData = [
[
`${data.killHouseName} (${data.killHouseUserProvince}/${data.killHouseUserCity})`,
data.cars?.driverName + ` (${data.cars?.driverMobile})`,
`${data.cars?.typeCar} با پلاک ${data.cars?.pelak}`,
`${data.paymentType === "credit" ? "زمان دار" : "نقدی"}`,
<a
style={{ textDecoration: "none", color: "black" }}
href={data.barInfo.killHouseImageWithoutLoad}
alt="دانلود سند خودرو بدون بار"
key="provinceKillRequests"
>
<img
src={data.barInfo.killHouseImageWithoutLoad}
width="50"
height="50"
alt="بدون بار"
className="images-file"
/>
<p>{data.barInfo.killHouseWeightWithoutLoad} کیلوگرم</p>
</a>,
<a
style={{ textDecoration: "none", color: "black" }}
href={data.barInfo.killHouseImageWithLoad}
alt="دانلود سند خودرو با بار"
key="provinceKillRequests"
>
<img
src={data.barInfo.killHouseImageWithLoad}
width="50"
height="50"
alt="بدون بار"
className="images-file"
key="provinceKillRequests"
/>
<p>{data.barInfo.killHouseWeightWithLoad} کیلوگرم</p>
</a>,
data.quantity + " قطعه",
data.barInfo.killHouseNetWeight + " کیلوگرم",
(data.barInfo.killHouseNetWeight / data.quantity).toFixed(2) +
" کیلوگرم",
<Button
onClick={() => {
dispatch(
DRAWER({
right: !(window.innerWidth <= 600),
bottom: window.innerWidth <= 600,
content: (
<CloseFileSubmitInfo
killHouseImageWithLoad={data.barInfo.killHouseImageWithLoad}
killHouseWeightWithoutLoad={
data.barInfo.killHouseWeightWithoutLoad
}
realQuantity={data.quantity}
/>
),
title: " بستن پرونده",
})
);
}}
variant="outlined"
key={"closefile"}
startIcon={<CloseIcon />}
>
بستن پرونده
</Button>,
],
];
financialColumns = [
"قیمت روز",
"قیمت هرکیلو",
"سهم مرغدار",
"سهم اتحادیه",
"مانده تا سررسید 30 روزه",
"سهم مرغدار با ضریب سود",
"سهم اتحادیه با ضریب سود",
"جمع مبلغ قابل پرداخت",
"وضعیت",
"جریمه مرغدار",
"جریمه کشتارگاه",
];
let poultryShareWithProfit;
if (data.provinceFactorToKillHouse?.poultryShareWithProfit) {
poultryShareWithProfit =
data.provinceFactorToKillHouse?.poultryShareWithProfit;
} else if (
data.provinceFactorToKillHouseForPoultry?.poultryShareWithProfit
) {
poultryShareWithProfit =
data.provinceFactorToKillHouseForPoultry?.poultryShareWithProfit;
}
financialData = [
[
liveChickenPrice + " ﷼",
data.provinceFactorToKillHouse
? data.provinceFactorToKillHouse.provinceFactorFee + " ریال"
: "نامشخص",
data.provinceFactorToKillHouse
? data.provinceFactorToKillHouse.provinceFactorFee *
data.barInfo.killHouseNetWeight +
" ریال"
: "نامشخص",
data.provinceFactorToKillHouse?.totalShareAllocation
? data.provinceFactorToKillHouse?.totalShareAllocation + " ریال"
: "نامشخص",
timerState,
poultryShareWithProfit ? `${poultryShareWithProfit} ریال` : "نامشخص",
data.provinceFactorToKillHouse?.unionShareWithProfit
? `${data.provinceFactorToKillHouse?.unionShareWithProfit} ریال`
: "نامشخص",
data.provinceFactorToKillHouse?.cost
? `${
data.provinceFactorToKillHouse?.cost +
data.provinceFactorToKillHouse?.poultryShareWithProfit
} ریال`
: "نامشخص",
state,
],
];
financialColumnsCash = [
"قیمت روز",
"قیمت هرکیلو",
"سهم مرغدار",
"سهم اتحادیه",
"مبلغ قابل پرداخت",
"وضعیت",
];
let pricePayment;
if (data.provinceFactorToKillHouse?.cost) {
pricePayment = `${data.provinceFactorToKillHouse?.cost} ریال`;
} else if (data.provinceFactorToKillHouseForPoultry?.cost) {
pricePayment = `${data.provinceFactorToKillHouseForPoultry?.cost} ریال`;
} else {
pricePayment = "نامشخص";
}
financialDataCash = [
[
liveChickenPrice + " ﷼",
data.provinceFactorToKillHouse
? data.provinceFactorToKillHouse.provinceFactorFee + " ریال"
: "ندارد",
// data.provinceFactorToKillHouse
// ? data.provinceFactorToKillHouse.provinceFactorFee *
// data.barInfo.killHouseNetWeight +
// " ریال"
// : "ندارد",
poultryShareWithProfit ? `${poultryShareWithProfit} ریال` : "نامشخص",
data.provinceFactorToKillHouse?.totalShareAllocation
? data.provinceFactorToKillHouse?.totalShareAllocation + " ریال"
: "نامشخص",
pricePayment,
state,
],
];
// remove payment fields for aviculture
const urlRole = getRoleFromUrl();
if (urlRole === "Poultry") {
financialColumnsCash.splice(5, 3);
financialDataCash[0]?.splice(5, 3);
financialColumns.splice(5, 4);
financialData[0]?.splice(5, 4);
}
}
return (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
مرحله مالی
</Typography>
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Grid container gap={SPACING.SMALL}>
{data.barInfo.killHouseAssignmentState === "pending" ? (
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
درخواست در انتظار تایید اپراتور مالی است.
</Typography>
) : (
<>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
درخواست در تاریخ
</Typography>
<Typography variant="body2" fontWeight="bold">
{formatTime(new Date(data.barInfo.acceptRejectDate))}
</Typography>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
{data.barInfo.killHouseAssignmentState === "accepted"
? "تایید شده است."
: data.barInfo.killHouseAssignmentState === "pending"
? "در انتظار تایید"
: "رد شده است."}
</Typography>
</>
)}
</Grid>
</TimelineContent>
</Grid>
</Grid>
<Grid container>
<Grid xs={12}>
<SimpleTable
name={`اطلاعات بار ${data.barcod}`}
columns={barInfoColumns}
data={barInfoData}
/>
{data.paymentType === "cash" ? (
<SimpleTable
name="اطلاعات مالی"
columns={financialColumnsCash}
data={financialDataCash}
/>
) : (
<SimpleTable
name="اطلاعات مالی"
columns={financialColumns}
data={financialData}
/>
)}
</Grid>
</Grid>
</Grid>
</TimelineItem>
);
};
CloseFileFinancialInfo.propTypes = {
item: PropTypes.array,
data: PropTypes.any,
auction: PropTypes.bool,
};
export default CloseFileFinancialInfo;

View File

@@ -0,0 +1,346 @@
import {
Button,
Checkbox,
Divider,
FormControl,
FormControlLabel,
FormLabel,
Radio,
RadioGroup,
TextField,
Typography,
} from "@mui/material";
import { useFormik } from "formik";
import React, { useEffect } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { ImageUpload } from "../../../../components/image-upload/ImageUpload";
import { SPACING } from "../../../../data/spacing";
import { Yup } from "../../../../lib/yup/yup";
import { fixBase64 } from "../../../../utils/toBase64";
export const CloseFileSubmitInfo = () => {
const [closeFileWeightWithoutBar, setCloseFileWeightWithoutBar] =
React.useState([]);
const [closeFileWeightWithoutBarBase64, setCloseFileWeightWithoutBarBase64] =
React.useState([]);
const closeFileWeightWithoutBarHandler = (imageList, addUpdateIndex) => {
setCloseFileWeightWithoutBar(imageList);
setCloseFileWeightWithoutBarBase64(
imageList.map((img) => fixBase64(img.data_url))
);
};
const [closeFileWeightWithBar, setCloseFileWeightWithBar] = React.useState(
[]
);
const [closeFileWeightWithBarBase64, setCloseFileWeightWithBarBase64] =
React.useState([]);
const closeFileWeightWithBarHandler = (imageList, addUpdateIndex) => {
setCloseFileWeightWithBar(imageList);
setCloseFileWeightWithBarBase64(
imageList.map((img) => fixBase64(img.data_url))
);
};
const [closeWithNoOperation, setCloseWithNoOperation] = React.useState(false);
const handleToggle = () => {
setCloseWithNoOperation(!closeWithNoOperation);
};
const isFormValid = (closeWithNoOperation) => {
if (closeWithNoOperation) {
return false;
} else {
return !formik.isValid;
}
};
const formik = useFormik({
initialValues: {
pultrypenalty: "",
killHousepenalty: "",
image: "",
carweightwithbar: "",
carweightwithoutbar: "",
payablemoney: "",
realLoadCount: "",
},
validationSchema: Yup.object({
pultrypenalty: Yup.number().typeError("لطفا عدد وارد کنید!"),
killHousepenalty: Yup.number().typeError("لطفا عدد وارد کنید!"),
carweightwithbar: Yup.number().typeError("لطفا عدد وارد کنید!"),
carweightwithoutbar: Yup.number().typeError("لطفا عدد وارد کنید!"),
payablemoney: Yup.number().typeError("لطفا عدد وارد کنید!"),
realLoadCount: Yup.number().typeError("لطفا عدد وارد کنید!"),
image: Yup.string().typeError("لطفا تصویر را وارد کنید!"),
}),
});
useEffect(() => {
formik.validateForm();
}, []);
return (
<Grid
className="slaughter-new-request-form"
container
gap={SPACING.SMALL}
direction="column"
flex="1"
justifyContent="space-between"
>
<Grid container gap={SPACING.SMALL} direction="column">
<FormControlLabel
control={<Checkbox onClick={handleToggle} />}
label="کد بار بدون اقدام بسته شود"
/>
<Divider />
<Grid
sx={{
opacity: closeWithNoOperation ? "60%" : "100%",
color: closeWithNoOperation ? "red" : "black",
}}
container
gap={SPACING.SMALL}
direction="column"
>
<Typography variant="body1">اطلاعات جریمه</Typography>
<TextField
disabled={closeWithNoOperation}
fullWidth
id="pultrypenalty"
label="جریمه مرغدار"
value={formik.values.pultrypenalty}
error={
formik.touched.pultrypenalty
? Boolean(formik.errors.pultrypenalty)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.pultrypenalty &&
Boolean(formik.errors.pultrypenalty)
? formik.errors.pultrypenalty
: null
}
autoComplete="current-password"
variant="outlined"
/>
<Typography variant="body2" color="primary">
پیشنهاد قیمت: 1400,000,000
</Typography>
<TextField
disabled={closeWithNoOperation}
fullWidth
id="killHousepenalty"
label="جریمه کشتارگاه"
value={formik.values.killHousepenalty}
error={
formik.touched.killHousepenalty
? Boolean(formik.errors.killHousepenalty)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.killHousepenalty &&
Boolean(formik.errors.killHousepenalty)
? formik.errors.killHousepenalty
: null
}
autoComplete="current-password"
variant="outlined"
/>
<Typography variant="body2" color="primary">
پیشنهاد قیمت: 1400,000,000
</Typography>
<Divider />
<Typography variant="body1">اطلاعات بار</Typography>
<TextField
disabled={closeWithNoOperation}
size="small"
fullWidth
id="realLoadCount"
label="تعداد واقعی بارگیری"
value={formik.values.realLoadCount}
error={
formik.touched.realLoadCount
? Boolean(formik.errors.realLoadCount)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.realLoadCount &&
Boolean(formik.errors.realLoadCount)
? formik.errors.realLoadCount
: null
}
autoComplete="current-password"
variant="outlined"
/>
<TextField
disabled={closeWithNoOperation}
size="small"
fullWidth
id="carweightwithoutbar"
label="وزن ماشین بدون بار"
value={formik.values.carweightwithoutbar}
error={
formik.touched.carweightwithoutbar
? Boolean(formik.errors.carweightwithoutbar)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.carweightwithoutbar &&
Boolean(formik.errors.carweightwithoutbar)
? formik.errors.carweightwithoutbar
: null
}
autoComplete="current-password"
variant="outlined"
/>
<TextField
disabled={closeWithNoOperation}
size="small"
fullWidth
id="carweightwithbar"
label="وزن ماشین با بار"
value={formik.values.carweightwithbar}
error={
formik.touched.carweightwithbar
? Boolean(formik.errors.carweightwithbar)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.carweightwithbar &&
Boolean(formik.errors.carweightwithbar)
? formik.errors.carweightwithbar
: null
}
autoComplete="current-password"
variant="outlined"
/>
<Grid
container
direction="column"
alignItems="start"
gap={SPACING.SMALL}
>
<Typography variant="body2">
تصویر سند وزن خودرو بدون بار
</Typography>
<ImageUpload
disabled={closeWithNoOperation}
id="image"
onChange={closeFileWeightWithoutBarHandler}
images={closeFileWeightWithoutBar}
maxNumber={4}
title={"بارگذاری سند وزن خودرو بدون بار"}
value={formik.values.image}
error={formik.touched.image ? Boolean(formik.errors.image) : null}
onBlur={formik.handleBlur}
helperText={
formik.touched.image && Boolean(formik.errors.image)
? formik.errors.image
: null
}
/>
<Typography variant="body2">تصویر سند وزن خودرو با بار</Typography>
<ImageUpload
disabled={closeWithNoOperation}
id="image"
onChange={closeFileWeightWithBarHandler}
images={closeFileWeightWithBar}
maxNumber={4}
title={"بارگذاری سند وزن خودرو با بار"}
value={formik.values.image}
error={formik.touched.image ? Boolean(formik.errors.image) : null}
onBlur={formik.handleBlur}
helperText={
formik.touched.image && Boolean(formik.errors.image)
? formik.errors.image
: null
}
/>
</Grid>
<Divider />
<TextField
disabled={closeWithNoOperation}
fullWidth
id="payablemoney"
label="مبلغ قابل پرداخت"
value={formik.values.payablemoney}
error={
formik.touched.payablemoney
? Boolean(formik.errors.payablemoney)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.payablemoney && Boolean(formik.errors.payablemoney)
? formik.errors.payablemoney
: null
}
autoComplete="current-password"
variant="outlined"
/>
<Typography variant="body2" color="primary">
پیشنهاد قیمت: 1400,000,000
</Typography>
<Typography variant="body1" color="primary">
مبلغ قابل پرداخت: 1400,000,000
</Typography>
<FormControl disabled={closeWithNoOperation}>
<FormLabel id="demo-radio-buttons-group-label">
نوع پرداخت
</FormLabel>
<RadioGroup
aria-labelledby="demo-radio-buttons-group-label"
defaultValue="cash"
name="radio-buttons-group"
>
<FormControlLabel value="cash" control={<Radio />} label="نقدی" />
<FormControlLabel
value="credit"
control={<Radio />}
label="زماندار"
/>
</RadioGroup>
</FormControl>
</Grid>
<Button
disabled={isFormValid(closeWithNoOperation)}
variant="contained"
>
ثبت
</Button>
</Grid>
</Grid>
);
};

View File

@@ -0,0 +1,137 @@
import { Button } from "@mui/material";
import { useFormik } from "formik";
import { useContext, useEffect, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { ImageUpload } from "../../../../components/image-upload/ImageUpload";
import { NumberInput } from "../../../../components/number-format-custom/NumberFormatCustom";
import { SPACING } from "../../../../data/spacing";
import { Yup } from "../../../../lib/yup/yup";
import { fixBase64 } from "../../../../utils/toBase64";
import { PropTypes } from "prop-types";
import { useDispatch } from "react-redux";
import {
CLOSE_MODAL,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { depositeAllocation } from "../../services/deposite-allocation";
import { AppContext } from "../../../../contexts/AppContext";
import { provinceFinancialGetFinalFactorsService } from "../../../province-finacial/services/province-financial-get-final-factors-service";
export const FactorPaymentShareDrawer = ({
share,
allocationKey,
paymentPrice,
fileId,
}) => {
const [openNotif] = useContext(AppContext);
const dispatch = useDispatch();
const formik = useFormik({
initialValues: {
factorImg: "",
payment: paymentPrice,
},
validationSchema: Yup.object({
factorImg: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا عدد وارد کنید!"),
payment: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا عدد وارد کنید!"),
}),
});
const [factorImgs, setFactorImgs] = useState([]);
const factorImgHandler = (imageList, addUpdateIndex) => {
if (imageList[0]) {
formik.setFieldValue("factorImg", fixBase64(imageList[0]?.data_url));
} else {
formik.setFieldValue("factorImg", "");
}
setFactorImgs(imageList);
};
useEffect(() => {
formik.validateForm();
}, []);
return (
<Grid container gap={SPACING.SMALL} justifyContent="center">
<NumberInput
allowLeadingZeros
thousandSeparator=","
fullWidth
label="مبلغ پرداختی"
name="payment"
id="payment"
variant="outlined"
InputProps={{
readOnly: true,
}}
value={formik.values.payment}
error={formik.touched.payment ? Boolean(formik.errors.payment) : null}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.payment && Boolean(formik.errors.payment)
? formik.errors.payment
: null
}
/>
<Grid>
<ImageUpload
onChange={factorImgHandler}
images={factorImgs}
maxNumber={1}
title={"بارگذاری سند"}
/>
</Grid>
<Button
fullWidth
variant="contained"
disabled={!formik.isValid}
onClick={() => {
dispatch(LOADING_START());
dispatch(
depositeAllocation({
key: allocationKey,
type: share,
image: formik.values.factorImg,
payment: formik.values.payment,
})
).then((r) => {
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
dispatch(provinceFinancialGetFinalFactorsService());
dispatch(CLOSE_MODAL());
dispatch(LOADING_END());
// getFileFromApi(roles, fileId, dispatch);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
}}
>
ثبت
</Button>
</Grid>
);
};
FactorPaymentShareDrawer.propTypes = {
share: PropTypes.string,
allocationKey: PropTypes.string,
paymentPrice: PropTypes.any,
fileId: PropTypes.any,
};

View File

@@ -0,0 +1,96 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Typography } from "@mui/material";
import React from "react";
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { Timer } from "../../../../components/timer/Timer";
import moment from "moment";
const FileAuctionStatus = ({ file }) => {
const { ceilingPrice, floorPrice, date, fee, index, totalIndex } =
file.auctionsList[0];
const { fee: highestBid } = file?.killHouseAuctionsList
? file.killHouseAuctionsList[0]
: { fee: "پیشنهادی وجود ندارد" };
const totalBids = file.killHouseAuctionsList?.length;
const auctionFinishDate = moment(new Date(date));
const currentDate = moment();
const diff = auctionFinishDate.diff(currentDate);
let auctionRemainedSeconds = moment.duration(diff).asSeconds();
return (
<>
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color="secondary" />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
در حال مزایده
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Typography variant="body2">
درخواست درحال مزایده می باشد.
</Typography>
</TimelineContent>
</Grid>
</Grid>
<Grid>
<SimpleTable
columns={[
"اولویت مرغدار",
"کف قیمت",
"سقف قیمت",
"قیمت درخواستی مرغدار",
"مدت زمان باقی مانده",
"قیمت بالاترین پیشنهاد",
"تعداد کل پیشنهادات",
// "فروشنده",
]}
data={[
[
`اولویت ${index} از ${totalIndex}`,
`${floorPrice}`,
`${ceilingPrice}`,
`${fee}`,
<Timer
key={"FileAuctionStatus"}
seconds={auctionRemainedSeconds}
/>,
highestBid === "پیشنهادی وجود ندارد"
? highestBid
: `${highestBid}`,
totalBids ? totalBids : "پیشنهادی وجود ندارد",
// file.provinceRequestAuctionList ? "استان" : "مرغدار",
],
]}
/>
</Grid>
</Grid>
</TimelineItem>
</>
);
};
FileAuctionStatus.propTypes = {
file: PropTypes.object,
};
export default FileAuctionStatus;

View File

@@ -0,0 +1,60 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Typography } from "@mui/material";
import React from "react";
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
export const FileAuctionWinner = ({ file }) => {
const { killHouseWinner } = file;
return (
<>
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent variant="body1" fontWeight="bold">
اطلاعات مزایده
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Typography variant="body2">
در این قسمت اطلاعات برنده خرید در مزایده را مشاهده می کنید.
</Typography>
</TimelineContent>
</Grid>
</Grid>
<Grid>
<SimpleTable
columns={["نام خریدار", "تلفن خریدار", "استان/شهر", "قیمت خرید"]}
data={[
[
`${killHouseWinner.killHouseName} (${killHouseWinner.killHouseUserName})`,
killHouseWinner.killHouseUserMobile,
`${killHouseWinner.killHouseProvince}/${killHouseWinner.killHouseCity}`,
killHouseWinner.fee + " ﷼",
],
]}
/>
</Grid>
</Grid>
</TimelineItem>
</>
);
};
FileAuctionWinner.propTypes = {
file: PropTypes.object,
};

View File

@@ -0,0 +1,106 @@
import { Typography } from "@mui/material";
import React from "react";
import { Grid } from "../../../../components/grid/Grid";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { formatJustDate } from "../../../../utils/formatTime";
import { PropTypes } from "prop-types";
import { SPACING } from "../../../../data/spacing";
import { TimelineOppositeContent } from "@mui/lab";
import { format } from "date-fns-jalali";
export const FileComplaint = ({ item }) => {
return (
<>
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
بررسی شکایت
</TimelineOppositeContent>
</Grid>
</Grid>
<Grid container>
<SimpleTable
name={`تلفات برای این بار در تاریخ ${formatJustDate(
item.complaint?.createDate
)} ثبت شده.`}
columns={[
"عنوان",
"توضیحات",
"تاریخ ثبت",
"وضعیت",
"درصد تلفات",
"تلفات عرف",
"وزن واقعی",
"وزن با احتساب تلفات",
"پیوست تصویر",
]}
data={[
[
item.complaint?.title,
item.complaint?.description
? item.complaint?.description
: "بدون توضیحات",
format(new Date(item.complaint?.createDate), "yyyy/MM/dd"),
item.complaint?.state === "pending"
? "در حال بررسی"
: item.complaint?.state === "accepted"
? "تایید شده"
: "رد شده",
item.complaint?.percent,
item.complaint?.percentageLosses,
item.complaint?.realWeight,
item.complaint?.lossesWeight !== 0
? item.complaint?.lossesWeight
: "تلفات بررسی نشده است",
item.complaint?.image?.length
? item.complaint?.image?.map((item, i) => {
return [
<Grid
display="inline-flex"
key={`SlaughterPaymentFactorImage${i}`}
>
<a href={item} alt="دانلود">
<img
src={item}
width="80"
height="80"
alt="دانلود"
style={{
marginRight: "10px",
borderRadius: "5px",
}}
/>
</a>
</Grid>,
];
})
: "بدون پیوست",
],
]}
/>
{item?.complaint?.reviewer && (
<Typography
mt={SPACING.TINY}
variant="body2"
color={(prop) => prop.palette.grey["A700"]}
>
{`تلفات در تاریخ ${formatJustDate(
item?.complaint?.reviewer?.createDate
)} توسط ${item?.complaint?.reviewer?.operatorname} `}
{item?.complaint?.reviewer?.state === "accepted" ? "تایید " : "رد "}
شده است.
</Typography>
)}
</Grid>
</>
);
};
FileComplaint.propTypes = {
item: PropTypes.object,
};

View File

@@ -0,0 +1,57 @@
import * as React from "react";
import { PropTypes } from "prop-types";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { format } from "date-fns-jalali";
export const FileInformation = ({ file }) => {
const requestedSellTypeCash = file.poultry?.sellType?.cash ? "نقدی" : null;
const requestedSellTypeCredit = file.poultry?.sellType?.credit
? "زمان دار"
: null;
const requestedSellType = [requestedSellTypeCash, requestedSellTypeCredit]
.filter((item) => item)
.join(" یا ");
return (
<SimpleTable
columns={[
"کدسفارش",
"نام مرغدار",
"تلفن",
"تاریخ درخواست کشتار",
"استان",
"شهرستان",
"تاریخ جوجه ریزی",
"تعداد",
"جمع تلفات",
"وزن تقریبی هر مرغ",
"سن مرغ",
"نژاد",
"نحوه فروش",
// "فروشنده",
]}
data={[
[
file.poultry.poultryOrderCode,
file.poultry.poultryName,
file.poultry.poultryMobile,
format(new Date(file.poultry.poultrySendDate), "yyyy/MM/dd"),
file.poultry.poultryProvince,
file.poultry.poultryCity,
format(new Date(file.poultryHatching.date), "yyyy/MM/dd"),
file.poultry.poultryQuantity,
file.poultryHatching.losses,
file.poultry.poultryIndexWeight,
file.poultry.age,
file.poultry.poultryChickenBreed,
requestedSellType,
// file.provinceRequestAuctionList ? "استان" : "مرغدار",
],
]}
/>
);
};
FileInformation.propTypes = {
file: PropTypes.any,
};

View File

@@ -0,0 +1,199 @@
import { Button, TextField } from "@mui/material";
import React, { useContext, useEffect, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { PropTypes } from "prop-types";
import { Yup } from "../../../../lib/yup/yup";
import { useFormik } from "formik";
import { SPACING } from "../../../../data/spacing";
import { useDispatch } from "react-redux";
import useUserProfile from "../../../authentication/hooks/useUserProfile";
import { useParams } from "react-router-dom";
import { AppContext } from "../../../../contexts/AppContext";
import { AnimatePresence, motion } from "framer-motion";
import {
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { getFileFromApi } from "../../hooks/useRequestFile";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { provinceCheckComplaint } from "../../services/province-check-complaint";
export const FileOperatorCheckComplaint = ({ item }) => {
const [isDenyedComplaint, setisDenyedComplaint] = useState(false);
const [roles] = useUserProfile();
const { id } = useParams();
const [openNotif] = useContext(AppContext);
const dispatch = useDispatch();
const formik = useFormik({
initialValues: {
rejectText: "",
},
validationSchema: Yup.object({
rejectText: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا دلیل خود را بیان کنید."),
}),
});
useEffect(() => {
formik.validateForm();
}, []);
return (
<>
<Grid container>
<Grid xs={12}>
<Grid xs={12}>
{item.complaint.state === "pending" && (
<Grid container gap={SPACING.SMALL} padding={SPACING.SMALL}>
<AnimatePresence>
{isDenyedComplaint ? (
<motion.div
animate={{ x: -10, opacity: 1 }}
transition={{ duration: 0.3 }}
initial={{ opacity: 0 }}
exit={{ opacity: 0 }}
>
<Grid
flexDirection={"column"}
container
gap={SPACING.SMALL}
>
<Grid>
<TextField
multiline
rows={4}
fullWidth
id="rejectText"
label="پیام خود را وارد کنید"
variant="outlined"
value={formik.values.rejectText}
error={
formik.touched.rejectText
? Boolean(formik.errors.rejectText)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.rejectText &&
Boolean(formik.errors.rejectText)
? formik.errors.rejectText
: null
}
/>
</Grid>
<Grid container gap={SPACING.SMALL}>
<Grid>
<Button
variant="outlined"
color="secondary"
onClick={() => {
setisDenyedComplaint(false);
}}
>
لغو
</Button>
</Grid>
<Grid>
<Button
disabled={!formik.isValid}
variant="outlined"
onClick={() => {
dispatch(LOADING_START());
dispatch(
provinceCheckComplaint({
key: item.complaint.complaintKey,
state: "rejected",
role: getRoleFromUrl(),
message: formik.values.rejectText,
})
).then((r) => {
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
getFileFromApi(roles, id, dispatch);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
dispatch(LOADING_END());
});
}}
>
رد شکایت
</Button>
</Grid>
</Grid>
</Grid>
</motion.div>
) : (
<Grid container gap={SPACING.SMALL}>
<Button
variant="outlined"
color="secondary"
onClick={() => {
setisDenyedComplaint(true);
}}
>
رد شکایت
</Button>
<Button
variant="outlined"
onClick={() => {
dispatch(LOADING_START());
dispatch(
provinceCheckComplaint({
key: item.complaint.complaintKey,
state: "accepted",
role: getRoleFromUrl(),
})
).then((r) => {
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
getFileFromApi(roles, id, dispatch);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
dispatch(LOADING_END());
});
}}
>
تایید شکایت
</Button>
</Grid>
)}
</AnimatePresence>
</Grid>
)}
</Grid>
</Grid>
</Grid>
</>
);
};
FileOperatorCheckComplaint.propTypes = {
item: PropTypes.object,
};

View File

@@ -0,0 +1,24 @@
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import TimelineOppositeContent from "@mui/lab/TimelineOppositeContent";
import { Typography } from "@mui/material";
export const FinalFactorTitle = ({ file }) => {
return (
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
فاکتور نهایی
</Typography>
</TimelineOppositeContent>
</Grid>
</Grid>
</Grid>
);
};
FinalFactorTitle.propTypes = {
file: PropTypes.any,
};

View File

@@ -0,0 +1,400 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Typography } from "@mui/material";
import React, { useEffect } from "react";
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { SPACING } from "../../../../data/spacing";
import { formatTime } from "../../../../utils/formatTime";
import moment from "moment";
import { Timer } from "../../../../components/timer/Timer";
import { useDispatch, useSelector } from "react-redux";
import { avicultureGetChickenPrice } from "../../../aviculture/services/aviculture-get-chicken-price";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
// import { useSelector } from "react-redux";
const FinancialCheckRequestInformation = ({ data, auction }) => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(avicultureGetChickenPrice());
}, []);
// let columns = [];
// let item = [];
const { avicultureChickenPrice } = useSelector(
(state) => state.avicultureSlice
);
const liveChickenPrice = avicultureChickenPrice?.liveChickenPrice;
let barInfoColumns,
barInfoData,
financialColumns,
financialColumnsCash,
financialData,
financialDataCash;
const paymentDate = moment(new Date(data.paymentDeadLine));
const currentDate = moment();
const diff = paymentDate.diff(currentDate);
let paymentRemainedSeconds = moment.duration(diff).asSeconds();
if (auction) {
// columns = [
// "کشتارگاه",
// "تعداد",
// "نام راننده",
// "ماشین",
// "وزن بار",
// "سند خودرو بدون بار",
// "سند خودرو با بار",
// "وضعیت",
// ];
// item = [
// [
// data.quantity + " قطعه",
// data.cars.driverName + ` (${data.cars.driverMobile})`,
// `${data.cars.typeCar} با پلاک ${data.cars.pelak}`,
// data.barInfo.killHouseNetWeight + " کیلوگرم",
// data.barInfo.killHouseNetWeight + " کیلوگرم",
// <a
// href={data.barInfo.killHouseImageWithoutLoad}
// alt="دانلود سند خودرو بدون بار"
// key="provinceKillRequests"
// >
// <img
// src={data.barInfo.killHouseImageWithoutLoad}
// width="50"
// height="50"
// alt="بدون بار"
// className="images-file"
// />
// </a>,
// <a
// href={data.barInfo.killHouseImageWithLoad}
// alt="دانلود سند خودرو با بار"
// key="provinceKillRequests"
// >
// <img
// src={data.barInfo.killHouseImageWithLoad}
// width="50"
// height="50"
// alt="بدون بار"
// className="images-file"
// key="provinceKillRequests"
// />
// </a>,
// !data.killHouseFactorToProvince && data.provinceFactorToKillHouse
// ? "در انتظار پرداخت کشتارگاه"
// : "پرداخت شده توسط کشتارگاه",
// ],
// ];
} else {
let state;
state =
!data.killHouseFactorToProvince && !data.provinceFactorToKillHouse
? "در انتظار تایید مالی"
: state;
state =
!data.killHouseFactorToProvince && data.provinceFactorToKillHouse
? "در انتظار پرداخت کشتارگاه"
: state;
state =
data.killHouseFactorToProvince && data.provinceFactorToKillHouse
? "پرداخت شده توسط کشتارگاه"
: state;
let timerState;
const isFactorPayed =
data.killHouseFactorToProvince?.factorState === "accepted" ||
data.killHouseFactorToPoultry?.factorState === "accepted";
const timer = data && (
<Timer
key="finincalTimer"
isFilePaymentTime={true}
seconds={paymentRemainedSeconds}
/>
);
const isPaymentFactorPending =
!data.killHouseFactorToProvince &&
!data.provinceFactorToKillHouseForPoultry;
const isPaymentPendingAndTimerEnabled = Boolean(data.paymentDeadLine);
// if (
// !data.provinceFactorToKillHouse ||
// !data.provinceFactorToKillHouseForPoultry
// ) {
// timerState = "در انتظار تایید مالی";
// } else if (isFactorPayed) {
// timerState = "پرداخت شده ✔";
// } else if (isPaymentPendingAndTimerEnabled) {
// timerState = timer;
// } else if (isPaymentPending) {
// timerState = "در انتظار صدور تمامی فاکتورها";
// }
if (isPaymentPendingAndTimerEnabled) {
timerState = timer;
} else if (isPaymentFactorPending) {
timerState = "در انتظار تایید مالی";
} else {
timerState = "در انتظار صدور تمامی فاکتورها";
}
if (isFactorPayed) {
timerState = "پرداخت شده ✔";
}
barInfoColumns = [
"کشتارگاه",
"نام راننده",
"ماشین",
// "کد قرنطینه",
// "کد حمل و نقل",
"نوع خرید",
"سند خودرو بدون بار",
"سند خودرو با بار",
"تعداد درخواست",
"تعداد واقعی بارگیری",
"وزن بار",
"میانگین وزن",
];
barInfoData = [
[
`${data.killHouseName} (${data.killHouseUserProvince}/${data.killHouseUserCity})`,
data.cars?.driverName + ` (${data.cars?.driverMobile})`,
`${data.cars?.typeCar} با پلاک ${data.cars?.pelak}`,
`${data.paymentType === "credit" ? "زمان دار" : "نقدی"}`,
<a
style={{ textDecoration: "none", color: "black" }}
href={data.barInfo.killHouseImageWithoutLoad}
alt="دانلود سند خودرو بدون بار"
key="provinceKillRequests"
>
<img
src={data.barInfo.killHouseImageWithoutLoad}
width="50"
height="50"
alt="بدون بار"
className="images-file"
/>
<p>{data.barInfo.killHouseWeightWithoutLoad} کیلوگرم</p>
</a>,
<a
style={{ textDecoration: "none", color: "black" }}
href={data.barInfo.killHouseImageWithLoad}
alt="دانلود سند خودرو با بار"
key="provinceKillRequests"
>
<img
src={data.barInfo.killHouseImageWithLoad}
width="50"
height="50"
alt="بدون بار"
className="images-file"
key="provinceKillRequests"
/>
<p>{data.barInfo.killHouseWeightWithLoad} کیلوگرم</p>
</a>,
data.quantity + " قطعه",
data.barInfo.realQuantity + " قطعه",
data.barInfo.killHouseNetWeight + " کیلوگرم",
(data.barInfo.killHouseNetWeight / data.barInfo.realQuantity).toFixed(
2
) + " کیلوگرم",
],
];
financialColumns = [
"قیمت روز",
"قیمت هرکیلو",
"سهم مرغدار",
"سهم اتحادیه",
"مانده تا سررسید 30 روزه",
"سهم مرغدار با ضریب سود",
"سهم اتحادیه با ضریب سود",
"جمع مبلغ قابل پرداخت",
"وضعیت",
];
let poultryShareWithProfit;
if (data.provinceFactorToKillHouse?.poultryShareWithProfit) {
poultryShareWithProfit =
data.provinceFactorToKillHouse?.poultryShareWithProfit;
} else if (
data.provinceFactorToKillHouseForPoultry?.poultryShareWithProfit
) {
poultryShareWithProfit =
data.provinceFactorToKillHouseForPoultry?.poultryShareWithProfit;
}
financialData = [
[
liveChickenPrice + " ﷼",
data.provinceFactorToKillHouse
? data.provinceFactorToKillHouse.provinceFactorFee + " ریال"
: "نامشخص",
data.provinceFactorToKillHouse
? data.provinceFactorToKillHouse.provinceFactorFee *
data.barInfo.killHouseNetWeight +
" ریال"
: "نامشخص",
data.provinceFactorToKillHouse?.totalShareAllocation
? data.provinceFactorToKillHouse?.totalShareAllocation + " ریال"
: "نامشخص",
timerState,
poultryShareWithProfit ? `${poultryShareWithProfit} ریال` : "نامشخص",
data.provinceFactorToKillHouse?.unionShareWithProfit
? `${data.provinceFactorToKillHouse?.unionShareWithProfit} ریال`
: "نامشخص",
data.provinceFactorToKillHouse?.cost
? `${
data.provinceFactorToKillHouse?.cost +
data.provinceFactorToKillHouse?.poultryShareWithProfit
} ریال`
: "نامشخص",
state,
],
];
financialColumnsCash = [
"قیمت روز",
"قیمت هرکیلو",
"سهم مرغدار",
"سهم اتحادیه",
"مبلغ قابل پرداخت",
"وضعیت",
];
let pricePayment;
if (data.provinceFactorToKillHouse?.cost) {
pricePayment = `${data.provinceFactorToKillHouse?.cost} ریال`;
} else if (data.provinceFactorToKillHouseForPoultry?.cost) {
pricePayment = `${data.provinceFactorToKillHouseForPoultry?.cost} ریال`;
} else {
pricePayment = "نامشخص";
}
financialDataCash = [
[
liveChickenPrice + " ﷼",
data.provinceFactorToKillHouse
? data.provinceFactorToKillHouse.provinceFactorFee + " ریال"
: "ندارد",
// data.provinceFactorToKillHouse
// ? data.provinceFactorToKillHouse.provinceFactorFee *
// data.barInfo.killHouseNetWeight +
// " ریال"
// : "ندارد",
poultryShareWithProfit ? `${poultryShareWithProfit} ریال` : "نامشخص",
data.provinceFactorToKillHouse?.totalShareAllocation
? data.provinceFactorToKillHouse?.totalShareAllocation + " ریال"
: "نامشخص",
pricePayment,
state,
],
];
// remove payment fields for aviculture
const urlRole = getRoleFromUrl();
if (urlRole === "Poultry") {
financialColumnsCash.splice(5, 3);
financialDataCash[0]?.splice(5, 3);
financialColumns.splice(5, 4);
financialData[0]?.splice(5, 4);
}
}
return (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
مرحله مالی
</Typography>
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Grid container gap={SPACING.SMALL}>
{data.barInfo.killHouseAssignmentState === "pending" ? (
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
درخواست در انتظار تایید اپراتور مالی است.
</Typography>
) : (
<>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
درخواست در تاریخ
</Typography>
<Typography variant="body2" fontWeight="bold">
{formatTime(new Date(data.barInfo.acceptRejectDate))}
</Typography>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
{data.barInfo.killHouseAssignmentState === "accepted"
? "تایید شده است."
: data.barInfo.killHouseAssignmentState === "pending"
? "در انتظار تایید"
: "رد شده است."}
</Typography>
</>
)}
</Grid>
</TimelineContent>
</Grid>
</Grid>
<Grid container>
<Grid xs={12}>
<SimpleTable
name={`اطلاعات بار ${data.barcod} - کد قرنطینه ${data.clearanceCode} - کد حمل و نقل ${data.trafficCode}`}
columns={barInfoColumns}
data={barInfoData}
/>
{data.paymentType === "cash" ? (
<SimpleTable
name="اطلاعات مالی"
columns={financialColumnsCash}
data={financialDataCash}
/>
) : (
<SimpleTable
name="اطلاعات مالی"
columns={financialColumns}
data={financialData}
/>
)}
</Grid>
</Grid>
</Grid>
</TimelineItem>
);
};
FinancialCheckRequestInformation.propTypes = {
item: PropTypes.array,
data: PropTypes.any,
auction: PropTypes.bool,
};
export default FinancialCheckRequestInformation;

View File

@@ -0,0 +1,322 @@
import React, { useEffect } from "react";
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import moment from "moment";
import { Timer } from "../../../../components/timer/Timer";
import { useDispatch, useSelector } from "react-redux";
import { avicultureGetChickenPrice } from "../../../aviculture/services/aviculture-get-chicken-price";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
// import { useSelector } from "react-redux";
const FinancialCheckRequestInformationContent = ({ data, auction }) => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(avicultureGetChickenPrice());
}, []);
const { avicultureChickenPrice } = useSelector(
(state) => state.avicultureSlice
);
const liveChickenPrice = avicultureChickenPrice?.liveChickenPrice;
let barInfoColumns,
barInfoData,
financialColumns,
financialColumnsCash,
financialData,
financialDataCash;
const paymentDate = moment(new Date(data.paymentDeadLine));
const currentDate = moment();
const diff = paymentDate.diff(currentDate);
const paymentRemainedSeconds = moment.duration(diff).asSeconds();
if (auction) {
// columns = [
// "کشتارگاه",
// "تعداد",
// "نام راننده",
// "ماشین",
// "وزن بار",
// "سند خودرو بدون بار",
// "سند خودرو با بار",
// "وضعیت",
// ];
// item = [
// [
// data.quantity + " قطعه",
// data.cars.driverName + ` (${data.cars.driverMobile})`,
// `${data.cars.typeCar} با پلاک ${data.cars.pelak}`,
// data.barInfo.killHouseNetWeight + " کیلوگرم",
// data.barInfo.killHouseNetWeight + " کیلوگرم",
// <a
// href={data.barInfo.killHouseImageWithoutLoad}
// alt="دانلود سند خودرو بدون بار"
// key="provinceKillRequests"
// >
// <img
// src={data.barInfo.killHouseImageWithoutLoad}
// width="50"
// height="50"
// alt="بدون بار"
// className="images-file"
// />
// </a>,
// <a
// href={data.barInfo.killHouseImageWithLoad}
// alt="دانلود سند خودرو با بار"
// key="provinceKillRequests"
// >
// <img
// src={data.barInfo.killHouseImageWithLoad}
// width="50"
// height="50"
// alt="بدون بار"
// className="images-file"
// key="provinceKillRequests"
// />
// </a>,
// !data.killHouseFactorToProvince && data.provinceFactorToKillHouse
// ? "در انتظار پرداخت کشتارگاه"
// : "پرداخت شده توسط کشتارگاه",
// ],
// ];
} else {
let state;
state =
!data.killHouseFactorToProvince && !data.provinceFactorToKillHouse
? "در انتظار تایید مالی"
: state;
state =
!data.killHouseFactorToProvince && data.provinceFactorToKillHouse
? "در انتظار پرداخت کشتارگاه"
: state;
state =
data.killHouseFactorToProvince && data.provinceFactorToKillHouse
? "پرداخت شده توسط کشتارگاه"
: state;
let timerState;
const isFactorPayed =
data.killHouseFactorToProvince?.factorState === "accepted" ||
data.killHouseFactorToPoultry?.factorState === "accepted";
const timer = data && (
<Timer
key="finincalTimer"
isFilePaymentTime={true}
seconds={paymentRemainedSeconds}
/>
);
const isPaymentFactorPending =
!data.killHouseFactorToProvince &&
!data.provinceFactorToKillHouseForPoultry;
const isPaymentPendingAndTimerEnabled = Boolean(data.paymentDeadLine);
// if (
// !data.provinceFactorToKillHouse ||
// !data.provinceFactorToKillHouseForPoultry
// ) {
// timerState = "در انتظار تایید مالی";
// } else if (isFactorPayed) {
// timerState = "پرداخت شده ✔";
// } else if (isPaymentPendingAndTimerEnabled) {
// timerState = timer;
// } else if (isPaymentPending) {
// timerState = "در انتظار صدور تمامی فاکتورها";
// }
if (isPaymentPendingAndTimerEnabled) {
timerState = timer;
} else if (isPaymentFactorPending) {
timerState = "در انتظار تایید مالی";
} else {
timerState = "در انتظار صدور تمامی فاکتورها";
}
if (isFactorPayed) {
timerState = "پرداخت شده ✔";
}
barInfoColumns = [
"کشتارگاه",
"نام راننده",
"ماشین",
"نوع خرید",
"سند خودرو بدون بار",
"سند خودرو با بار",
"تعداد درخواست",
"تعداد واقعی بارگیری",
"وزن بار",
"میانگین وزن",
];
barInfoData = [
[
`${data.killHouseName} (${data.killHouseUserProvince}/${data.killHouseUserCity})`,
data.cars?.driverName + ` (${data.cars?.driverMobile})`,
`${data.cars?.typeCar} با پلاک ${data.cars?.pelak}`,
`${data.paymentType === "credit" ? "زمان دار" : "نقدی"}`,
<a
style={{ textDecoration: "none", color: "black" }}
href={data.barInfo.killHouseImageWithoutLoad}
alt="دانلود سند خودرو بدون بار"
key="provinceKillRequests"
>
<img
src={data.barInfo.killHouseImageWithoutLoad}
width="50"
height="50"
alt="بدون بار"
className="images-file"
/>
<p>{data.barInfo.killHouseWeightWithoutLoad} کیلوگرم</p>
</a>,
<a
style={{ textDecoration: "none", color: "black" }}
href={data.barInfo.killHouseImageWithLoad}
alt="دانلود سند خودرو با بار"
key="provinceKillRequests"
>
<img
src={data.barInfo.killHouseImageWithLoad}
width="50"
height="50"
alt="بدون بار"
className="images-file"
key="provinceKillRequests"
/>
<p>{data.barInfo.killHouseWeightWithLoad} کیلوگرم</p>
</a>,
data.quantity + " قطعه",
data.barInfo.realQuantity + " قطعه",
data.barInfo.killHouseNetWeight + " کیلوگرم",
(data.barInfo.killHouseNetWeight / data.barInfo.realQuantity).toFixed(
2
) + " کیلوگرم",
],
];
financialColumns = [
"قیمت روز",
"قیمت هرکیلو",
"سهم مرغدار",
"سهم اتحادیه",
"مانده تا سررسید 30 روزه",
"سهم مرغدار با ضریب سود",
"سهم اتحادیه با ضریب سود",
"جمع مبلغ قابل پرداخت",
"وضعیت",
];
let poultryShareWithProfit;
if (data.provinceFactorToKillHouse?.poultryShareWithProfit) {
poultryShareWithProfit =
data.provinceFactorToKillHouse?.poultryShareWithProfit;
} else if (
data.provinceFactorToKillHouseForPoultry?.poultryShareWithProfit
) {
poultryShareWithProfit =
data.provinceFactorToKillHouseForPoultry?.poultryShareWithProfit;
}
financialData = [
[
liveChickenPrice + " ﷼",
data.provinceFactorToKillHouse
? data.provinceFactorToKillHouse.provinceFactorFee + " ریال"
: "نامشخص",
data.provinceFactorToKillHouse
? data.provinceFactorToKillHouse.provinceFactorFee *
data.barInfo.killHouseNetWeight +
" ریال"
: "نامشخص",
data.provinceFactorToKillHouse?.totalShareAllocation
? data.provinceFactorToKillHouse?.totalShareAllocation + " ریال"
: "نامشخص",
timerState,
poultryShareWithProfit ? `${poultryShareWithProfit} ریال` : "نامشخص",
data.provinceFactorToKillHouse?.unionShareWithProfit
? `${data.provinceFactorToKillHouse?.unionShareWithProfit} ریال`
: "نامشخص",
data.provinceFactorToKillHouse?.cost
? `${
data.provinceFactorToKillHouse?.cost +
data.provinceFactorToKillHouse?.poultryShareWithProfit
} ریال`
: "نامشخص",
state,
],
];
financialColumnsCash = [
"قیمت روز",
"قیمت هرکیلو",
"سهم مرغدار",
"سهم اتحادیه",
"مبلغ قابل پرداخت",
"وضعیت",
];
financialDataCash = [
[
liveChickenPrice + " ﷼",
data.provinceFactorToKillHouse
? data.provinceFactorToKillHouse.provinceFactorFee + " ریال"
: "ندارد",
data.provinceFactorToKillHouse
? data.provinceFactorToKillHouse.provinceFactorFee *
data.barInfo.killHouseNetWeight +
" ریال"
: "ندارد",
data.provinceFactorToKillHouse?.totalShareAllocation
? data.provinceFactorToKillHouse?.totalShareAllocation + " ریال"
: "نامشخص",
data.provinceFactorToKillHouse?.cost
? `${data.provinceFactorToKillHouse?.cost} ریال`
: "ندارد",
state,
],
];
// remove payment fields for aviculture
const urlRole = getRoleFromUrl();
if (urlRole === "Poultry") {
financialColumnsCash.splice(5, 3);
financialDataCash[0]?.splice(5, 3);
financialColumns.splice(5, 4);
financialData[0]?.splice(5, 4);
}
}
return (
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid xs={12}>
<SimpleTable
name={`اطلاعات بار ${data.barcod}`}
columns={barInfoColumns}
data={barInfoData}
/>
{data.paymentType === "cash" ? (
<SimpleTable
name="اطلاعات مالی"
columns={financialColumnsCash}
data={financialDataCash}
/>
) : (
<SimpleTable
name="اطلاعات مالی"
columns={financialColumns}
data={financialData}
/>
)}
</Grid>
</Grid>
</Grid>
);
};
FinancialCheckRequestInformationContent.propTypes = {
item: PropTypes.array,
data: PropTypes.any,
auction: PropTypes.bool,
};
export default FinancialCheckRequestInformationContent;

View File

@@ -0,0 +1,751 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import {
Button,
ButtonGroup,
TextField,
ToggleButton,
ToggleButtonGroup,
Typography,
} from "@mui/material";
import React, { useEffect, useState } from "react";
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { AnimatePresence, motion } from "framer-motion";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import { useDispatch, useSelector } from "react-redux";
import { financialCheckRequest } from "../../services/financial-check-request";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { avicultureGetChickenPrice } from "../../../aviculture/services/aviculture-get-chicken-price";
import { provinceFinancialGetPendingRequestsService } from "../../../province-finacial/services/province-financial-get-pending-requests";
import { NumberInput } from "../../../../components/number-format-custom/NumberFormatCustom";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { formatJustDate } from "../../../../utils/formatTime";
export const FinancialCheckRequestOperation = ({ item }) => {
const [openNotif, , selectedDate1, , selectedDate2] = useContext(AppContext);
const dispatch = useDispatch();
useEffect(() => {
dispatch(avicultureGetChickenPrice());
formik.validateForm();
formik2.validateForm();
}, []);
const { avicultureChickenPrice } = useSelector(
(state) => state.avicultureSlice
);
const liveChickenPrice = avicultureChickenPrice?.liveChickenPrice;
// calc suggest price
// const chickenWeight = parseFloat(
// file.poultry.poultryIndexWeight.split(" ")[0]
// );
const chickenWeight = parseFloat(
(item.barInfo.killHouseNetWeight / item.barInfo.realQuantity).toFixed(2)
);
// let suggestPrice = liveChickenPrice;
//buildchange
// hamedan & arak & bushehr
const standardChicken = 2.5;
// kermanshah
// const standardChicken = 2.7;
// const checkStep = 0.05;
// const costPerStep = 500;
if (chickenWeight < standardChicken) {
// const howMuchToReduce =
// ((standardChicken - chickenWeight).toFixed(2) / checkStep) * costPerStep;
// suggestPrice = liveChickenPrice - howMuchToReduce;
}
const formik = useFormik({
initialValues: {
rejectText: "",
// wage: "1000",
},
validationSchema: Yup.object({
rejectText: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا دلیل خود را بیان کنید."),
}),
});
const [activeButtonIndex, setActiveButtonIndex] = useState(false);
const handleButtonClick = (index) => {
setActiveButtonIndex(index);
if (!activeButtonIndex) {
formik2.setFieldValue("reason", "");
formik2.setFieldValue("amount", "");
}
};
const formik2 = useFormik({
initialValues: {
fee: "",
paymentType: "together",
wage: 0,
amount: "",
reason: "",
},
validationSchema: Yup.object({
fee: Yup.number().required("این فیلد اجباری است!"),
amount: Yup.number(),
paymentType: Yup.string().required("این فیلد اجباری است!"),
reason: activeButtonIndex
? Yup.string().required("این فیلد اجباری است!")
: Yup.string(),
wage: Yup.number().required("این فیلد اجباری است!"),
}),
});
let totalFactorPrice =
(formik2.values.fee + formik2.values.wage) * item.killHouseNetWeight;
if (activeButtonIndex === "plus") {
totalFactorPrice += Number(formik2.values.amount);
} else if (activeButtonIndex === "decrease") {
totalFactorPrice -= Number(formik2.values.amount);
}
let finalTotalFactorPrice =
totalFactorPrice - item.killRequestPaymentRemainAmount;
if (item.smsPayment) {
finalTotalFactorPrice += 50000;
}
const [isDenyed, setisDenyed] = useState(false);
const btnValidation = !formik2.isValid;
const [paymentType, setPaymentType] = React.useState("union");
const handleChange = (event, newAlignment) => {
if (newAlignment) {
setPaymentType(newAlignment);
}
};
return (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color="secondary" />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<>
<Grid container justifyContent="space-between">
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
انجام عملیات
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Typography variant="body2">
درخواست را بررسی و سپس تایید یا رد کنید.
</Typography>
</TimelineContent>
</Grid>
</Grid>
<Grid
container
gap={SPACING.SMALL}
mb={SPACING.TINY}
justifyContent="space-between"
>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
موجودی کیف پول کشتارگاه:
</Typography>
<Typography variant={"button"} color="primary">
{`${item.killHouseWalletAmount?.toLocaleString()}`}
</Typography>
</Grid>
</Grid>
</Grid>
<Grid container width="100%">
<Grid
container
alignItems="start"
direction="row-reverse"
justifyContent="start"
>
<Grid
container
gap={SPACING.TINY}
mt={SPACING.TINY}
alignItems="center"
ml={SPACING.LARGE}
>
<Typography variant={"caption"} color="error">
صدور فاکتور بنام:
</Typography>
<ToggleButtonGroup
color="primary"
value={paymentType}
orientation="vertical"
exclusive
onChange={handleChange}
aria-label="Platform"
>
<ToggleButton value="union">اتحادیه</ToggleButton>
<ToggleButton value="poultry">مرغدار</ToggleButton>
</ToggleButtonGroup>
<Grid ml={SPACING.MEDIUM}>
{paymentType === "union" && (
<Grid container alignItems="center" gap={SPACING.SMALL}>
<Grid>
<Typography>اطلاعات حساب اتحادیه</Typography>
</Grid>
<Grid
style={{
border: "1px solid #ccc",
padding: "10px",
borderRadius: "4px",
}}
>
<Typography>
شماره کارت: {item?.provinceBank?.card}
</Typography>
<Typography>
شماره شبا: {item?.provinceBank?.shaba}
</Typography>
<Typography>
شماره حساب: {item?.provinceBank?.account}
</Typography>
<Typography>
بانک {item?.provinceBank?.bankName} - بنام{" "}
{item.provinceBank?.nameOfBankUser}
</Typography>
</Grid>
</Grid>
)}
{paymentType === "poultry" && (
<Grid container alignItems="center" gap={SPACING.SMALL}>
<Grid>
<Typography>اطلاعات حساب مرغدار</Typography>
</Grid>
<Grid
style={{
border: "1px solid #ccc",
padding: "10px",
borderRadius: "4px",
}}
>
<Typography>
شماره کارت:{" "}
{item?.poultryBank?.card
? item?.poultryBank?.card
: "ندارد"}
</Typography>
<Typography>
شماره شبا:{" "}
{item?.poultryBank?.shaba
? item?.poultryBank?.shaba
: "ندارد"}
</Typography>
<Typography>
شماره حساب:{" "}
{item?.poultryBank?.account
? item?.poultryBank?.account
: "ندارد"}
</Typography>
<Typography>
بانک{" "}
{item?.poultryBank?.bankName
? item?.poultryBank?.bankName
: "نامشخص"}{" "}
- بنام{" "}
{item.poultryBank?.nameOfBankUser
? item.poultryBank?.nameOfBankUser
: "نامشخص"}
</Typography>
</Grid>
</Grid>
)}
</Grid>
</Grid>
<Grid
container
direction="column"
gap={SPACING.SMALL}
mt={SPACING.TINY}
alignItems="start"
>
<Grid container gap={SPACING.SMALL}>
<Grid>
<NumberInput
allowLeadingZeros
thousandSeparator=","
id="fee"
label="قیمت (﷼)"
variant="outlined"
error={
formik2.touched.fee ? Boolean(formik2.errors.fee) : null
}
onChange={formik2.handleChange}
onBlur={formik2.handleBlur}
helperText={
formik2.touched.fee && Boolean(formik2.errors.fee)
? formik2.errors.fee
: null
}
/>
</Grid>
<Grid>
<NumberInput
allowLeadingZeros
thousandSeparator=","
id="wage"
label="تعرفه استان (﷼)"
variant="outlined"
value={formik2.values.wage}
error={
formik2.touched.wage
? Boolean(formik2.errors.wage)
: null
}
onChange={formik2.handleChange}
onBlur={formik2.handleBlur}
helperText={
formik2.touched.wage && Boolean(formik2.errors.wage)
? formik2.errors.wage
: null
}
/>
</Grid>
</Grid>
<Grid>
<Grid container gap={SPACING.SMALL}>
<Grid
container
direction="column"
gap={SPACING.SMALL}
alignItems="start"
>
<Typography>اضافه یا کسر از فاکتور</Typography>
<ButtonGroup
color="primary"
aria-label="outlined primary button group"
>
<Button
onClick={() => handleButtonClick("plus")}
variant={
activeButtonIndex === "plus"
? "contained"
: "outlined"
}
color="primary"
>
+
</Button>
<Button
onClick={() => handleButtonClick("decrease")}
variant={
activeButtonIndex === "decrease"
? "contained"
: "outlined"
}
color="primary"
>
-
</Button>
<Button
onClick={() => handleButtonClick(false)}
color="error"
>
حذف
</Button>
</ButtonGroup>
</Grid>
<Grid>
{!!activeButtonIndex && (
<Grid container gap={SPACING.SMALL}>
<Grid>
<TextField
id="amount"
label="مبلغ اضافه/کسر از فاکتور"
variant="outlined"
error={
formik2.touched.amount
? Boolean(formik2.errors.amount)
: null
}
onChange={formik2.handleChange}
onBlur={formik2.handleBlur}
helperText={
formik2.touched.amount &&
Boolean(formik2.errors.amount)
? formik2.errors.amount
: null
}
/>
</Grid>
<Grid>
<TextField
id="reason"
label="شرح موضوع"
variant="outlined"
error={
formik2.touched.reason
? Boolean(formik2.errors.reason)
: null
}
multiline
rows={2} // Specify the number of rows to display at once
onChange={formik2.handleChange}
onBlur={formik2.handleBlur}
helperText={
formik2.touched.reason &&
Boolean(formik2.errors.reason)
? formik2.errors.reason
: null
}
/>
</Grid>
</Grid>
)}
</Grid>
</Grid>
</Grid>
</Grid>
<Grid width="100%">
<Grid container gap={SPACING.TINY} my={SPACING.TINY}>
<Grid container gap={SPACING.TINY} alignItems="center">
<Typography color="green" variant={"caption"}>
قیمت مرغ:
</Typography>
<Typography variant={"button"}>
{liveChickenPrice?.toLocaleString()}
</Typography>
</Grid>
<Grid container gap={SPACING.TINY} alignItems="center">
<Typography variant={"caption"} color="green">
آخرین تاریخ قیمت گذاری:
</Typography>
<Typography variant={"button"}>
{avicultureChickenPrice?.createDate &&
formatJustDate(avicultureChickenPrice?.createDate)}
</Typography>
</Grid>
{/* <Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
قیمت پیشنهادی:
</Typography>
<Typography variant={"button"}>
{suggestPrice > 0
? `${suggestPrice?.toLocaleString()} ﷼`
: "نامعتبر"}
</Typography>
</Grid> */}
</Grid>
<SimpleTable
columns={[
"قیمت کل",
"هزینه پیامک اطلاع رسانی",
"مبلغ خالص بار",
"مبلغ کل فاکتور",
"سهم مرغدار",
"سهم استان",
"مانده واریزی اولیه",
"مبلغ فاکتور نهایی",
]}
data={[
[
(
formik2.values.fee + formik2.values.wage
)?.toLocaleString() + " ﷼",
item.smsPayment ? "دارد : 50,000 ﷼" : "ندارد",
(
(formik2.values.fee + formik2.values.wage) *
item.killHouseNetWeight
).toLocaleString() + " ﷼",
totalFactorPrice?.toLocaleString() + " ﷼",
(
formik2.values.fee * item.killHouseNetWeight
)?.toLocaleString() + " ﷼",
(
formik2.values.wage * item.killHouseNetWeight
)?.toLocaleString() + " ﷼",
item.killRequestPaymentRemainAmount?.toLocaleString() +
" ﷼",
finalTotalFactorPrice < 0
? 0
: finalTotalFactorPrice?.toLocaleString() + " ﷼",
],
]}
/>
</Grid>
{/* <Grid container mt={SPACING.SMALL} textAlign="start">
<FormControl>
<Typography variant="body1" fontWeight="bold">
نحوه پرداخت
</Typography>
<RadioGroup
aria-labelledby="demo-controlled-radio-buttons-group"
name="controlled-radio-buttons-group"
value={formik2.values.paymentType}
onChange={(e) => {
formik2.setFieldValue("paymentType", e.target.value);
}}
>
<FormControlLabel
value="separate"
control={<Radio />}
label="پرداخت جداگانه به اتحادیه و مرغدار"
/>
<FormControlLabel
value="together"
control={<Radio />}
label="پرداخت یکجا به حساب اتحادیه"
/>
</RadioGroup>
</FormControl>
</Grid> */}
<Grid xs={12}>
<Grid container gap={SPACING.SMALL} padding={SPACING.SMALL}>
<AnimatePresence>
{isDenyed ? (
<motion.div
animate={{ x: -10, opacity: 1 }}
transition={{ duration: 0.3 }}
initial={{ opacity: 0 }}
exit={{ opacity: 0 }}
>
<Grid
flexDirection={"column"}
container
gap={SPACING.SMALL}
>
<Grid>
<TextField
multiline
rows={4}
fullWidth
id="rejectText"
label="پیام خود را وارد کنید"
variant="outlined"
value={formik.values.rejectText}
error={
formik.touched.rejectText
? Boolean(formik.errors.rejectText)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.rejectText &&
Boolean(formik.errors.rejectText)
? formik.errors.rejectText
: null
}
/>
</Grid>
<Grid container gap={SPACING.SMALL}>
<Grid>
<Button
variant="outlined"
color="secondary"
onClick={() => {
setisDenyed(false);
}}
>
لغو
</Button>
</Grid>
<Grid>
<Button
variant="outlined"
onClick={() => {
dispatch(LOADING_START());
dispatch(
financialCheckRequest({
message: formik.values.rejectText,
kill_house_info_key:
item.barInfo.killHouseAssignmentKey,
state: "rejected",
})
).then((r) => {
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
dispatch(
DRAWER({
right: false,
bottom: false,
content: null,
})
);
dispatch(
provinceFinancialGetPendingRequestsService(
{
selectedDate1,
selectedDate2,
}
)
);
// getFileFromApi(roles, id, dispatch);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
dispatch(LOADING_END());
});
}}
>
رد درخواست
</Button>
</Grid>
</Grid>
</Grid>
</motion.div>
) : (
<Grid container gap={SPACING.SMALL}>
<Button
variant="outlined"
color="secondary"
onClick={() => {
setisDenyed(true);
}}
>
رد درخواست
</Button>
<Button
disabled={btnValidation}
variant="outlined"
onClick={() => {
if (totalFactorPrice < 0) {
// openNotif({
// vertical: "top",
// horizontal: "center",
// msg: `آیتم کسر مبلغ ${formik2.values.reason} نمی تواند بیشتر از مبلغ کل فاکتور باشد.`,
// severity: "error",
// });
formik2.setFieldError(
"amount",
"مبلغ کسر نمی تواند بزرگتر از مبلغ کل فاکتور باشد!"
);
return;
}
dispatch(LOADING_START());
dispatch(
financialCheckRequest({
kill_house_info_key:
item.barInfo.killHouseAssignmentKey,
pay: formik2.values.paymentType,
fee: formik2.values.fee,
real_weight:
item.barInfo.killHouseNetWeight /
item.quantity,
province_input_wage: formik2.values.wage,
province_input_amount: formik2.values.amount
? formik2.values.amount
: null,
province_input_amount_state: activeButtonIndex,
state: "accepted",
reason: formik2.values.reason,
bank: paymentType,
})
).then((r) => {
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
dispatch(
provinceFinancialGetPendingRequestsService({
selectedDate1,
selectedDate2,
})
);
dispatch(
DRAWER({
right: false,
bottom: false,
top: false,
content: null,
})
);
// getFileFromApi(roles, id, dispatch);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
dispatch(LOADING_END());
});
}}
>
صدور فاکتور
</Button>
</Grid>
)}
</AnimatePresence>
</Grid>
</Grid>
</Grid>
</Grid>
</>
</Grid>
</TimelineItem>
);
};
FinancialCheckRequestOperation.propTypes = {
item: PropTypes.object,
file: PropTypes.object,
};

View File

@@ -0,0 +1,24 @@
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import TimelineOppositeContent from "@mui/lab/TimelineOppositeContent";
import { Typography } from "@mui/material";
export const FinancialCheckRequestTitle = ({ file }) => {
return (
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
مرحله تایید پرداخت فاکتور
</Typography>
</TimelineOppositeContent>
</Grid>
</Grid>
</Grid>
);
};
FinancialCheckRequestTitle.propTypes = {
file: PropTypes.any,
};

View File

@@ -0,0 +1,24 @@
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import TimelineOppositeContent from "@mui/lab/TimelineOppositeContent";
import { Typography } from "@mui/material";
export const FinancialCreateFactorTitle = ({ file }) => {
return (
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
مرحله صدور و پرداخت فاکتور مالی
</Typography>
</TimelineOppositeContent>
</Grid>
</Grid>
</Grid>
);
};
FinancialCreateFactorTitle.propTypes = {
file: PropTypes.any,
};

View File

@@ -0,0 +1,24 @@
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import TimelineOppositeContent from "@mui/lab/TimelineOppositeContent";
import { Typography } from "@mui/material";
export const InspectorCheckRequestTitle = ({ file }) => {
return (
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
تایید بازرس
</Typography>
</TimelineOppositeContent>
</Grid>
</Grid>
</Grid>
);
};
InspectorCheckRequestTitle.propTypes = {
file: PropTypes.any,
};

View File

@@ -0,0 +1,72 @@
import * as React from "react";
import { PropTypes } from "prop-types";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { Grid } from "../../../../components/grid/Grid";
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Typography } from "@mui/material";
import { SPACING } from "../../../../data/spacing";
export const InspectorInformation = ({ data }) => {
return (
<>
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
اطلاعات تایید نهایی بازرس
</Typography>
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Grid container gap={SPACING.SMALL}>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
وضعیت نهایی پرونده بررسی شده توسط بازرس در این مرحله نمایش
داده شده است.
</Typography>
</Grid>
</TimelineContent>
</Grid>
</Grid>
<Grid container>
<Grid xs={12}>
<SimpleTable
columns={["نام بازرس", "تاریخ ثبت", "پیغام", "وضعیت"]}
data={[
[
data.inspectorName,
new Date(data.acceptRejectDate),
data.message ? data.message : "-",
data.state === "accepted" ? "تایید شده" : "ابراز مشکل",
],
]}
/>
</Grid>
</Grid>
</Grid>
</TimelineItem>
</>
);
};
InspectorInformation.propTypes = {
data: PropTypes.any,
};

View File

@@ -0,0 +1,253 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Button, TextField, Typography } from "@mui/material";
import React, { useEffect, useState } from "react";
import { PropTypes } from "prop-types";
import { AnimatePresence, motion } from "framer-motion";
import { useDispatch } from "react-redux";
import { useFormik } from "formik";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { Yup } from "../../../../lib/yup/yup";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { inspectorCheckRequest } from "../../services/inspector-check-request";
import { getFileFromApi } from "../../hooks/useRequestFile";
import useUserProfile from "../../../authentication/hooks/useUserProfile";
import { useParams } from "react-router-dom";
import { inspectorGetNewRequests } from "../../../inspector/services/inspector-new-requests";
export const InspectorRequestOperations = ({ process }) => {
const [openNotif] = useContext(AppContext);
const [isSubmited, setIsSubmited] = useState(false);
useEffect(() => {
if (process === null) {
setIsSubmited(true);
}
}, []);
const formik = useFormik({
initialValues: {
rejectText: "",
},
validationSchema: Yup.object({
rejectText: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا دلیل خود را بیان کنید."),
}),
});
const [isDenyed, setisDenyed] = useState(false);
const dispatch = useDispatch();
const [roles] = useUserProfile();
const { id } = useParams();
return (
<>
{!isSubmited && (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color="secondary" />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
انجام عملیات بازرسی
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Typography variant="body2">
در این مرحله درخواست را تایید یا رد کنید.
</Typography>
</TimelineContent>
</Grid>
</Grid>
<Grid>
<Grid xs={12}>
<Grid container gap={SPACING.SMALL} padding={SPACING.SMALL}>
<AnimatePresence>
{isDenyed ? (
<motion.div
animate={{ x: -10, opacity: 1 }}
transition={{ duration: 0.3 }}
initial={{ opacity: 0 }}
exit={{ opacity: 0 }}
>
<Grid
flexDirection={"column"}
container
gap={SPACING.SMALL}
>
<Grid>
<TextField
multiline
rows={4}
fullWidth
id="rejectText"
label="پیام خود را وارد کنید"
variant="outlined"
value={formik.values.rejectText}
error={
formik.touched.rejectText
? Boolean(formik.errors.rejectText)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.rejectText &&
Boolean(formik.errors.rejectText)
? formik.errors.rejectText
: null
}
/>
</Grid>
<Grid container gap={SPACING.SMALL}>
<Grid>
<Button
variant="outlined"
color="secondary"
onClick={() => {
setisDenyed(false);
}}
>
لغو
</Button>
</Grid>
<Grid>
<Button
color="secondary"
variant="outlined"
disabled={!formik.isValid}
onClick={() => {
dispatch(LOADING_START());
dispatch(
inspectorCheckRequest({
message: formik.values.rejectText,
key: process?.poultry?.poultryRequestKey,
state: "rejected",
})
).then((r) => {
if (r.error) {
dispatch(LOADING_END());
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
dispatch(
DRAWER({
right: false,
bottom: false,
top: false,
content: null,
})
);
dispatch(inspectorGetNewRequests());
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
dispatch(LOADING_END());
}}
>
رد درخواست
</Button>
</Grid>
</Grid>
</Grid>
</motion.div>
) : (
<Grid container gap={SPACING.SMALL}>
<Button
variant="outlined"
color="secondary"
onClick={() => {
setisDenyed(true);
}}
>
رد اطلاعات و پیام به استان
</Button>
<Button
variant="outlined"
onClick={() => {
dispatch(LOADING_START());
dispatch(
inspectorCheckRequest({
key: process?.poultry?.poultryRequestKey,
state: "accepted",
})
).then((r) => {
if (r.error) {
dispatch(LOADING_END());
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
dispatch(
DRAWER({
right: false,
bottom: false,
top: false,
content: null,
})
);
dispatch(inspectorGetNewRequests());
getFileFromApi(roles, id, dispatch);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
dispatch(LOADING_END());
}}
>
تایید نهایی درخواست
</Button>
</Grid>
)}
</AnimatePresence>
</Grid>
</Grid>
</Grid>
</Grid>
</TimelineItem>
)}
</>
);
};
InspectorRequestOperations.propTypes = {
process: PropTypes.any,
};

View File

@@ -0,0 +1,36 @@
import { format } from "date-fns-jalali";
import { useEffect, useState } from "react";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
export const ProvinceAllocated = ({ allocated }) => {
const [data, setData] = useState([]);
useEffect(() => {
const d = allocated?.map((item, i) => {
let assignmentState;
if (item.provinceKillRequestState === "accepted") {
assignmentState = "تایید شده";
} else if (item.provinceKillRequestState === "pending") {
assignmentState =
"در انتظار تایید و تخصیص خودرو توسط کشتارگاه می باشد.";
} else if (item.provinceKillRequestState === "rejected") {
assignmentState = "درخواست توسط کشتارگاه رد شده است!";
}
return [
`${item.killHouseName} (${item.killHouseUserName})`,
format(new Date(item.date), "yyyy/MM/dd"),
item.mainQuantity?.toLocaleString(),
item.automaticState ? "تخصیص خودکار" : "تخصیص دستی",
assignmentState,
];
});
setData(d);
}, []);
return (
<SimpleTable
columns={["خریدار", "تاریخ کشتار", "تعداد", "نوع تخصیص", "وضعیت"]}
data={data}
/>
);
};

View File

@@ -0,0 +1,105 @@
import { Grid } from "../../../../components/grid/Grid";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { PropTypes } from "prop-types";
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Typography } from "@mui/material";
import { format } from "date-fns-jalali";
export const ProvinceAllocationInformation = ({ item, i }) => {
let columns = [];
let data = [];
let state;
state =
item.provinceKillRequestState === "pending"
? "در انتظار تایید کشتارگاه"
: state;
state = item.provinceKillRequestState === "accepted" ? "تایید شده" : state;
state = item.provinceKillRequestState === "rejected" ? "رد شده" : state;
if (item.provinceKillRequestMessage) {
columns = [
"نام کشتارگاه",
"مالک کشتارگاه",
"تعداد تخصیص داده شده",
"تاریخ تخصیص",
"نحوه خرید",
"نوع تخصیص",
"وضعیت درخواست",
"دلیل رد",
];
data = [
item.killHouseName,
item.killHouseUserName,
item.mainQuantity + " قطعه",
format(new Date(item.date), "yyyy/MM/dd"),
item.paymentType,
item.automaticState ? "اتوماتیک" : "دستی",
state,
item.provinceKillRequestMessage,
];
} else {
columns = [
"نام کشتارگاه",
"مالک کشتارگاه",
"تعداد تخصیص داده شده",
"تاریخ تخصیص",
"نوع تخصیص",
"وضعیت درخواست",
];
data = [
item.killHouseName,
item.killHouseUserName,
item.mainQuantity + " قطعه",
format(new Date(item.date), "yyyy/MM/dd"),
item.automaticState ? "اتوماتیک" : "دستی",
state,
];
}
return (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent variant="body1" fontWeight="bold">
تخصیصات استان به کشتارگاه
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Typography variant="body2">
در این قسمت جزییات تخصیصات را مشاهده می کنید.
</Typography>
</TimelineContent>
</Grid>
</Grid>
<Grid>
<Grid key={"ProvinceAllocationInformation" + i}>
<Grid>
<SimpleTable
// name={`اطلاعات تخصیص شماره ${i + 1}`}
columns={columns}
data={[data]}
/>
</Grid>
</Grid>
</Grid>
</Grid>
</TimelineItem>
);
};
ProvinceAllocationInformation.propTypes = {
item: PropTypes.object,
i: PropTypes.any,
};

View File

@@ -0,0 +1,82 @@
import { Grid } from "../../../../components/grid/Grid";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { PropTypes } from "prop-types";
import { TimelineOppositeContent } from "@mui/lab";
import { format } from "date-fns-jalali";
export const ProvinceAllocationInformationContent = ({ item, i }) => {
let columns = [];
let data = [];
let state;
state =
item.provinceKillRequestState === "pending"
? "در انتظار تایید کشتارگاه"
: state;
state = item.provinceKillRequestState === "accepted" ? "تایید شده" : state;
state = item.provinceKillRequestState === "rejected" ? "رد شده" : state;
if (item.provinceKillRequestMessage) {
columns = [
"نام کشتارگاه",
"مالک کشتارگاه",
"تعداد تخصیص داده شده",
"تاریخ تخصیص",
"نحوه خرید",
"وضعیت درخواست",
"دلیل رد",
];
data = [
item.killHouseName,
item.killHouseUserName,
item.mainQuantity + " قطعه",
format(new Date(item.date), "yyyy/MM/dd"),
item.paymentType,
state,
item.provinceKillRequestMessage,
];
} else {
columns = [
"نام کشتارگاه",
"مالک کشتارگاه",
"تعداد تخصیص داده شده",
"تاریخ تخصیص",
"وضعیت درخواست",
];
data = [
item.killHouseName,
item.killHouseUserName,
item.mainQuantity + " قطعه",
format(new Date(item.date), "yyyy/MM/dd"),
state,
];
}
return (
<Grid>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent variant="body1" fontWeight="bold">
تخصیصات استان به کشتارگاه
</TimelineOppositeContent>
</Grid>
</Grid>
<Grid>
<Grid key={"ProvinceAllocationInformation" + i}>
<Grid>
<SimpleTable
// name={`اطلاعات تخصیص شماره ${i + 1}`}
columns={columns}
data={[data]}
/>
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
);
};
ProvinceAllocationInformationContent.propTypes = {
item: PropTypes.object,
i: PropTypes.any,
};

View File

@@ -0,0 +1,666 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Grid } from "../../../../components/grid/Grid";
import {
Button,
TextField,
// FormControl,
// FormControlLabel,
// Radio,
// RadioGroup,
Typography,
} from "@mui/material";
import React, { useEffect, useState } from "react";
import { PropTypes } from "prop-types";
import TimelineItem from "@mui/lab/TimelineItem";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import useGetAllocationInformation from "../../hooks/useGetAllocationInformation";
import { SPACING } from "../../../../data/spacing";
import { useDispatch, useSelector } from "react-redux";
// import PendingIcon from "@mui/icons-material/Pending";
import AccessTimeIcon from "@mui/icons-material/AccessTime";
import { format } from "date-fns-jalali";
// import { getSlaughterHousesRequest } from "../../services/getSlaughterHousesRequest";
import { ProvinceAuction } from "../province-auction/ProvinceAuction";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import ThumbDownAltIcon from "@mui/icons-material/ThumbDownAlt";
import { avicultureGetChickenPrice } from "../../../aviculture/services/aviculture-get-chicken-price";
import { provinceRemoveAllocation } from "../../services/province-remove-allocation";
import { SlaghterHouseRequestAllocationItem } from "../slaghterhouse-request-allocation-Item/SlaghterHouseRequestAllocationItem";
import { poultryRequestIndexWeightService } from "../../services/city-edit-avculture.info";
import MyTable from "../../../../components/my-table/MyTable";
import { getAllocationInformation } from "../../services/get-allocation-information";
import { provinceGetAllRequests } from "../../../province/services/province-get-all-requests";
import { getSlaughterHousesRequest } from "../../services/getSlaughterHousesRequest";
import useRequestFile, { getFileFromApi } from "../../hooks/useRequestFile";
import useUserProfile from "../../../authentication/hooks/useUserProfile";
import { LOADING_END, OPEN_MODAL } from "../../../../lib/redux/slices/appSlice";
// import useRequestFile from "../../hooks/useRequestFile";
import { ProvinceEditPoultryRequestForm } from "../../../province/components/province-edit-poultry-request-form/ProvinceEditPoultryRequestForm";
import { ProvinceAllocated } from "../province-allocated/ProvinceAllocated";
export const ProvinceAllocation = ({
id,
orginalQuantity,
// file,
item,
// remainQuantity,
getItemFreeSaleInProvince,
updateTable,
}) => {
const myFile = useRequestFile(id);
const file = myFile?.file?.process;
const [openNotif, , selectedDate1] = useContext(AppContext);
const remainQuantity = file?.poultry?.poultryRemainQuantity;
let { slaughterHousesRequest } = useSelector((state) => state.fileSlice);
const [, setRequestedWeight] = useState();
const [, setRequestedBuyType] = useState();
const [fileQauntity, setFileQauntity] = useState(remainQuantity);
useEffect(() => {
setFileQauntity(remainQuantity);
}, [remainQuantity, file]);
const [allEntredQauntity, setAllEntredQauntity] = useState(null);
const handleAllEntredQauntity = (q) => {
setAllEntredQauntity(q);
};
useEffect(() => {
// if (allEntredQauntity === null) {
// let obj = {};
// slaughterHousesRequest.map((item, i) => {
// obj = { ...obj, [i]: item.remainQuantity };
// });
// setAllEntredQauntity(obj);
// } else {
// const getSum = (a, b) => a + b;
// const dd = Object.values(allEntredQauntity).reduce(getSum, 0);
// setFileQauntity(file.poultry.poultryQuantity - dd);
// }
if (allEntredQauntity !== null) {
const getSum = (a, b) => a + b;
const dd = Object.values(allEntredQauntity).reduce(getSum, 0);
setFileQauntity(remainQuantity - dd);
}
}, [allEntredQauntity]);
useEffect(() => {
dispatch(poultryRequestIndexWeightService());
dispatch(getSlaughterHousesRequest(file?.poultry?.poultryRequestKey));
}, [file]);
// const [allocateOrAuction, setAllocateOrAuction] = useState("allocate");
const [allocateOrAuction] = useState("allocate");
const [slaughterAllocationLimit] = useState();
const getSum = (a, b) => a + b;
const avgLast4KillhousesWeight = Array.isArray(slaughterHousesRequest)
? slaughterHousesRequest
?.map((item) => item.firstAverageWeight)
?.reduce(getSum, 0) / slaughterHousesRequest?.length
: "";
// useEffect(() => {
// dispatch(
// getSlaughterHousesRequest({ key: file.poultry.poultryRequestKey })
// );
// }, []);
const allocationInformation = useGetAllocationInformation(
file?.poultry?.poultryRequestKey
);
const dispatch = useDispatch();
const [roles] = useUserProfile();
// const { avicultureChickenPrice } = useSelector(
// (state) => state.avicultureSlice
// );
// const liveChickenPrice = avicultureChickenPrice?.liveChickenPrice;
// calc suggest price
// const chickenWeight = parseFloat(
// file.poultry.poultryIndexWeight.split(" ")[0]
// );
// let suggestPrice = liveChickenPrice;
// const standardChicken = 2.75;
// const checkStep = 0.05;
// const costPerStep = 500;
// if (chickenWeight < 2.7) {
// const howMuchToReduce =
// ((standardChicken - chickenWeight).toFixed(2) / checkStep) * costPerStep;
// suggestPrice = liveChickenPrice - howMuchToReduce;
// }
useEffect(() => {
dispatch(avicultureGetChickenPrice());
}, []);
const formik = useFormik({
initialValues: {
quantity: "",
slaughterHouse: "",
paymentType: "cash",
// fee: "",
},
validationSchema: Yup.object({
quantity: Yup.number()
.test(
"testlimit",
"تعداد باید کمتر یا مساوی ظرفیت کشتارگاه و مانده درخواست باشد",
(val, context) => {
return (
context.originalValue &&
context.originalValue <= allocationInformation.quantity &&
context.originalValue <= slaughterAllocationLimit &&
context.originalValue > 0
);
}
)
// .max(allocationInformation.quantity, "بالاتر از ظرفیت وارد شده است")
.required("این فیلد اجباری است!")
.typeError("لطفا عدد وارد کنید!"),
slaughterHouse: Yup.string().required("این فیلد اجباری است!"),
paymentType: Yup.string().required("این فیلد اجباری است!"),
// fee: Yup.number().required("این فیلد اجباری است!"),
}),
});
useEffect(() => {
formik.validateForm();
}, []);
useEffect(() => {
if (!formik.values.slaughterHouse) {
setRequestedBuyType(null);
setRequestedWeight(null);
}
}, [formik.values.slaughterHouse]);
const fileWeight = file?.poultry?.IndexWeight;
let weightType;
const { poultryRequestIndexWeight } = useSelector((state) => state.fileSlice);
const avgPoultryRequestsWeight = poultryRequestIndexWeight?.ave;
if (fileWeight > avgPoultryRequestsWeight) {
weightType = "high";
} else if (fileWeight < avgPoultryRequestsWeight) {
weightType = "low";
}
slaughterHousesRequest = Array.isArray(slaughterHousesRequest)
? slaughterHousesRequest
: [];
const sortedSlaughterReqs = [...slaughterHousesRequest]?.sort(function (
a,
b
) {
if (weightType === "high") {
if (
a.firstAverageWeight < b.firstAverageWeight &&
a.killHouse.systemAddress?.city?.name === file?.poultry?.poultryCity
) {
return -1;
// return a.firstAverageWeight - b.firstAverageWeight;
}
}
if (weightType === "low") {
if (
a.firstAverageWeight > b.firstAverageWeight &&
a.killHouse.systemAddress?.city?.name === file?.poultry?.poultryCity
) {
return -1;
// return b.firstAverageWeight - a.firstAverageWeight;
}
}
return 0;
});
const totalAllocatedMainQuantity = allocationInformation?.provinceAssignments
?.length
? allocationInformation?.provinceAssignments?.reduce(
(accumulator, currentValue) => {
if (currentValue.provinceKillRequestState !== "rejected") {
return accumulator + currentValue.mainQuantity;
}
return accumulator;
},
0
)
: 0;
const defaultValueForAllocate = orginalQuantity - totalAllocatedMainQuantity;
const [searchText, setSearchText] = useState("");
return (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color="secondary" />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
انجام عملیات
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
{/* <Typography variant="body2">
در این مرحله سفارش را به کشتارگاه تخصیص دهید.
</Typography> */}
<Grid container gap={SPACING.LARGE} alignItems="center">
<Typography
variant="body1"
color={fileQauntity < 0 ? "red" : "black"}
>
تعداد اولیه درخواست کشتار: {orginalQuantity?.toLocaleString()}{" "}
قطعه
<Button
aria-label="delete"
color="primary"
onClick={() => {
dispatch(
OPEN_MODAL({
title: "ویرایش تعداد اولیه درخواست کشتار",
content: (
<ProvinceEditPoultryRequestForm
quantity={totalAllocatedMainQuantity}
poultryRequestKey={item.poultryRequest.key}
/>
),
})
);
}}
>
ویرایش
</Button>
</Typography>
<Typography
variant="body1"
color={fileQauntity < 0 ? "red" : "black"}
>
تخصیص داده شده:
{totalAllocatedMainQuantity?.toLocaleString()} قطعه
<Button
onClick={() => {
dispatch(
OPEN_MODAL({
title: "تخصیصات انجام شده",
content: (
<ProvinceAllocated
allocated={
allocationInformation?.provinceAssignments
}
/>
),
})
);
}}
>
مشاهده
</Button>
</Typography>
<Typography variant="body1" color={"green"}>
تعداد قابل تخصیص: {fileQauntity?.toLocaleString()} قطعه
</Typography>
<Typography variant="body1" color={"primary"}>
مرغدار:{" "}
{`${item?.poultryRequest?.poultry?.unitName} (${item?.poultryRequest?.poultry?.userprofile?.mobile})`}
</Typography>
<Typography variant="body1" color={"primary"}>
نوع فروش: {getItemFreeSaleInProvince(item)}
</Typography>
</Grid>
</TimelineContent>
</Grid>
</Grid>
{/* <Grid container>
<FormControl
sx={{
flexDirection: "row",
}}
>
<Grid container alignItems="center" gap={SPACING.MEDIUM}>
<FormLabel>فروش از طریق</FormLabel>
<RadioGroup
row
aria-labelledby="demo-row-radio-buttons-group-label"
name="row-radio-buttons-group"
onChange={(e) => {
setAllocateOrAuction(e.currentTarget.value);
}}
>
<FormControlLabel
value="allocate"
control={<Radio />}
label="تخصیص به کشتارگاه"
/>
<FormControlLabel
value="auction"
control={<Radio />}
label="مزایده"
/>
</RadioGroup>
</Grid>
</FormControl>
</Grid> */}
{allocateOrAuction === "allocate" && (
<Grid container direction="column" width="100%" alignItems="start">
<Grid
container
direction="column"
gap={SPACING.TINY}
mt={SPACING.SMALL}
>
<Grid container xs={12} gap={2}>
<TextField
label="جستجو بر اساس خریدار"
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
/>
<MyTable>
{sortedSlaughterReqs
?.filter((item) => {
const buyerNamePrefix = item?.killHouse?.killer
? "کشتارکن"
: "کشتارگاه";
const forSearch =
buyerNamePrefix + " " + item?.killHouse?.name;
return forSearch.includes(searchText);
})
.map((slaughterHouseReq, i) => {
return (
<SlaghterHouseRequestAllocationItem
name={i}
slaughterHouseReq={slaughterHouseReq}
avgLast4KillhousesWeight={avgLast4KillhousesWeight}
key={slaughterHouseReq?.name}
provinceCheckRequestKey={
file?.province?.provinceCheckRequestKey
}
poultryRequestKey={file?.poultry?.poultryRequestKey}
poultryRequestId={file?.poultry?.poultryRequestId}
file={file}
handleAllEntredQauntity={handleAllEntredQauntity}
allEntredQauntity={allEntredQauntity}
defaultValueForAllocate={defaultValueForAllocate}
updateTable={updateTable}
/>
);
})}
</MyTable>
</Grid>
{/* <Grid container direction="column" textAlign="initial">
<FormControl>
<Typography variant="body1">نحوه فروش</Typography>
<RadioGroup
aria-labelledby="demo-radio-buttons-group-label"
name="radio-buttons-group"
onChange={(event) => {
formik.setFieldValue(
"paymentType",
event.currentTarget.value
);
}}
>
<FormControlLabel
value="cash"
control={<Radio />}
label="نقدی"
/>
<FormControlLabel
value="credit"
control={<Radio />}
label="زمان دار (تا یک ماه)"
/>
</RadioGroup>
</FormControl>
</Grid> */}
{/* <Grid>
<TextField
id="fee"
label="قیمت"
variant="outlined"
error={formik.touched.fee ? Boolean(formik.errors.fee) : null}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.fee && Boolean(formik.errors.fee)
? formik.errors.fee
: null
}
/>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
قیمت مرغ استاندارد:
</Typography>
<Typography variant={"button"}>
{liveChickenPrice} ﷼
</Typography>
</Grid>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
قیمت پیشنهادی:
</Typography>
<Typography variant={"button"}>{suggestPrice} ﷼</Typography>
</Grid>
</Grid> */}
</Grid>
{/* <Grid
style={{
background: file?.poultry?.clearanceCode
? "#7aff7a"
: "#ff7a7a",
padding: "10px",
borderRadius: "5px",
width: "100%",
textAlign: "center",
}}
my={SPACING.SMALL}
>
<Typography fontWeight="bold" variant="body1">
کدرهگیری سامانه قرنطینه:{" "}
{file?.poultry?.clearanceCode
? file?.poultry?.clearanceCode
: "در انتظار صدور"}
</Typography>
</Grid> */}
<Grid textAlign={"start"} my={SPACING.SMALL}>
<Typography fontWeight="bold" variant="body1">
تخصیص های انجام شده
</Typography>
</Grid>
{!allocationInformation?.provinceAssignments?.length && (
<Typography textAlign={"start"} variant="body2">
تخصیصی انجام نشده است.
</Typography>
)}
{allocationInformation?.provinceAssignments?.map((item, i) => {
let assignmentState;
if (item.provinceKillRequestState === "accept") {
assignmentState = "تایید شده است.";
} else if (item.provinceKillRequestState === "pending") {
assignmentState =
"در انتظار تایید و تخصیص خودرو توسط کشتارگاه می باشد.";
} else if (item.provinceKillRequestState === "rejected") {
assignmentState = "درخواست توسط کشتارگاه رد شده است!";
}
return (
<Grid
container
gap={SPACING.MEDIUM}
alignItems={"center"}
mb={SPACING.SMALL}
key={i}
>
<Grid gap={SPACING.TINY} container direction={"column"}>
<Grid container gap={SPACING.SMALL} alignItems={"center"}>
<Grid>
<Typography variant={"caption"}>
{item.killHouseName} / {item.killHouseUserName} /
{item.killHouseMobile}
</Typography>
</Grid>
<Grid>
<Typography variant={"caption"}>
تاریخ کشتار{" "}
{format(new Date(item.date), "yyyy/MM/dd")}
</Typography>
</Grid>
<Grid>
<Typography variant={"caption"}>
{item.mainQuantity?.toLocaleString()} قطعه
</Typography>
</Grid>
<Grid>
<Typography
variant={"caption"}
fontWeight="bold"
color="error"
>
{item?.market
? "پنل معاملات"
: item.automaticState
? "تخصیص خودکار"
: "تخصیص دستی"}
</Typography>
</Grid>
</Grid>
<Grid
textAlign={"start"}
container
gap={SPACING.TINY}
alignItems={"center"}
>
{item.provinceKillRequestState !== "rejected" ? (
<AccessTimeIcon color={"primary"} />
) : (
<ThumbDownAltIcon color={"error"} />
)}
<Typography variant={"caption"}>
{assignmentState}
</Typography>
</Grid>
</Grid>
{item.provinceKillRequestState !== "rejected" &&
item?.returnToProvince === false && (
<Grid>
<Grid>
<Button
size={"small"}
variant="outlined"
color="error"
onClick={() => {
dispatch(
provinceRemoveAllocation({
key: item.provinceKillRequestKey,
})
).then((r) => {
if (r.error) {
dispatch(LOADING_END());
if (r.error.message.includes("403")) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "به علت تایید کشتارگاه امکان حذف تخصیص وجود ندارد!",
severity: "error",
});
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
}
} else {
getFileFromApi(roles, id, dispatch);
dispatch(
getSlaughterHousesRequest(
file?.poultry?.poultryRequestKey
)
);
dispatch(
provinceGetAllRequests(selectedDate1)
);
dispatch(
getAllocationInformation({
key: file?.poultry?.poultryRequestKey,
})
);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد!",
severity: "success",
});
updateTable();
}
});
}}
>
حذف
</Button>
</Grid>
</Grid>
)}
</Grid>
);
})}
</Grid>
)}
{allocateOrAuction === "auction" && (
<Grid>
<ProvinceAuction
poultryRequestKey={file?.poultry?.poultryRequestKey}
/>
</Grid>
)}
</Grid>
</TimelineItem>
);
};
ProvinceAllocation.propTypes = {
file: PropTypes.object,
};

View File

@@ -0,0 +1,613 @@
import { Autocomplete } from "@mui/lab";
import { Grid } from "../../../../components/grid/Grid";
import {
Button,
FormControl,
FormControlLabel,
Radio,
RadioGroup,
TextField,
Typography,
} from "@mui/material";
import React, { useEffect, useState } from "react";
import { PropTypes } from "prop-types";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import useSlaughterHousesRequest from "../../hooks/useSlaughterHousesRequest";
import useGetAllocationInformation from "../../hooks/useGetAllocationInformation";
import { SPACING } from "../../../../data/spacing";
import { useDispatch } from "react-redux";
import { provinceDoAllocation } from "../../services/province-do-allocation";
import { getSlaughterHousesForSelect } from "../../utils/getSlaughterHousesForSelect";
import {
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { getAllocationInformation } from "../../services/get-allocation-information";
// import PendingIcon from "@mui/icons-material/Pending";
import AccessTimeIcon from "@mui/icons-material/AccessTime";
import { format } from "date-fns-jalali";
// import { getSlaughterHousesRequest } from "../../services/getSlaughterHousesRequest";
import { ProvinceAuction } from "../province-auction/ProvinceAuction";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { getFileFromApi } from "../../hooks/useRequestFile";
import useUserProfile from "../../../authentication/hooks/useUserProfile";
import { useParams } from "react-router-dom";
import ThumbDownAltIcon from "@mui/icons-material/ThumbDownAlt";
import { avicultureGetChickenPrice } from "../../../aviculture/services/aviculture-get-chicken-price";
import { provinceRemoveAllocation } from "../../services/province-remove-allocation";
export const ProvinceAllocationContent = ({ file }) => {
const [openNotif] = useContext(AppContext);
const [selectedSlaughterHouseKey, setSelectedSlaughterHouseKey] =
useState(null);
const [requestedWeight, setRequestedWeight] = useState();
const [requestedBuyType, setRequestedBuyType] = useState();
// const [allocateOrAuction, setAllocateOrAuction] = useState("allocate");
const [allocateOrAuction] = useState("allocate");
const [slaughterAllocationLimit, setSlaughterAllocationLimit] = useState();
const slaughterHousesRequest = useSlaughterHousesRequest(
file.poultry.poultryRequestKey
);
// useEffect(() => {
// dispatch(
// getSlaughterHousesRequest({ key: file.poultry.poultryRequestKey })
// );
// }, []);
const allocationInformation = useGetAllocationInformation(
file.poultry.poultryRequestKey
);
const dispatch = useDispatch();
const [roles] = useUserProfile();
const { id } = useParams();
// const { avicultureChickenPrice } = useSelector(
// (state) => state.avicultureSlice
// );
// const liveChickenPrice = avicultureChickenPrice?.liveChickenPrice;
// calc suggest price
// const chickenWeight = parseFloat(
// file.poultry.poultryIndexWeight.split(" ")[0]
// );
// let suggestPrice = liveChickenPrice;
// const standardChicken = 2.75;
// const checkStep = 0.05;
// const costPerStep = 500;
// if (chickenWeight < 2.7) {
// const howMuchToReduce =
// ((standardChicken - chickenWeight).toFixed(2) / checkStep) * costPerStep;
// suggestPrice = liveChickenPrice - howMuchToReduce;
// }
// poultry sellType
const requestedSellTypeCash = file.poultry.sellType.cash ? "نقدی" : null;
const requestedSellTypeCredit = file.poultry.sellType.credit
? "زمان دار"
: null;
const requestedSellType = [requestedSellTypeCash, requestedSellTypeCredit]
.filter((item) => item)
.join(" یا ");
useEffect(() => {
dispatch(avicultureGetChickenPrice());
}, []);
const formik = useFormik({
initialValues: {
quantity: "",
slaughterHouse: "",
paymentType: "",
// fee: "",
},
validationSchema: Yup.object({
quantity: Yup.number()
.test(
"testlimit",
"تعداد باید کمتر یا مساوی ظرفیت کشتارگاه و مانده درخواست باشد",
(val, context) => {
return (
context.originalValue &&
context.originalValue <= allocationInformation.quantity &&
context.originalValue <= slaughterAllocationLimit &&
context.originalValue > 0
);
}
)
// .max(allocationInformation.quantity, "بالاتر از ظرفیت وارد شده است")
.required("این فیلد اجباری است!")
.typeError("لطفا عدد وارد کنید!"),
slaughterHouse: Yup.string().required("این فیلد اجباری است!"),
paymentType: Yup.string().required("این فیلد اجباری است!"),
// fee: Yup.number().required("این فیلد اجباری است!"),
}),
});
useEffect(() => {
formik.validateForm();
}, []);
useEffect(() => {
if (!formik.values.slaughterHouse) {
setRequestedBuyType(null);
setRequestedWeight(null);
}
}, [formik.values.slaughterHouse]);
return (
<>
<Grid container direction="column" flexWrap="nowrap" flex="1">
{/* <Grid container>
<FormControl
sx={{
flexDirection: "row",
}}
>
<Grid container alignItems="center" gap={SPACING.MEDIUM}>
<FormLabel>فروش از طریق</FormLabel>
<RadioGroup
row
aria-labelledby="demo-row-radio-buttons-group-label"
name="row-radio-buttons-group"
onChange={(e) => {
setAllocateOrAuction(e.currentTarget.value);
}}
>
<FormControlLabel
value="allocate"
control={<Radio />}
label="تخصیص به کشتارگاه"
/>
<FormControlLabel
value="auction"
control={<Radio />}
label="مزایده"
/>
</RadioGroup>
</Grid>
</FormControl>
</Grid> */}
{allocateOrAuction === "allocate" && (
<Grid container direction="column" alignItems="start">
<Grid
container
direction="column"
gap={SPACING.TINY}
mt={SPACING.SMALL}
>
<Grid>
<Autocomplete
disablePortal
options={getSlaughterHousesForSelect(slaughterHousesRequest)}
id="slaughterHouse"
value={formik.values.slaughterHouse}
onChange={(e, option) => {
// if (e.target.nodeName === "svg") {
// formik.setFieldValue("slaughterHouse", "");
// } else {
// const target = e.target || e.srcElement;
formik.setFieldValue("slaughterHouse", e.target.outerText);
if (option?.key) {
setSelectedSlaughterHouseKey(option.key);
}
setSlaughterAllocationLimit(option.remainQuantity);
setRequestedWeight(option.requestedWeight);
setRequestedBuyType(option.requestedBuyType);
// }
}}
onBlur={formik.handleBlur}
sx={{ width: "100%", minWidth: 300 }}
renderInput={(params) => (
<TextField
{...params}
label="کشتارگاه"
value={formik.values.slaughterHouse}
helperText={
formik.touched.slaughterHouse &&
Boolean(formik.errors.slaughterHouse)
? formik.errors.slaughterHouse
: null
}
error={
formik.touched.slaughterHouse
? Boolean(formik.errors.slaughterHouse)
: null
}
/>
)}
/>
</Grid>
<Grid>
<Grid container alignItems="center" gap={SPACING.SMALL}>
<Typography>مرغدار:</Typography>
<Grid>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
حدود وزنی اعلامی:
</Typography>
<Typography variant={"button"}>
{file.poultry.poultryIndexWeight}
</Typography>
</Grid>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
پیشنهاد فروش:
</Typography>
<Typography variant={"button"}>
{requestedSellType}
</Typography>
</Grid>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
کشتارگاه های پیشنهادی:
</Typography>
<Typography variant={"button"}>
{file?.poultry?.killHouseList?.join(" - ")}
</Typography>
</Grid>
</Grid>
</Grid>
<Grid container alignItems="center" gap={SPACING.SMALL}>
<Typography>کشتارگاه:</Typography>
<Grid>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
پیشنهاد وزن:
</Typography>
<Typography variant={"button"}>
{requestedWeight}
</Typography>
</Grid>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
پیشنهاد خرید:
</Typography>
<Typography variant={"button"}>
{requestedBuyType}
</Typography>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid>
<TextField
id="quantity"
label="حجم"
variant="outlined"
error={
formik.touched.quantity
? Boolean(formik.errors.quantity)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.quantity && Boolean(formik.errors.quantity)
? formik.errors.quantity
: null
}
/>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
مانده درخواست
</Typography>
<Typography variant={"button"}>
{allocationInformation.quantity - formik.values.quantity >=
0
? allocationInformation.quantity - formik.values.quantity
: allocationInformation.quantity}{" "}
قطعه
</Typography>
</Grid>
</Grid>
<Grid container direction="column" textAlign="initial">
<FormControl>
<Typography variant="body1">نحوه فروش</Typography>
<RadioGroup
aria-labelledby="demo-radio-buttons-group-label"
name="radio-buttons-group"
onChange={(event) => {
formik.setFieldValue(
"paymentType",
event.currentTarget.value
);
}}
>
<FormControlLabel
value="cash"
control={<Radio />}
label="نقدی"
/>
<FormControlLabel
value="credit"
control={<Radio />}
label="زمان دار (تا یک ماه)"
/>
</RadioGroup>
</FormControl>
</Grid>
{/* <Grid>
<TextField
id="fee"
label="قیمت"
variant="outlined"
error={formik.touched.fee ? Boolean(formik.errors.fee) : null}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.fee && Boolean(formik.errors.fee)
? formik.errors.fee
: null
}
/>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
قیمت مرغ استاندارد:
</Typography>
<Typography variant={"button"}>
{liveChickenPrice} ﷼
</Typography>
</Grid>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
قیمت پیشنهادی:
</Typography>
<Typography variant={"button"}>{suggestPrice} ﷼</Typography>
</Grid>
</Grid> */}
<Grid>
<Button
size={"large"}
variant="contained"
disabled={!formik.isValid}
onClick={() => {
dispatch(LOADING_START());
dispatch(
provinceDoAllocation({
kill_request_key: selectedSlaughterHouseKey,
province_check_request_key:
file.province.provinceCheckRequestKey,
quantity: formik.values.quantity,
payment_type: formik.values.paymentType,
// fee: formik.values.fee,
})
).then((r) => {
dispatch(LOADING_END());
dispatch(
getAllocationInformation({
key: file.poultry.poultryRequestKey,
})
);
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
getFileFromApi(roles, id, dispatch);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
}}
>
ثبت اطلاعات
</Button>
</Grid>
</Grid>
<Grid textAlign={"start"} my={SPACING.SMALL}>
<Typography fontWeight="bold" variant="body1">
تخصیص های انجام شده
</Typography>
</Grid>
{!allocationInformation?.provinceAssignments?.length && (
<Typography textAlign={"start"} variant="body2">
تخصیصی انجام نشده است.
</Typography>
)}
{allocationInformation?.provinceAssignments?.map((item, i) => {
let assignmentState;
if (item.provinceKillRequestState === "accept") {
assignmentState = "تایید شده است.";
} else if (item.provinceKillRequestState === "pending") {
assignmentState =
"در انتظار تایید و تخصیص خودرو توسط کشتارگاه می باشد.";
} else if (item.provinceKillRequestState === "rejected") {
assignmentState = "درخواست توسط کشتارگاه رد شده است!";
}
return (
<Grid
container
gap={SPACING.MEDIUM}
alignItems={"center"}
mb={SPACING.SMALL}
key={i}
>
<Grid gap={SPACING.TINY} container direction={"column"}>
<Grid container gap={SPACING.SMALL} alignItems={"center"}>
<Grid>
<Typography variant={"caption"}>
{item.killHouseName} / {item.killHouseUserName} /
{item.killHouseMobile}
</Typography>
</Grid>
<Grid>
<Typography variant={"caption"}>
تاریخ کشتار{" "}
{format(new Date(item.date), "yyyy/MM/dd")}
</Typography>
</Grid>
<Grid>
<Typography variant={"caption"}>
{item.quantity} قطعه
</Typography>
</Grid>
</Grid>
<Grid
textAlign={"start"}
container
gap={SPACING.TINY}
alignItems={"center"}
>
{item.provinceKillRequestState !== "rejected" ? (
<AccessTimeIcon color={"primary"} />
) : (
<ThumbDownAltIcon color={"error"} />
)}
<Typography variant={"caption"}>
{assignmentState}
</Typography>
</Grid>
</Grid>
{item.provinceKillRequestState !== "rejected" && (
<Grid>
<Grid>
<Button
size={"small"}
variant="outlined"
color="error"
onClick={() => {
dispatch(
provinceRemoveAllocation({
key: item.provinceKillRequestKey,
})
).then((r) => {
if (r.error) {
if (r.error.message.includes("403")) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "به علت تایید کشتارگاه امکان حذف تخصیص وجود ندارد!",
severity: "error",
});
} else {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
}
} else {
getFileFromApi(roles, id, dispatch);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد!",
severity: "success",
});
}
});
}}
>
حذف
</Button>
</Grid>
</Grid>
)}
</Grid>
);
})}
</Grid>
)}
{allocateOrAuction === "auction" && (
<Grid>
<ProvinceAuction
poultryRequestKey={file.poultry.poultryRequestKey}
/>
</Grid>
)}
</Grid>
</>
);
};
ProvinceAllocationContent.propTypes = {
file: PropTypes.object,
};

View File

@@ -0,0 +1,24 @@
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import TimelineOppositeContent from "@mui/lab/TimelineOppositeContent";
import { Typography } from "@mui/material";
export const ProvinceAllocationTitle = ({ file }) => {
return (
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
مرحله تخصیص استان
</Typography>
</TimelineOppositeContent>
</Grid>
</Grid>
</Grid>
);
};
ProvinceAllocationTitle.propTypes = {
file: PropTypes.any,
};

View File

@@ -0,0 +1,311 @@
import {
Button,
Divider,
FormControl,
FormHelperText,
IconButton,
InputLabel,
MenuItem,
Select,
TextField,
Typography,
} from "@mui/material";
import { useFormik } from "formik";
import moment from "moment";
import { useContext, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { PropTypes } from "prop-types";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { Yup } from "../../../../lib/yup/yup";
import { avicultureGetChickenPrice } from "../../../aviculture/services/aviculture-get-chicken-price";
import { avicultureGetRequests } from "../../../aviculture/services/aviculture-requests";
import DeleteIcon from "@mui/icons-material/Delete";
import AddIcon from "@mui/icons-material/Add";
import { provinceRequestAuction } from "../../services/province-request-auction";
import { AppContext } from "../../../../contexts/AppContext";
import { getFileFromApi } from "../../hooks/useRequestFile";
import { useParams } from "react-router-dom";
import useUserProfile from "../../../authentication/hooks/useUserProfile";
export const ProvinceAuction = ({ poultryRequestKey }) => {
const [pricingKey, setPriceKey] = useState();
const { id } = useParams();
const [roles] = useUserProfile();
const { avicultureChickenPrice } = useSelector(
(state) => state.avicultureSlice
);
const [openNotif] = useContext(AppContext);
const dispatch = useDispatch();
useEffect(() => {
dispatch(avicultureGetChickenPrice());
}, []);
const [arr, setArr] = useState([
{
id: 0,
value: "",
hour: 2,
},
]);
const addInput = () => {
setArr((prevState) => {
return [
...prevState,
{
id: prevState.length,
value: "",
hour: 1,
},
];
});
};
const removeInput = (e) => {
let number = arr.length - 1;
if (number !== 0) {
let filteredArrayPrice = arr.filter((object, i) => i < number);
// let filteredArrayTime = arrPrices.filter((object, i) => i < number);
setArr(filteredArrayPrice);
// setArrPrices(filteredArrayTime);
}
};
const handleChange = (e) => {
const [itemName, itemIndex] = e.target.name.split("-");
if (itemName === "price") {
setArr((prevState) => {
const newState = prevState;
newState[itemIndex].value = e.target.value;
return newState;
});
} else if (itemName === "hour") {
setArr((prevState) => {
const newState = prevState;
newState[itemIndex].hour = Number(e.target.value);
return newState;
});
}
};
useEffect(() => {
if (avicultureChickenPrice) {
setPriceKey(avicultureChickenPrice.key);
}
}, [avicultureChickenPrice]);
const formik = useFormik({
initialValues: {
noChicken: "",
price1: "",
price2: "",
price3: "",
slaughterDate: moment(Date()).format("YYYY-MM-DD hh:mm:ss"),
period1: "4",
period2: "4",
period3: "4",
weight: "",
},
validationSchema: Yup.object({
price1: Yup.number()
.typeError("لطفا عدد وارد کنید!")
.min(
avicultureChickenPrice?.floorPrice,
"قیمت وارد شده از کف قیمت امروز کمتر است"
)
.max(
avicultureChickenPrice?.ceilingPrice,
"قیمت وارد شده از سقف قیمت امروز بیشتر است"
),
price2: Yup.number()
.typeError("لطفا عدد وارد کنید!")
.min(
avicultureChickenPrice?.floorPrice,
"قیمت وارد شده از کف قیمت امروز کمتر است"
)
.max(
avicultureChickenPrice?.ceilingPrice,
"قیمت وارد شده از سقف قیمت امروز بیشتر است"
),
price3: Yup.number()
.typeError("لطفا عدد وارد کنید!")
.min(
avicultureChickenPrice?.floorPrice,
"قیمت وارد شده از کف قیمت امروز کمتر است"
)
.max(
avicultureChickenPrice?.ceilingPrice,
"قیمت وارد شده از سقف قیمت امروز بیشتر است"
),
weight: Yup.number()
.required("این فیلد اجباری است!")
.typeError("لطفا وزن را وارد کنید!"),
}),
});
return (
<Grid container gap={SPACING.SMALL}>
<Grid container gap={SPACING.SMALL} alignItems={"center"}>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
کف قیمت امروز:
</Typography>
<Typography color="secondary" variant={"button"}>
{avicultureChickenPrice?.floorPrice
? avicultureChickenPrice?.floorPrice.toLocaleString()
: "نامشخص"}{" "}
{" "}
ریال
</Typography>
</Grid>
<Grid container gap={SPACING.SMALL} alignItems={"center"}>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
سقف قیمت امروز:
</Typography>
<Typography color="secondary" variant={"button"}>
{avicultureChickenPrice?.ceilingPrice
? avicultureChickenPrice?.ceilingPrice.toLocaleString()
: "نامشخص"}{" "}
{" "}
ریال
</Typography>
</Grid>
<Divider style={{ width: "100%" }} />
<Grid container direction="column">
<Grid
container
direction="column"
gap={SPACING.SMALL}
alignItems="start"
>
<Grid container gap={SPACING.MEDIUM} alignItems="center">
{arr.map((item, i) => {
return (
<Grid gap={SPACING.SMALL} container key={i}>
<Typography variant="body2" fontWeight="bold">
پیشنهاد {i + 1}
</Typography>
<TextField
error={false}
fullWidth
label="قیمت پیشنهادی"
variant="outlined"
onChange={handleChange}
name={"price-" + i}
/>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">
بازه زمانی (ساعت)
</InputLabel>
<Select
labelId="demo-simple-select-label"
label="بازه زمانی (ساعت)"
name={"hour-" + i}
onChange={handleChange}
>
<MenuItem value={"1"}>1</MenuItem>
<MenuItem value={"2"}>2</MenuItem>
<MenuItem value={"3"}>3</MenuItem>
<MenuItem value={"4"}>4</MenuItem>
<MenuItem value={"5"}>5</MenuItem>
<MenuItem value={"6"}>6</MenuItem>
<MenuItem value={"7"}>7</MenuItem>
<MenuItem value={"8"}>8</MenuItem>
<MenuItem value={"9"}>9</MenuItem>
<MenuItem value={"10"}>10</MenuItem>
</Select>
<FormHelperText>
{formik.touched.period1 && Boolean(formik.errors.period1)
? formik.errors.period1
: null}
</FormHelperText>
</FormControl>
{/* <input
key={i}
onChange={handleChange}
value={item.value}
id={i}
type={item.type}
/> */}
</Grid>
);
})}
<Grid container direction="column">
<IconButton aria-label="delete" color="secondary">
<DeleteIcon onClick={removeInput} />
</IconButton>
<IconButton aria-label="delete" color="success">
<AddIcon onClick={addInput} />
</IconButton>
</Grid>
</Grid>
</Grid>
</Grid>
<Button
fullWidth
disabled={!formik.isValid}
onClick={() => {
dispatch(LOADING_START());
dispatch(
provinceRequestAuction({
poultry_request_key: poultryRequestKey,
auction_list: arr.map((item, i) => {
return {
pricing_key: pricingKey,
fee: item.value,
hour: item.hour,
};
}),
})
).then((r) => {
dispatch(LOADING_END());
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
severity: "error",
msg: "مشکلی پیش آمده است!",
});
} else {
dispatch(avicultureGetRequests());
getFileFromApi(roles, id, dispatch);
openNotif({
vertical: "top",
horizontal: "center",
severity: "success",
msg: "با موفقیت انجام شد!",
});
dispatch(DRAWER({ right: false, bottom: false, content: null }));
}
});
}}
size="large"
variant="contained"
>
ثبت درخواست
</Button>
</Grid>
);
};
ProvinceAuction.propTypes = {
poultryRequestKey: PropTypes.any,
};

View File

@@ -0,0 +1,322 @@
import {
TimelineConnector,
TimelineContent,
// TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Button, TextField, Typography } from "@mui/material";
import React, { useEffect, useState } from "react";
// import { formatTime } from "../../../../utils/formatTime";
import { PropTypes } from "prop-types";
import { SPACING } from "../../../../data/spacing";
import { Grid } from "../../../../components/grid/Grid";
import { AnimatePresence, motion } from "framer-motion";
import { useDispatch } from "react-redux";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import { provinceAcceptRequest } from "../../services/provinceAcceptRequest";
import {
CLOSE_MODAL,
DRAWER,
LOADING_END,
LOADING_START,
OPEN_MODAL,
} from "../../../../lib/redux/slices/appSlice";
import { provinceRejectRequest } from "../../services/provinceRejectRequest";
import useRequestFile from "../../hooks/useRequestFile";
// import useUserProfile from "../../../authentication/hooks/useUserProfile";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { getProvinceNewRequests } from "../../../province/services/get-province-new-requests";
const ProvinceCheckRequest = ({ id, file, item, updateTable }) => {
const myFile = useRequestFile(id);
file = file ? file : myFile?.file?.process;
const [openNotif, , selectedDate1, , selectedDate2, ,] =
useContext(AppContext);
const [isSubmited, setIsSubmited] = useState(false);
// const [roles] = useUserProfile();
useEffect(() => {
if (file?.province !== null) {
setIsSubmited(true);
}
}, [file]);
const formik = useFormik({
initialValues: {
rejectText: "",
},
validationSchema: Yup.object({
rejectText: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا دلیل خود را بیان کنید."),
}),
});
const [isDenyed, setisDenyed] = useState(false);
// const animationControl = useAnimation();
// useEffect(() => {
// if (isDenyed) {
// animationControl.start({
// x: -10,
// display: "block",
// transition: { duration: 0.3 },
// });
// }
// }, [isDenyed]);
// const MotionInput = motion(TextField);
const dispatch = useDispatch();
return (
<>
{!isSubmited && (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color="secondary" />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
انجام عملیات
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Typography variant="body2">
در این مرحله درخواست را تایید یا رد کنید.
</Typography>
</TimelineContent>
</Grid>
</Grid>
<Grid>
<Grid xs={12}>
<Grid container gap={SPACING.SMALL} padding={SPACING.SMALL}>
<AnimatePresence>
{isDenyed ? (
<motion.div
animate={{ x: -10, opacity: 1 }}
transition={{ duration: 0.3 }}
initial={{ opacity: 0 }}
exit={{ opacity: 0 }}
>
<Grid
flexDirection={"column"}
container
gap={SPACING.SMALL}
>
<Grid>
<TextField
multiline
rows={4}
fullWidth
id="rejectText"
label="پیام خود را وارد کنید"
variant="outlined"
value={formik.values.rejectText}
error={
formik.touched.rejectText
? Boolean(formik.errors.rejectText)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.rejectText &&
Boolean(formik.errors.rejectText)
? formik.errors.rejectText
: null
}
/>
</Grid>
<Grid container gap={SPACING.SMALL}>
<Grid>
<Button
variant="outlined"
color="secondary"
onClick={() => {
setisDenyed(false);
}}
>
لغو
</Button>
</Grid>
<Grid>
<Button
disabled={!formik.values.rejectText}
variant="outlined"
onClick={() => {
dispatch(LOADING_START());
dispatch(
provinceRejectRequest({
message: formik.values.rejectText,
key: item?.cityCheckRequest,
state: "reject",
})
).then((r) => {
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
updateTable();
dispatch(
DRAWER({
right: false,
bottom: false,
content: null,
})
);
dispatch(
getProvinceNewRequests({
selectedDate1,
selectedDate2,
})
);
// getFileFromApi(roles, id, dispatch);
dispatch(LOADING_END());
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
}}
>
رد اطلاعات و پیام به مرغدار
</Button>
</Grid>
</Grid>
</Grid>
</motion.div>
) : (
<Grid container gap={SPACING.SMALL} xs={12}>
<Button
fullWidth
variant="outlined"
color="secondary"
onClick={() => {
setisDenyed(true);
}}
>
رد اطلاعات و پیام به مرغدار
</Button>
<Button
fullWidth
variant="outlined"
onClick={() => {
dispatch(LOADING_START());
dispatch(
provinceAcceptRequest({
key: item?.cityCheckRequest,
state: "accept",
})
).then((r) => {
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
// getFileFromApi(roles, id, dispatch);
updateTable();
dispatch(
getProvinceNewRequests({
selectedDate1,
selectedDate2,
})
);
dispatch(
DRAWER({
right: false,
bottom: false,
content: null,
})
);
dispatch(
OPEN_MODAL({
title: "عملیات با موفقیت انجام شد.",
content: (
<Grid
container
direction="column"
gap={SPACING.MEDIUM}
alignItems="center"
justifyContent="center"
>
<Grid>
<Typography color={"green"}>
پرونده به کارتابل (در انتظار تخصیص)
انتقال پیدا کرد.
</Typography>
</Grid>
<Grid>
<Button
variant="contained"
color="success"
onClick={() => {
dispatch(CLOSE_MODAL());
}}
>
تایید
</Button>
</Grid>
</Grid>
),
})
);
dispatch(
getProvinceNewRequests({
selectedDate1,
selectedDate2,
})
);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
dispatch(LOADING_END());
updateTable();
}
});
}}
>
تایید و اختصاص به کشتارگاه
</Button>
</Grid>
)}
</AnimatePresence>
</Grid>
</Grid>
</Grid>
</Grid>
</TimelineItem>
)}
</>
);
};
ProvinceCheckRequest.propTypes = {
file: PropTypes.object,
};
export default ProvinceCheckRequest;

View File

@@ -0,0 +1,254 @@
import {
TimelineConnector,
TimelineContent,
// TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Button, TextField, Typography } from "@mui/material";
import React, { useState } from "react";
// import { formatTime } from "../../../../utils/formatTime";
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import { useDispatch } from "react-redux";
import { AnimatePresence, motion } from "framer-motion";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { provinceFinancialSlaughterCheckRequest } from "../../services/provinceFinancialSlaughterCheckRequest";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { provinceFinancialGetPayedFactorsService } from "../../../province-finacial/services/province-financial-get-payed-factors-service";
const ProvinceFinancialSlaughterCheckRequest = ({ factorKey, factorType }) => {
const [openNotif] = useContext(AppContext);
const [isSubmited] = useState(false);
const [isDenyed, setisDenyed] = useState(false);
const dispatch = useDispatch();
const formik = useFormik({
initialValues: {
rejectText: "",
},
validationSchema: Yup.object({
rejectText: Yup.string()
.required("این فیلد اجباری است!")
.typeError("لطفا دلیل خود را بیان کنید."),
}),
});
return (
<>
{!isSubmited && (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color="secondary" />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
انجام عملیات
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Typography variant="body2">
در این مرحله فاکتور پرداخت را تایید یا رد کنید.
</Typography>
</TimelineContent>
</Grid>
</Grid>
<Grid>
<Grid>
<Grid container gap={SPACING.SMALL} padding={SPACING.SMALL}>
<AnimatePresence>
{isDenyed ? (
<motion.div
animate={{ x: -10, opacity: 1 }}
transition={{ duration: 0.3 }}
initial={{ opacity: 0 }}
exit={{ opacity: 0 }}
>
<Grid
flexDirection={"column"}
container
gap={SPACING.SMALL}
>
<Grid>
<TextField
multiline
rows={4}
fullWidth
id="rejectText"
label="پیام خود را وارد کنید"
variant="outlined"
value={formik.values.rejectText}
error={
formik.touched.rejectText
? Boolean(formik.errors.rejectText)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.rejectText &&
Boolean(formik.errors.rejectText)
? formik.errors.rejectText
: null
}
/>
</Grid>
<Grid container gap={SPACING.SMALL}>
<Grid>
<Button
variant="outlined"
color="secondary"
onClick={() => {
setisDenyed(false);
}}
>
لغو
</Button>
</Grid>
<Grid>
<Button
variant="outlined"
onClick={() => {
dispatch(LOADING_START());
dispatch(
provinceFinancialSlaughterCheckRequest({
key: factorKey,
type: factorType,
message: formik.values.rejectText,
state: "rejected",
})
).then((r) => {
dispatch(LOADING_END());
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
setisDenyed(false);
// getFileFromApi(roles, id, dispatch);
dispatch(
provinceFinancialGetPayedFactorsService()
);
dispatch(
DRAWER({
right: false,
bottom: false,
top: false,
content: null,
size: null,
})
);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
}}
>
رد پرداخت
</Button>
</Grid>
</Grid>
</Grid>
</motion.div>
) : (
<Grid container gap={SPACING.SMALL}>
<Button
variant="outlined"
color="secondary"
onClick={() => {
setisDenyed(true);
}}
>
رد پرداخت
</Button>
<Button
variant="outlined"
onClick={() => {
dispatch(LOADING_START());
dispatch(
provinceFinancialSlaughterCheckRequest({
key: factorKey,
type: factorType,
state: "accepted",
})
).then((r) => {
dispatch(LOADING_END());
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
// getFileFromApi(roles, id, dispatch);
dispatch(
provinceFinancialGetPayedFactorsService()
);
dispatch(
DRAWER({
right: false,
bottom: false,
top: false,
content: null,
size: null,
})
);
setisDenyed(false);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
}}
>
تایید پرداخت
</Button>
</Grid>
)}
</AnimatePresence>
</Grid>
</Grid>
</Grid>
</Grid>
</TimelineItem>
)}
</>
);
};
ProvinceFinancialSlaughterCheckRequest.propTypes = {
factorKey: PropTypes.any,
factorType: PropTypes.any,
};
export default ProvinceFinancialSlaughterCheckRequest;

View File

@@ -0,0 +1,143 @@
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { PropTypes } from "prop-types";
import { useEffect, useState } from "react";
import TimelineSeparator from "@mui/lab/TimelineSeparator";
import TimelineDot from "@mui/lab/TimelineDot";
import TimelineConnector from "@mui/lab/TimelineConnector";
import { Grid } from "../../../../components/grid/Grid";
import TimelineOppositeContent from "@mui/lab/TimelineOppositeContent";
import { Typography } from "@mui/material";
import TimelineContent from "@mui/lab/TimelineContent";
import { SPACING } from "../../../../data/spacing";
import TimelineItem from "@mui/lab/TimelineItem";
import { formatTime } from "../../../../utils/formatTime";
import { format } from "date-fns-jalali";
export const ProvinceInformation = ({ file, quantity }) => {
const [provinceInfoData, setProvinceInfoData] = useState({
provinceOperatorName: "اپراتور استان",
provinceOperatorMobile: "-",
acceptedRejectedDate: null,
provinceState: "در انتظار تایید",
});
const { province, provinceOperator } = file;
useEffect(() => {
let provinceOperatorName,
provinceOperatorMobile,
acceptedRejectedDate,
provinceState;
if (province) {
provinceOperatorName = province.provinceOperatorName;
provinceOperatorMobile = province.provinceOperatorMobile;
acceptedRejectedDate = province.acceptedRejectedDate;
provinceState =
province.provinceState === "accept" ? "تایید شده" : "رد شده";
} else {
provinceOperatorName = provinceOperator?.provinceOperatorName;
provinceOperatorMobile = provinceOperator?.provinceOperatorMobile;
acceptedRejectedDate = null;
provinceState = "در انتظار تایید";
}
setProvinceInfoData({
provinceOperatorName,
provinceOperatorMobile,
acceptedRejectedDate,
provinceState,
});
}, [province]);
return (
<>
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
مرحله استان
</Typography>
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Grid container gap={SPACING.SMALL}>
{provinceInfoData.provinceState === "در انتظار تایید" ? (
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
درخواست منتظر انجام عملیات توسط اپراتور می باشد.
</Typography>
) : (
<>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
درخواست در تاریخ
</Typography>
<Typography variant="body2" fontWeight="bold">
{provinceInfoData.acceptedRejectedDate
? formatTime(provinceInfoData.acceptedRejectedDate)
: "-"}
</Typography>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
{provinceInfoData.provinceState} است.
</Typography>
</>
)}
</Grid>
</TimelineContent>
</Grid>
</Grid>
<Grid>
<Grid xs={12}>
<SimpleTable
columns={[
"نام اپراتور",
"تلفن",
"استان",
"تاریخ بررسی",
"وضعیت درخواست",
"وضعیت تخصیص",
province?.provinceMessage ? "دلیل رد" : "",
]}
data={[
[
provinceInfoData.provinceOperatorName,
provinceInfoData.provinceOperatorMobile,
provinceOperator.provinceOperatorProvinc,
format(
new Date(provinceInfoData.acceptedRejectedDate),
"yyyy/MM/dd"
),
provinceInfoData.provinceState,
quantity !== 0 ? "در انتظار تخصیص استان" : "تخصیص داده شده",
province?.provinceMessage ? province?.provinceMessage : "",
],
]}
/>
</Grid>
</Grid>
</Grid>
</TimelineItem>
</>
);
};
ProvinceInformation.propTypes = {
file: PropTypes.any,
quantity: PropTypes.any,
};

View File

@@ -0,0 +1,80 @@
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { PropTypes } from "prop-types";
import { useEffect, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { format } from "date-fns-jalali";
export const ProvinceInformationContent = ({ file, quantity }) => {
const [provinceInfoData, setProvinceInfoData] = useState({
provinceOperatorName: "اپراتور استان",
provinceOperatorMobile: "-",
acceptedRejectedDate: null,
provinceState: "در انتظار تایید",
});
const { province, provinceOperator } = file;
useEffect(() => {
let provinceOperatorName,
provinceOperatorMobile,
acceptedRejectedDate,
provinceState;
if (province) {
provinceOperatorName = province.provinceOperatorName;
provinceOperatorMobile = province.provinceOperatorMobile;
acceptedRejectedDate = province.acceptedRejectedDate;
provinceState =
province.provinceState === "accept" ? "تایید شده" : "رد شده";
} else {
provinceOperatorName = provinceOperator?.provinceOperatorName;
provinceOperatorMobile = provinceOperator?.provinceOperatorMobile;
acceptedRejectedDate = null;
provinceState = "در انتظار تایید";
}
setProvinceInfoData({
provinceOperatorName,
provinceOperatorMobile,
acceptedRejectedDate,
provinceState,
});
}, [province]);
return (
<>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid xs={12}>
<SimpleTable
columns={[
"نام اپراتور",
"تلفن",
"استان",
"تاریخ بررسی",
"وضعیت درخواست",
"وضعیت تخصیص",
province?.provinceMessage ? "دلیل رد" : "",
]}
data={[
[
provinceInfoData.provinceOperatorName,
provinceInfoData.provinceOperatorMobile,
provinceOperator.provinceOperatorProvinc,
format(
new Date(provinceInfoData.acceptedRejectedDate),
"yyyy/MM/dd"
),
provinceInfoData.provinceState,
quantity !== 0 ? "در انتظار تخصیص استان" : "تخصیص داده شده",
province?.provinceMessage ? province?.provinceMessage : "",
],
]}
/>
</Grid>
</Grid>
</>
);
};
ProvinceInformationContent.propTypes = {
file: PropTypes.any,
quantity: PropTypes.any,
};

View File

@@ -0,0 +1,96 @@
import { PropTypes } from "prop-types";
import { useEffect, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import TimelineOppositeContent from "@mui/lab/TimelineOppositeContent";
import { Typography } from "@mui/material";
import TimelineContent from "@mui/lab/TimelineContent";
import { SPACING } from "../../../../data/spacing";
import { formatTime } from "../../../../utils/formatTime";
export const ProvinceInformationTitle = ({ file, quantity }) => {
const [provinceInfoData, setProvinceInfoData] = useState({
provinceOperatorName: "اپراتور استان",
provinceOperatorMobile: "-",
acceptedRejectedDate: null,
provinceState: "در انتظار تایید",
});
const { province, provinceOperator } = file;
useEffect(() => {
let provinceOperatorName,
provinceOperatorMobile,
acceptedRejectedDate,
provinceState;
if (province) {
provinceOperatorName = province.provinceOperatorName;
provinceOperatorMobile = province.provinceOperatorMobile;
acceptedRejectedDate = province.acceptedRejectedDate;
provinceState =
province.provinceState === "accept" ? "تایید شده" : "رد شده";
} else {
provinceOperatorName = provinceOperator?.provinceOperatorName;
provinceOperatorMobile = provinceOperator?.provinceOperatorMobile;
acceptedRejectedDate = null;
provinceState = "در انتظار تایید";
}
setProvinceInfoData({
provinceOperatorName,
provinceOperatorMobile,
acceptedRejectedDate,
provinceState,
});
}, [province]);
return (
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
مرحله استان
</Typography>
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Grid container gap={SPACING.SMALL}>
{provinceInfoData.provinceState === "در انتظار تایید" ? (
<Typography variant="body2" display="flex" gap={SPACING.SMALL}>
درخواست منتظر انجام عملیات توسط اپراتور می باشد.
</Typography>
) : (
<>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
درخواست در تاریخ
</Typography>
<Typography variant="body2" fontWeight="bold">
{provinceInfoData.acceptedRejectedDate
? formatTime(provinceInfoData.acceptedRejectedDate)
: "-"}
</Typography>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
{provinceInfoData.provinceState} است.
</Typography>
</>
)}
</Grid>
</TimelineContent>
</Grid>
</Grid>
</Grid>
);
};
ProvinceInformationTitle.propTypes = {
file: PropTypes.any,
quantity: PropTypes.any,
};

View File

@@ -0,0 +1,24 @@
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import TimelineOppositeContent from "@mui/lab/TimelineOppositeContent";
import { Typography } from "@mui/material";
export const SlaghterCheckRequestTitle = ({ file }) => {
return (
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
مرحله تایید کشتارگاه
</Typography>
</TimelineOppositeContent>
</Grid>
</Grid>
</Grid>
);
};
SlaghterCheckRequestTitle.propTypes = {
file: PropTypes.any,
};

View File

@@ -0,0 +1,306 @@
import {
Button,
Checkbox,
TableCell,
TableRow,
TextField,
Tooltip,
} from "@mui/material";
import { useFormik } from "formik";
import React, { useContext, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
// import { useParams } from "react-router-dom";
import { Grid } from "../../../../components/grid/Grid";
import { AppContext } from "../../../../contexts/AppContext";
import {
LOADING_END,
LOADING_START,
OPEN_MODAL,
} from "../../../../lib/redux/slices/appSlice";
// import useUserProfile from "../../../authentication/hooks/useUserProfile";
// import { getFileFromApi } from "../../hooks/useRequestFile";
import { getAllocationInformation } from "../../services/get-allocation-information";
import { provinceDoAllocation } from "../../services/province-do-allocation";
import * as Yup from "yup";
// import useUserProfile from "../../../authentication/hooks/useUserProfile";
// import { useParams } from "react-router-dom";
import { getSlaughterHousesRequest } from "../../services/getSlaughterHousesRequest";
// import useUserProfile from "../../../authentication/hooks/useUserProfile";
// import { useParams } from "react-router-dom";
import { provinceGetAllRequests } from "../../../province/services/province-get-all-requests";
import { getFileFromApi } from "../../hooks/useRequestFile";
import useUserProfile from "../../../authentication/hooks/useUserProfile";
import { ProvinceEditKillCapacityForm } from "../../../province/components/province-edit-kill-capacity-form/ProvinceEditKillCapacityForm";
// import { getSlaughterHousesRequest } from "../../services/getSlaughterHousesRequest";
import VerifiedIcon from "@mui/icons-material/Verified";
const validationSchema = Yup.object().shape({
quantity: Yup.number()
.required("تعداد اجباری است.")
.positive("تعداد باید بالاتر از 0 باشد.")
.integer("تعداد باید عدد باشد."),
});
export function SlaghterHouseRequestAllocationItem({
slaughterHouseReq,
provinceCheckRequestKey,
poultryRequestId,
poultryRequestKey,
// handleFileQuantity,
handleAllEntredQauntity,
allEntredQauntity,
name,
file,
avgLast4KillhousesWeight,
defaultValueForAllocate,
updateTable,
}) {
const [openNotif, , selectedDate1] = useContext(AppContext);
const [roles] = useUserProfile();
// const { id } = useParams();
const dispatch = useDispatch();
const [checked, setChecked] = useState(false);
const handleCheckboxChange = (event) => {
setChecked(event.target.checked);
};
const formik = useFormik({
initialValues: {
quantity: slaughterHouseReq.remainQuantity,
},
validationSchema: validationSchema,
onSubmit: (values) => {
dispatch(LOADING_START());
dispatch(
provinceDoAllocation({
kill_request_key: slaughterHouseReq.key,
province_check_request_key: provinceCheckRequestKey,
quantity: values.quantity,
payment_type: "نقدی",
})
).then((r) => {
dispatch(LOADING_END());
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
setChecked(false);
// handleAllEntredQauntity(null);
getFileFromApi(roles, poultryRequestId, dispatch);
dispatch(provinceGetAllRequests(selectedDate1));
dispatch(getSlaughterHousesRequest({ key: poultryRequestKey }));
dispatch(getAllocationInformation({ key: poultryRequestKey }));
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
updateTable();
}
});
},
});
useEffect(() => {
formik.validateForm();
}, []);
useEffect(() => {
const num =
Number(defaultValueForAllocate) < 0 ? 0 : Number(defaultValueForAllocate);
formik.setFieldValue("quantity", num);
}, [defaultValueForAllocate]);
useEffect(() => {
if (checked) {
const num =
Number(formik.values.quantity) < 0 ? 0 : Number(formik.values.quantity);
handleAllEntredQauntity({
...allEntredQauntity,
[name]: num,
});
} else {
handleAllEntredQauntity({
...allEntredQauntity,
[name]: Number(0),
});
}
}, [formik.values.quantity, checked]);
const { poultryRequestIndexWeight } = useSelector((state) => state.fileSlice);
const avgPoultryRequestsWeight = poultryRequestIndexWeight?.ave;
const fileWeight = file?.poultry?.IndexWeight;
// let weightProirity;
if (
fileWeight > avgPoultryRequestsWeight &&
slaughterHouseReq.firstAverageWeight < avgLast4KillhousesWeight
) {
// weightType = "high";
// weightProirity = true;
} else if (
fileWeight < avgPoultryRequestsWeight &&
slaughterHouseReq.firstAverageWeight > avgLast4KillhousesWeight
) {
// weightType = "low";
// weightProirity = true;
} else {
// weightProirity = false;
}
const allocationBtnDisabled =
checked && formik.isValid && defaultValueForAllocate > 0;
const buyerNamePrefix = slaughterHouseReq?.killHouse?.killer
? "کشتارکن"
: "کشتارگاه";
return (
<TableRow>
<TableCell style={{ alignItems: "center", textAlign: "center" }}>
<Grid container direction="row" flexWrap="nowrap" alignItems="center">
<Checkbox
key={slaughterHouseReq?.killHouse?.name}
checked={checked}
onChange={handleCheckboxChange}
/>
{buyerNamePrefix + " " + slaughterHouseReq?.killHouse?.name}
{slaughterHouseReq?.priority && (
<Tooltip title={"پیشنهادی مرغدار"} placement="left-start">
<VerifiedIcon color="success" />
</Tooltip>
)}
</Grid>
</TableCell>
<TableCell style={{ alignItems: "center", textAlign: "center" }}>
{slaughterHouseReq?.killHouse?.killHouseOperator?.user?.fullname} (
{slaughterHouseReq?.killHouse?.killHouseOperator?.user?.mobile})
</TableCell>
<TableCell style={{ alignItems: "center", textAlign: "center" }}>
<DisabledWrap key={"vv"} checked={checked}>
{slaughterHouseReq.firstAverageWeight} کیلوگرم
</DisabledWrap>
</TableCell>
{/* <TableCell style={{ alignItems: "center", textAlign: "center" }}>
<DisabledWrap key={"vv"} checked={checked}>
{slaughterHouseReq.secondAverageWeight} کیلوگرم
</DisabledWrap>
</TableCell> */}
{/* <TableCell style={{ alignItems: "center", textAlign: "center" }}>
{weightProirity ? (
<Typography color={"green"}>دارد</Typography>
) : (
<Typography color={"red"}>ندارد</Typography>
)}
</TableCell>
<TableCell style={{ alignItems: "center", textAlign: "center" }}>
{slaughterHouseReq?.killHouse?.systemAddress?.city?.name ===
file?.poultry?.poultryCity ? (
<Typography color={"green"}>دارد</Typography>
) : (
<Typography color={"red"}>ندارد</Typography>
)}
</TableCell>
<TableCell style={{ alignItems: "center", textAlign: "center" }}>
{slaughterHouseReq.debt ? (
<Typography color={"green"}>دارد</Typography>
) : (
<Typography color={"red"}>ندارد</Typography>
)}
</TableCell>
<TableCell style={{ alignItems: "center", textAlign: "center" }}>
<Typography>
{slaughterHouseReq?.factorAmount?.toLocaleString() + " ﷼"}
</Typography>
</TableCell>
<TableCell style={{ alignItems: "center", textAlign: "center" }}>
<Typography>
{slaughterHouseReq?.factorDeposit?.toLocaleString() + " ﷼"}
</Typography>
</TableCell> */}
<TableCell style={{ alignItems: "center", textAlign: "center" }}>
<DisabledWrap key={"vv"} checked={checked}>
{slaughterHouseReq?.killCapacity}
<Button
aria-label="delete"
color="primary"
onClick={() => {
dispatch(
OPEN_MODAL({
title: "اضافه کردن به درخواست کشتارگاه",
content: (
<ProvinceEditKillCapacityForm
poultryRequestKey={poultryRequestKey}
killRequestKey={slaughterHouseReq?.key}
killCapacity={slaughterHouseReq.killCapacity}
updateTable={updateTable}
/>
),
})
);
}}
>
ویرایش
</Button>
</DisabledWrap>
</TableCell>
<TableCell style={{ alignItems: "center", textAlign: "center" }}>
<DisabledWrap key={"vv"} checked={checked}>
{slaughterHouseReq?.remainQuantity?.toLocaleString()}
</DisabledWrap>
</TableCell>
<TableCell style={{ alignItems: "center", textAlign: "center" }}>
<DisabledWrap key={"vv"} checked={checked}>
{slaughterHouseReq?.numberOfAllocated?.toLocaleString()}
</DisabledWrap>
</TableCell>
<TableCell style={{ alignItems: "center", textAlign: "center" }}>
<DisabledWrap key={"vv"} checked={checked}>
<Grid key={slaughterHouseReq?.killHouse?.name}>
<TextField
disabled={!checked}
label="حجم"
type="number"
style={{ width: "80%" }}
inputProps={{
min: 0,
step: 1,
}}
fullWidth
id="quantity"
value={formik.values.quantity}
onChange={formik.handleChange}
error={formik.touched.quantity && Boolean(formik.errors.quantity)}
helperText={formik.touched.quantity && formik.errors.quantity}
/>
</Grid>
</DisabledWrap>
</TableCell>
<TableCell style={{ alignItems: "center", textAlign: "center" }}>
<DisabledWrap key={"vv"} checked={checked}>
<Button
key={slaughterHouseReq?.killHouse?.name}
variant="contained"
type="submit"
color="primary"
disabled={!allocationBtnDisabled}
onClick={formik.handleSubmit}
>
تخصیص
</Button>
</DisabledWrap>
</TableCell>
</TableRow>
);
}
const DisabledWrap = ({ children, checked }) => {
return <Grid style={{ opacity: !checked ? 0.5 : 1 }}>{children}</Grid>;
};

View File

@@ -0,0 +1,24 @@
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import TimelineOppositeContent from "@mui/lab/TimelineOppositeContent";
import { Typography } from "@mui/material";
export const SlaghterAssignCarTitle = ({ file }) => {
return (
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
مرحله تخصیص و ثبت اطلاعات بار ماشین کشتارگاه
</Typography>
</TimelineOppositeContent>
</Grid>
</Grid>
</Grid>
);
};
SlaghterAssignCarTitle.propTypes = {
file: PropTypes.any,
};

View File

@@ -0,0 +1,762 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import {
Autocomplete,
Button,
FormControl,
FormHelperText,
InputLabel,
MenuItem,
Select,
TextField,
Typography,
} from "@mui/material";
import React, { useState } from "react";
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import { useSlaughterHouseCars } from "../../hooks/useSlaughterHouseCars";
import { SPACING } from "../../../../data/spacing";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import { useEffect } from "react";
// import { useAcceptedSlaughterRequest } from "../../hooks/useAcceptedSlaughterRequest";
import { useDispatch } from "react-redux";
import { postSlaughterCarAllocation } from "../../services/postSlaughterCarAllocation";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { getAllocationInformation } from "../../services/get-allocation-information";
import { getAcceptedSlaughterRequest } from "../../services/getAcceptedSlaughterRequest";
import { useParams } from "react-router-dom";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { slaughterGetActiveRequests } from "../../../slaughter-house/services/slaughter-get-active-requests";
import { slaughterGetAllocatedCarsService } from "../../../slaughter-house/services/slaughter-get-allocated-cars";
import { slaughterGetExlusiveKillers } from "../../services/slaughterGetExlusiveKillers";
import { provincePolicyGetMaximumBarQuantityStatus } from "../../../province/services/province-policy-get-maximum-bar-quantity";
const SlaughterAssignCar = ({
poultryRequestKey,
provinceAllocationLimit,
killRequestKey,
killHouseKey,
// killHouseName,
killHouseCheckKey,
indexWeight,
item,
}) => {
const file = {};
const [openNotif] = useContext(AppContext);
const slaughterHouseCars = useSlaughterHouseCars(
poultryRequestKey,
killHouseKey,
killRequestKey
);
const [, , selectedDate1, , selectedDate2] = useContext(AppContext);
const [maximumQuantity, setMaximumQuantity] = useState(false);
const fetchData = () => {
dispatch(provincePolicyGetMaximumBarQuantityStatus()).then((r) => {
setMaximumQuantity(r.payload.data);
});
};
useEffect(() => {
fetchData();
}, []);
const { id } = useParams();
const buttonText =
getRoleFromUrl() === "ProvinceOperator"
? "ثبت اطلاعات خودرو بجای کشتارگاه"
: "ثبت اطلاعات خودرو";
// const killHouseCheckKey = acceptedSlaughterRequests.filter(
// (item) => item.quantity > 0
// )[0]?.killHouseCheckKey;
// useEffect(() => {
// const d = acceptedSlaughterRequests?.reduce(
// (total, item) => (item.quantity > total ? item.quantity : total),
// 0
// );
// setLimit(d);
// }, [acceptedSlaughterRequests]);
const getMaxLimit = () => {
return maximumQuantity?.allow ? maximumQuantity?.limitation : 3100;
};
const dispatch = useDispatch();
const formik = useFormik({
initialValues: {
// selectedRequest: "",
quantity: "",
car: "",
realCar: "",
shippingCode: "",
},
validationSchema: Yup.object({
// selectedRequest: Yup.string().required("این فیلد اجباری است!"),
quantity: Yup.number("یک عدد وارد کنید")
.typeError("لطفا ظرفیت را به عدد وارد کنید!")
.required("این فیلد اجباری است!")
.min(1, "یک مقدار مجاز وارد کنید!")
.max(
getMaxLimit(),
`حداکثر میزان تخصیص به ماشین ${getMaxLimit()} قطعه میباشد`
),
shippingCode: Yup.string().required("این فیلد اجباری است!"),
// .test("len", "ظرفیت بیشتر از حد مجاز است!", (val, context) => {
// return context.originalValue && context.originalValue <= limit;
// }),
car: Yup.object().required("این فیلد اجباری است!"),
realCar: Yup.object(),
}),
});
useEffect(() => {
formik.validateForm();
}, []);
useEffect(() => {
if (file.killHouseWinner) {
formik.setFieldValue("selectedRequest", "not required");
}
}, []);
useEffect(() => {
if (file.killHouseWinner) {
formik.setFieldValue("selectedRequest", "not required");
}
}, []);
// const carsOptions = slaughterHouseCars?.map((car, i) => {
// let carType = "اختصاصی";
// if (car.type === "exclusive") {
// carType = "اختصاصی";
// } else if (car.type === "rental") {
// carType = "اجاره ای";
// }
// const carLbl = `${car.driverName} (${car.driverMobile}) ${car.typeCar} پلاک ${car.pelak} ظرفیت ${car.capocity} قطعه (${carType})`;
// // const carLbl = ` ${car.driverName} (${car.driverMobile}) ${car.typeCar} ${car.typeWeight} پلاک ${car.pelak} ظرفیت ${car.capocity} قطعه `;
// return (
// <MenuItem disabled={car.busy} key={i} value={car}>
// {carLbl}
// </MenuItem>
// );
// });
const [chooseRealCar] = useState(false);
// const handleChange = (event) => {
// setChooseRealCar(!chooseRealCar);
// };
const [exclusiveKillers, setExclusiveKillers] = useState();
const [selectedOption, setSelectedOption] = useState();
useEffect(() => {
if (item?.exclusiveKiller) {
dispatch(slaughterGetExlusiveKillers()).then((r) => {
setExclusiveKillers(r.payload.data);
});
}
}, []);
const handleOptionChange = (event) => {
setSelectedOption(event?.target.value);
};
const getFormValidation = () => {
if (exclusiveKillers && exclusiveKillers.length > 0) {
return selectedOption && formik.isValid;
} else {
return formik.isValid;
}
};
return (
<>
{/* {acceptedSlaughterRequests.some((item) => item.quantity > 0) && ( */}
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color="secondary" />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
انجام عملیات
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Typography variant="body2">
{/* ماشین های {killHouseName} خود را به تخصیص اختصاص دهید. */}
</Typography>
</TimelineContent>
</Grid>
</Grid>
<Grid container justifyContent={"space-between"}>
<Grid
container
alignItems="start"
direction="column"
gap={SPACING.SMALL}
mt={SPACING.SMALL}
>
<Grid container gap={SPACING.SMALL}>
{/* {!file.killHouseWinner && (
<Grid container>
<FormControl sx={{ minWidth: "400px" }}>
<InputLabel id="demo-simple-select-label">
درخواست های تخصیص داده شده شما
</InputLabel>
<Select
labelId="demo-simple-select-label"
id="selectedRequest"
label="درخواست های تخصیص داده شده شما"
value={formik.values.selectedRequest}
error={
formik.touched.selectedRequest
? Boolean(formik.errors.selectedRequest)
: null
}
onChange={(e) => {
formik.setFieldValue(
"selectedRequest",
e.target.value
);
}}
onBlur={formik.handleBlur}
>
{acceptedSlaughterRequests
.filter((item) => item.quantity > 0)
.map((item, i) => {
return (
<MenuItem
key={i}
value={
item.killHouseCheckKey + " " + item.quantity
}
>
بار با ظرفیت {item.quantity} در تاریخ{" "}
{format(new Date(item.date), "yyyy/MM/dd")}
</MenuItem>
);
})}
</Select>
<FormHelperText>
{formik.touched.race && Boolean(formik.errors.race)
? formik.errors.race
: null}
</FormHelperText>
</FormControl>
</Grid>
)} */}
<Grid xs={12}>
<Typography sx={{ fontSize: "12px" }} color="secondary">
خودرو دارای کد بهداشتی حمل
</Typography>
</Grid>
<Grid container direction="column" alignItems="start">
<FormControl sx={{ width: "300px" }}>
<Autocomplete
options={slaughterHouseCars || []}
getOptionLabel={(car) => {
if (car) {
const carType =
car.type === "exclusive" ? "اختصاصی" : "اجاره ای";
return `${car.driverName} (${car.driverMobile}) ${car.typeCar} پلاک ${car.pelak} (${carType})`;
}
return "";
}}
value={formik.values.car}
onChange={(e, car) => {
formik.setFieldValue("car", car);
formik.setFieldValue(
"shippingCode",
car ? car.healthCode : ""
);
}}
onBlur={formik.handleBlur}
renderInput={(params) => (
<TextField
{...params}
label="انتخاب خودرو و راننده"
error={
formik.touched.car
? Boolean(formik.errors.car)
: null
}
/>
)}
/>
<FormHelperText>
{formik.touched.car && Boolean(formik.errors.car)
? formik.errors.car
: null}
</FormHelperText>
</FormControl>
{/* <Grid container alignItems="center" xs={12} gap={0}>
<FormControlLabel
control={<Checkbox checked={chooseRealCar} />}
onChange={handleChange}
label="انتخاب خودرو واقعی برای حمل مرغ زنده (اختیاری)"
componentsProps={{
typography: {
sx: { fontSize: "12px", color: "red" },
},
}}
/>
</Grid> */}
{chooseRealCar && (
<FormControl sx={{ width: "300px" }}>
<Autocomplete
options={slaughterHouseCars || []}
getOptionLabel={(car) => {
if (car) {
const carType =
car.type === "exclusive" ? "اختصاصی" : "اجاره ای";
return `${car.driverName} (${car.driverMobile}) ${car.typeCar} پلاک ${car.pelak} ظرفیت ${car.capocity} قطعه (${carType})`;
}
return "";
}}
value={formik.values.realCar}
onChange={(e, car) => {
formik.setFieldValue("realCar", car);
}}
onBlur={formik.handleBlur}
renderInput={(params) => (
<TextField
{...params}
label="انتخاب خودرو و راننده"
error={
formik.touched.car
? Boolean(formik.errors.realCar)
: null
}
/>
)}
/>
<FormHelperText>
{formik.touched.realCar &&
Boolean(formik.errors.realCar)
? formik.errors.realCar
: null}
</FormHelperText>
</FormControl>
)}
{exclusiveKillers?.length > 0 && (
<>
<Grid xs={12}>
<Typography
sx={{ fontSize: "12px" }}
color="red"
mb={1}
mt={1}
>
انتخاب کشتارکن جهت تخصیص
</Typography>
</Grid>
<FormControl>
<InputLabel id="demo-simple-select-label">
انتخاب کشتارکن (اجباری)
</InputLabel>
<Select
label="کشتارکن"
// disabled={disableSelect}
// label="Select Option"
value={selectedOption}
onChange={handleOptionChange}
>
{exclusiveKillers?.map((item, i) => {
return (
<MenuItem key={i} value={item?.key}>
{item?.name}
</MenuItem>
);
})}
</Select>
</FormControl>
</>
)}
<Grid
container
textAlign="start"
direction="column"
mt={SPACING.TINY}
>
{slaughterHouseCars
.filter((item) => item.busy)
.map((car, i) => {
const carLbl = `راننده ${car.driverName} ${car.typeCar} با پلاک ${car.pelak} جهت حمل بار کشتارگاه دیگری رزرو شده است.`;
// const carLbl = ` ${car.driverName} (${car.driverMobile}) ${car.typeCar} ${car.typeWeight} پلاک ${car.pelak} ظرفیت ${car.capocity} قطعه `;
return (
<Grid key={"car" + i}>
<Typography variant="caption">{carLbl}</Typography>
</Grid>
);
})}
</Grid>
</Grid>
<Grid>
<TextField
allowLeadingZeros
thousandSeparator=","
id="shippingCode"
label="کد بهداشتی حمل و نقل"
value={formik.values.shippingCode}
error={
formik.touched.shippingCode
? Boolean(formik.errors.shippingCode)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.shippingCode &&
Boolean(formik.errors.shippingCode)
? formik.errors.shippingCode
: null
}
variant="outlined"
/>
</Grid>
<Grid>
<TextField
allowLeadingZeros
thousandSeparator=","
id="quantity"
label="ظرفیت (قطعه)"
value={formik.values.quantity}
error={
formik.touched.quantity
? Boolean(formik.errors.quantity)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.quantity && Boolean(formik.errors.quantity)
? formik.errors.quantity
: null
}
autoComplete="current-password"
variant="outlined"
/>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
ظرفیت مجاز ماشین:
</Typography>
<Typography variant={"button"}>
{getMaxLimit()} قطعه
</Typography>
</Grid>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
باقی مانده:
</Typography>
<Typography variant={"button"}>
{provinceAllocationLimit -
Number(formik.values.quantity) >=
0
? provinceAllocationLimit -
Number(formik.values.quantity)
: 0}{" "}
قطعه
</Typography>
</Grid>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
مازاد:
</Typography>
<Typography variant={"button"}>
{Number(formik.values.quantity) > provinceAllocationLimit
? Math.abs(
Number(formik.values.quantity) -
provinceAllocationLimit
)
: 0}{" "}
قطعه
</Typography>
</Grid>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
وزن تقریبی هرقطعه مرغ:
</Typography>
<Typography variant={"button"}>
{indexWeight.toLocaleString()} کیلوگرم
</Typography>
</Grid>
</Grid>
<Grid container alignItems="start" gap={SPACING.SMALL}>
<Grid
container
mt={SPACING.TINY}
gap={SPACING.TINY}
alignItems="center"
>
<Typography color={(prop) => prop.palette.grey["A700"]}>
=
</Typography>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
وزن تقریبی بار:
</Typography>
<Typography variant={"button"}>
{(
Number(formik.values.quantity) * indexWeight
).toLocaleString()}{" "}
کیلوگرم
</Typography>
</Grid>
</Grid>
</Grid>
<Grid container>
<Button
size={"large"}
variant={"contained"}
disabled={!getFormValidation()}
onClick={() => {
dispatch(LOADING_START());
let reqObj = {};
if (file.killHouseWinner) {
reqObj = {
winner_key: file.killHouseWinner.killHouseWinnerKey,
quantity: Number(formik.values.quantity),
killer_key: selectedOption ? selectedOption : null,
car: {
id: formik.values.car.id,
key: formik.values.car.key,
driver_name: formik.values.car.driverName,
driver_mobile: formik.values.car.driverMobile,
name: formik.values.car.name,
type_car: formik.values.car.typeCar,
type_weight: formik.values.car.typeWeight,
pelak: formik.values.car.pelak,
capocity: formik.values.car.capocity,
weight_without_load:
formik.values.car.weightWithoutLoad,
health_code: formik.values.car.helathCode,
},
};
} else {
reqObj = {
killer_key: selectedOption ? selectedOption : null,
kill_house_check_key: killHouseCheckKey,
quantity: Number(formik.values.quantity),
traffic_code: formik.values.shippingCode,
real_car_key: formik.values.realCar.key,
role: getRoleFromUrl(),
car: {
id: formik.values.car.id,
key: formik.values.car.key,
driver_name: formik.values.car.driverName,
driver_mobile: formik.values.car.driverMobile,
name: formik.values.car.name,
type_car: formik.values.car.typeCar,
type_weight: formik.values.car.typeWeight,
pelak: formik.values.car.pelak,
capocity: formik.values.car.capocity,
weight_without_load:
formik.values.car.weightWithoutLoad,
health_code: formik.values.car.helathCode,
},
};
}
dispatch(postSlaughterCarAllocation(reqObj)).then((r) => {
dispatch(LOADING_END());
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
dispatch(LOADING_END());
// getFileFromApi(roles, id, dispatch);
dispatch(
slaughterGetActiveRequests({
isCar: true,
selectedDate1,
selectedDate2,
})
);
dispatch(
slaughterGetAllocatedCarsService({
selectedDate1,
selectedDate2,
})
);
dispatch(getAcceptedSlaughterRequest({ id }));
dispatch(
getAllocationInformation({
key: poultryRequestKey,
})
);
dispatch(getAcceptedSlaughterRequest());
dispatch(
DRAWER({
right: false,
bottom: false,
top: false,
content: null,
})
);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
}}
>
{buttonText}
</Button>
</Grid>
{/* <Grid
container
direction={"column"}
alignItems={"start"}
gap={SPACING.SMALL}
>
<Grid>
<Typography
variant={"body1"}
fontWeight={"bold"}
color={"primary"}
>
ماشین های ثبت شده
</Typography>
</Grid>
<Grid>
{!file.killHouseWinner &&
acceptedSlaughterRequests?.map((item, i) => {
const head = `برای سفارش ${item.orderCode} با باقی مانده ظرفیت ${item.quantity} قطعه `;
const killHouseAssignments =
item.killHouseAssignments.map((assignment, index) => {
const barItem = `کدبار ${assignment.barcod} تعداد ${assignment.quantity} قطعه با ماشین ${assignment.cars.typeCar} راننده ${assignment.cars.driverName}`;
return (
<Grid key={i + index} textAlign={"start"}>
<Grid color={(prop) => prop.palette.grey["A700"]}>
<ListItem>
<ListItemIcon>
<CircleIcon />
</ListItemIcon>
<ListItemText primary={barItem} />
</ListItem>
</Grid>
</Grid>
);
});
return (
<Grid key={"acceptedSlaughterRequests" + i}>
<Grid container gap={SPACING.SMALL}>
<Typography variant={"body2"}>{head}</Typography>
</Grid>
<List>{killHouseAssignments}</List>
</Grid>
);
})}
{file.killHouseWinner &&
file.auction?.map((item, i) => {
const head = `برای سفارش ${item.orderCode} با باقی مانده ظرفیت ${file.killHouseWinner.quantity} قطعه `;
const barItem = `کدبار ${item.barcod} تعداد ${item.quantity} قطعه با ماشین ${item.cars.typeCar} راننده ${item.cars.driverName}`;
const returnItem = (
<Grid key={i + i} textAlign={"start"}>
<Grid color={(prop) => prop.palette.grey["A700"]}>
<ListItem>
<ListItemIcon>
<CircleIcon />
</ListItemIcon>
<ListItemText primary={barItem} />
</ListItem>
</Grid>
</Grid>
);
return (
<Grid key={"acceptedSlaughterRequests" + i}>
<Grid container gap={SPACING.SMALL}>
<Typography variant={"body2"}>{head}</Typography>
</Grid>
<List>{returnItem}</List>
</Grid>
);
})}
</Grid>
</Grid> */}
</Grid>
</Grid>
</Grid>
</TimelineItem>
{/* )} */}
</>
);
};
SlaughterAssignCar.propTypes = {
file: PropTypes.object,
provinceAllocationLimit: PropTypes.any,
};
export default SlaughterAssignCar;

View File

@@ -0,0 +1,93 @@
import {
TimelineConnector,
TimelineContent,
// TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Typography } from "@mui/material";
import React from "react";
// import { formatTime } from "../../../../utils/formatTime";
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import CheckRequestItem from "../check-request-item/CheckRequestItem";
import { SPACING } from "../../../../data/spacing";
const SlaughterCheckRequest = ({ item }) => {
// useEffect(() => {
// if (file.city !== null) {
// setIsSubmited(true);
// }
// }, []);
// const animationControl = useAnimation();
// useEffect(() => {
// ("eeeeeee", isDenyed);
// if (isDenyed) {
// animationControl.start({
// x: -10,
// display: "block",
// transition: { duration: 0.3 },
// });
// }
// }, [isDenyed]);
// const MotionInput = motion(TextField);
return (
<>
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color="secondary" />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
انجام عملیات
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Typography variant="body2">
در این مرحله تخصیص را تایید یا رد کنید.
</Typography>
</TimelineContent>
</Grid>
</Grid>
<Grid>
<Grid
container
direction="column"
alignItems="start"
mt={SPACING.TINY}
key={item.date.valueOf()}
>
<CheckRequestItem
key={item.provinceKillReqKey}
reqKey={item.provinceKillReqKey}
poultryRequestKey={item.poultryReqKey}
/>
</Grid>
</Grid>
</Grid>
</TimelineItem>
</>
);
};
SlaughterCheckRequest.propTypes = {
item: PropTypes.object,
i: PropTypes.any,
poultryRequestKey: PropTypes.any,
};
export default SlaughterCheckRequest;

View File

@@ -0,0 +1,513 @@
import { Grid } from "../../../../components/grid/Grid";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import {
Button,
FormControl,
InputLabel,
MenuItem,
Select,
Typography,
} from "@mui/material";
import React, { useEffect, useState } from "react";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import { PropTypes } from "prop-types";
import { SPACING } from "../../../../data/spacing";
import { ImageUpload } from "../../../../components/image-upload/ImageUpload";
import { fixBase64 } from "../../../../utils/toBase64";
import { useDispatch, useSelector } from "react-redux";
import { slaughterEnterBarWeight } from "../../../slaughter-house/services/slaughter-enter-bar-weight";
import { DRAWER } from "../../../../lib/redux/slices/appSlice";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { slaughterUpdateBarWeight } from "../../../slaughter-house/services/slaughter-update-bar-weight";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { NumberInput } from "../../../../components/number-format-custom/NumberFormatCustom";
import { resizeImage } from "../../../../utils/resizeImage";
import { slaughterGetExlusiveKillers } from "../../services/slaughterGetExlusiveKillers";
import { isValidIndexWeight } from "../../../../utils/isValidIndexWeight";
import { checkPathStartsWith } from "../../../../utils/checkPathStartsWith";
export const SlaughterEnterBarItem = ({
data,
reqKey,
// checkKey,
isRejected,
item,
realNumber,
updateTable,
}) => {
const [openNotif] = useContext(AppContext);
const [weightWithBarImages, setWeightWithBarImages] = React.useState([]);
const [weightWithBarImg, setWeightWithBarImg] = React.useState(null);
const { weightRange } = useSelector((state) => state.provinceSlice);
const selectedSubUser = useSelector(
(state) => state.userSlice.selectedSubUser
);
const weightWithBarImgHandler = (imageList) => {
setWeightWithBarImages(imageList);
formik.setFieldValue("weightWithBarImg", "");
setWeightWithBarImg(null);
if (imageList[0]) {
const file = imageList[0]?.file;
resizeImage(file, (resizedDataUrl) => {
const optimizedBase64 = fixBase64(resizedDataUrl);
setWeightWithBarImg(optimizedBase64);
formik.setFieldValue("weightWithBarImg", optimizedBase64);
});
} else {
formik.setFieldValue("weightWithBarImg", "");
}
};
const [barWeight, setBarWeight] = useState(0);
const dispatch = useDispatch();
let numFirstWeight = 0;
const formik = useFormik({
initialValues: {
weightWithoutBar: "",
weightWithBar: "",
weightWithBarImg: "",
loadRealNumber: item.acceptedRealQuantity
? item.acceptedRealQuantity
: realNumber,
exploitedCarcass: 0,
},
validationSchema: Yup.object({
weightWithoutBar: Yup.number()
// .test(
// "weightWithoutBar",
// "وزن بدون بار نباید بزرگتر از وزن با بار باشد!",
// (val, context) => {
// return (
// context.originalValue && context.originalValue < numLastWeight
// );
// }
// )
.min(0, "عدد منفی وارد نکنید!")
.required("این فیلد اجباری است!")
.typeError("لطفا عدد وارد کنید!"),
weightWithBar: Yup.number()
.test(
"len",
"وزن با بار باید بیشتر از وزن بدون بار باشد!",
(val, context) => {
return (
context.originalValue && context.originalValue > numFirstWeight
);
}
)
.required("این فیلد اجباری است!")
.typeError("لطفا وزن را وارد کنید!"),
weightWithBarImg: Yup.string().required("این فیلد اجباری است!"),
loadRealNumber: Yup.number()
.required("این فیلد اجباری است!")
.typeError("لطفا عدد وارد کنید!"),
exploitedCarcass: Yup.number()
.required("این فیلد اجباری است!")
.typeError("لطفا عدد وارد کنید!"),
}),
});
numFirstWeight = Number(formik.values.weightWithoutBar);
useEffect(() => {
formik.validateForm();
}, []);
useEffect(() => {
// fill the form if req is rejected
if (isRejected || item) {
formik.setFieldValue(
"weightWithoutBar",
item.assignmentInfo?.carWeightWithoutLoad
);
formik.setFieldValue(
"weightWithBar",
item.assignmentInfo?.carWeightWithLoad
);
}
}, []);
useEffect(() => {
const numFirstWeight = Number(formik.values.weightWithoutBar);
const numLastWeight = Number(formik.values.weightWithBar);
if (numLastWeight) {
if (numFirstWeight < numLastWeight) {
setBarWeight(numLastWeight - numFirstWeight);
} else {
setBarWeight(0);
}
}
}, [formik.values.weightWithoutBar, formik.values.weightWithBar]);
const [exclusiveKillers, setExclusiveKillers] = useState();
const [selectedOption, setSelectedOption] = useState();
useEffect(() => {
dispatch(
slaughterGetExlusiveKillers({
role_key: checkPathStartsWith("slaughter")
? selectedSubUser?.key || ""
: "",
})
).then((r) => {
setExclusiveKillers(r.payload.data);
});
}, [selectedSubUser?.key]);
const handleOptionChange = (event) => {
setSelectedOption(event?.target.value);
};
const buttonText =
getRoleFromUrl() !== "KillHouse"
? "ثبت اطلاعات بجای کشتارگاه"
: "ثبت اطلاعات";
return (
<Grid container direction={"column"}>
<Grid>
<SimpleTable
columns={[
"کدبار",
"مرغداری",
"تعداد تخصیصی (قطعه)",
"تعداد تحویلی (قطعه)",
"وزن تحویلی (کیلوگرم)",
"میانگین وزن تحویلی هر قطعه (کیلوگرم)",
"سن",
"تاریخ کشتار",
"کشتارکن اختصاصی",
]}
data={data}
/>
</Grid>
<Grid
container
direction={"column"}
alignItems={"start"}
my={SPACING.SMALL}
gap={SPACING.SMALL}
>
<Grid container gap={SPACING.TINY}>
<Typography variant={"body2"} color={"primary"} fontWeight={"bold"}>
اطلاعات بار با کدبار {data[0][0]} را وارد کنید.
</Typography>
{(isRejected || item.assignmentInfo) && (
<Typography variant={"body2"} color={"error"} fontWeight={"bold"}>
توجه: حتما باید اطلاعات جدید دوباره وارد گردد. (سند ماشین و وزن
ماشین)
</Typography>
)}
{isRejected && (
<>
<Typography variant={"body2"} color={"error"} fontWeight={"bold"}>
({"اطلاعات بار توسط واحد مالی استان رد شده است."})
</Typography>
{/* <Typography variant={"body2"} color={"error"} fontWeight={"bold"}>
دلیل رد: {item?.barInfo?.message}
</Typography> */}
</>
)}
</Grid>
<Grid container direction={"column"} gap={SPACING.SMALL}>
<Grid container gap={SPACING.SMALL} alignItems={"normal"}>
<Grid container direction={"column"}>
<NumberInput
allowLeadingZeros
thousandSeparator=","
id="weightWithoutBar"
label="وزن ماشین بدون بار باسکول شده"
variant="outlined"
value={formik.values.weightWithoutBar}
error={
formik.touched.weightWithoutBar
? Boolean(formik.errors.weightWithoutBar)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.weightWithoutBar &&
Boolean(formik.errors.weightWithoutBar)
? formik.errors.weightWithoutBar
: null
}
/>
<ImageUpload
onChange={weightWithBarImgHandler}
images={weightWithBarImages}
maxNumber={1}
title={"بارگذاری سند"}
/>
{item.assignmentInfo.imageWithBar && (
<Grid
container
direction="column"
alignItems="center"
mt={SPACING.SMALL}
>
<a href={item.assignmentInfo.imageWithBar}>
<img
src={item.assignmentInfo.imageWithBar}
width="100"
height={"100"}
alt="killHouseImageWithLoad"
/>
</a>
<Typography variant="caption">
سند ماشین با بار بارگذاری شده
</Typography>
</Grid>
)}
</Grid>
<Grid container direction={"column"}>
<NumberInput
allowLeadingZeros
thousandSeparator=","
id="weightWithBar"
label="وزن ماشین با بار باسکول شده"
variant="outlined"
value={formik.values.weightWithBar}
error={
formik.touched.weightWithBar
? Boolean(formik.errors.weightWithBar)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.weightWithBar &&
Boolean(formik.errors.weightWithBar)
? formik.errors.weightWithBar
: null
}
/>
</Grid>
<Grid container direction={"column"}>
<NumberInput
allowLeadingZeros
thousandSeparator=","
style={{ width: 130 }}
id="loadRealNumber"
label="تعداد واقعی بارگیری"
variant="outlined"
value={formik.values.loadRealNumber}
error={
formik.touched.loadRealNumber
? Boolean(formik.errors.loadRealNumber)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.loadRealNumber &&
Boolean(formik.errors.loadRealNumber)
? formik.errors.loadRealNumber
: null
}
/>
</Grid>
<Grid container direction={"column"}>
<NumberInput
disabled={true}
allowLeadingZeros
thousandSeparator=","
style={{ width: 150 }}
id="exploitedCarcass"
label="لاشه استحصالی"
variant="outlined"
value={formik.values.exploitedCarcass}
error={
formik.touched.exploitedCarcass
? Boolean(formik.errors.exploitedCarcass)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.exploitedCarcass &&
Boolean(formik.errors.exploitedCarcass)
? formik.errors.exploitedCarcass
: null
}
/>
</Grid>
<Grid container direction={"column"}>
<Typography
color={(prop) => prop.palette.grey["A700"]}
variant={"caption"}
>
وزن بار وارد شده
</Typography>
<Typography variant={"button"}>{barWeight} کیلوگرم </Typography>
</Grid>
{exclusiveKillers?.length > 1 && (
<Grid container direction={"column"} gap={1} alignItems="center">
<FormControl>
<InputLabel id="demo-simple-select-label">
انتخاب کشتارکن
</InputLabel>
<Select
label="کشتارکن"
// disabled={disableSelect}
// label="Select Option"
value={selectedOption}
onChange={handleOptionChange}
>
{exclusiveKillers?.map((item, i) => {
return (
<MenuItem key={i} value={item?.key}>
{item?.name}
</MenuItem>
);
})}
</Select>
</FormControl>
<Grid>
<Typography sx={{ fontSize: "12px" }} color="red">
ویرایش کشتارکن اختصاصی (اختیاری)
</Typography>
</Grid>
</Grid>
)}
<Grid container direction={"column"} alignItems="center">
<Button
variant={"contained"}
disabled={!formik.isValid}
onClick={() => {
const thenCallback = (r) => {
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
// reset form values
formik.setFieldValue("weightWithBar", "");
formik.setFieldValue("weightWithoutBar", "");
setWeightWithBarImg(null);
setWeightWithBarImages([]);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
dispatch(
DRAWER({
right: false,
top: false,
bottom: false,
content: null,
size: null,
})
);
updateTable(1);
}
};
if (
(item?.killhouseUser?.maximumLoadVolumeReduction !== 0 &&
formik.values.loadRealNumber <
item?.acceptedRealQuantity *
(1 -
item?.killhouseUser?.maximumLoadVolumeReduction /
100)) ||
(item?.killhouseUser?.maximumLoadVolumeIncrease !== 0 &&
formik.values.loadRealNumber >
item?.acceptedRealQuantity *
(1 +
item?.killhouseUser?.maximumLoadVolumeIncrease /
100))
) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "حجم وارد شده با مجوز حداکثر افزایش/کاهش ورود اطلاعات بار مطابقت ندارد!",
severity: "error",
});
} else if (
getRoleFromUrl() !== "SuperAdmin" &&
getRoleFromUrl() !== "AdminX" &&
!isValidIndexWeight(
weightRange,
item?.poultryRequest?.age,
parseInt(barWeight) /
parseInt(formik.values.loadRealNumber)
)
) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "میانگین وزنی با احراز سنی مطابقت ندارد. لطفا با اتحادیه تماس بگیرید.",
severity: "error",
});
} else if (
isRejected ||
item.assignmentInfo?.assignmentState === true
) {
const reqUpdate = {
car_weight_with_load: formik.values.weightWithBar,
car_weight_without_load: formik.values.weightWithoutBar,
car_with_load_image: weightWithBarImg,
key: item.assignmentInfo.assignmentKey,
real_quantity: formik.values.loadRealNumber,
exploited_carcass: formik.values.exploitedCarcass,
role: getRoleFromUrl(),
killer_key: selectedOption ? selectedOption : null,
};
dispatch(slaughterUpdateBarWeight(reqUpdate)).then(
thenCallback
);
} else {
const req = {
car_weight_with_load: formik.values.weightWithBar,
car_weight_without_load: formik.values.weightWithoutBar,
car_with_load_image: weightWithBarImg,
real_quantity: formik.values.loadRealNumber,
exploited_carcass: formik.values.exploitedCarcass,
kill_house_request_key: reqKey,
// kill_house_check_key: checkKey,
role: getRoleFromUrl(),
killer_key: selectedOption ? selectedOption : null,
};
if (!req.kill_house_check_key) {
delete req.kill_house_check_key;
}
dispatch(slaughterEnterBarWeight(req)).then(thenCallback);
}
}}
>
{buttonText}
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
);
};
SlaughterEnterBarItem.propTypes = {
data: PropTypes.array,
reqKey: PropTypes.string,
checkKey: PropTypes.string,
isRejected: PropTypes.bool,
item: PropTypes.any,
realNumber: PropTypes.any,
};

View File

@@ -0,0 +1,101 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Grid } from "../../../../components/grid/Grid";
import { Typography } from "@mui/material";
import React, { useEffect } from "react";
import { PropTypes } from "prop-types";
import TimelineItem from "@mui/lab/TimelineItem";
import { SlaughterEnterBarItem } from "../slaughter-enter-bar-item/SlaughterEnterBarItem";
import { format } from "date-fns-jalali";
import { provincePolicyGetWeightRange } from "../../../province/services/province-policy-get-weight-range";
import { useDispatch, useSelector } from "react-redux";
import { checkPathStartsWith } from "../../../../utils/checkPathStartsWith";
export const SlaughterEnterBarWeight = ({ item, updateTable }) => {
const dispatch = useDispatch();
const selectedSubUser = useSelector(
(state) => state.userSlice.selectedSubUser
);
const sum = item?.acceptedRealWeight / item?.acceptedRealQuantity;
const data = [
[
item.barCode,
`${item.poultryRequest?.poultry?.unitName} (${item.poultryRequest.poultry?.user?.mobile})`,
item.quantity.toLocaleString(),
item?.acceptedRealQuantity
? item?.acceptedRealQuantity?.toLocaleString()
: "وارد نشده",
item?.acceptedRealWeight
? item?.acceptedRealWeight?.toLocaleString()
: "وارد نشده",
sum ? sum.toFixed(2) : "وارد نشده",
item?.poultryRequest?.age,
format(new Date(item?.poultryRequest?.sendDate), "yyyy/MM/dd"),
item?.killer?.name,
],
];
useEffect(() => {
dispatch(
provincePolicyGetWeightRange({
role_key: checkPathStartsWith("slaughter")
? selectedSubUser?.key || ""
: "",
})
);
}, [selectedSubUser?.key]);
return (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color="secondary" />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
انجام عملیات
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Typography variant="body2">
در این مرحله اطلاعات مربوط به وزن و سند باسکول را وارد نمایید.
</Typography>
</TimelineContent>
</Grid>
</Grid>
<Grid container direction={"column"} justifyContent={"space-between"}>
<Grid>
<SlaughterEnterBarItem
data={data}
realNumber={item.quantity}
reqKey={item.key}
isRejected={
item?.assignmentInfo
? item?.assignmentInfo.state === "rejected"
: null
}
item={item}
updateTable={updateTable}
/>
</Grid>
</Grid>
</Grid>
</TimelineItem>
);
};
SlaughterEnterBarWeight.propTypes = {
file: PropTypes.object,
};

View File

@@ -0,0 +1,40 @@
import {
Button,
FormControl,
InputLabel,
MenuItem,
Select,
} from "@mui/material";
import { useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
export const SlaughterHouseVetCancelBar = () => {
const [selectedOption, setSelectedOption] = useState(null);
const handleSelectChange = (event) => {
setSelectedOption(event.target.value);
};
return (
<Grid container gap={SPACING.TINY} style={{ width: "100%" }}>
<FormControl>
<InputLabel id="my-select-label">دلیل لغو بار</InputLabel>
<Select
value={selectedOption}
onChange={handleSelectChange}
label="دلیل لغو بار"
>
<MenuItem value="عدم ارسال راننده توسط کشتارگاه">
عدم ارسال راننده توسط کشتارگاه
</MenuItem>
<MenuItem value="عدم تحویل بار توسط مرغدار">
عدم تحویل بار توسط مرغدار
</MenuItem>
</Select>
</FormControl>
<Button variant="contained" fullWidth onClick={() => {}}>
ثبت
</Button>
</Grid>
);
};

View File

@@ -0,0 +1,181 @@
import { Button, TextField, Typography } from "@mui/material";
import React, { useState } from "react";
import { SPACING } from "../../../../data/spacing";
import { AnimatePresence } from "framer-motion";
import {
DRAWER,
LOADING_END,
LOADING_START,
OPEN_MODAL,
} from "../../../../lib/redux/slices/appSlice";
import { useDispatch } from "react-redux";
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { slaughterHouseVetSendCheckRequest } from "../../services/slaughter-house-vet-send-check-request";
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { slaughterHouseVetNewRequests } from "../../../slaughter-house-vet/services/slaughter-house-vet-new-requests";
// import { SlaughterHouseVetCancelBar } from "../slaughter-house-vet-cancel-bar/SlaughterHouseVetCancelBar";
import { VetFarmCancelBar } from "../../../vet-farm/components/vet-farm-cancel-bar/VetFarmCancelBar";
export default function SlaughterHouseVetCheckRequest({ item }) {
const dispatch = useDispatch();
const [openNotif, , selectedDate1, , selectedDate2] = useContext(AppContext);
const [value, setValue] = useState(item.quantity);
const [realWeight, setRealWeight] = useState();
const handleInputChange = (event) => {
setValue(event.target.value);
};
const handleInputChangeRealWeight = (event) => {
setRealWeight(event.target.value);
};
return (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color={"secondary"} />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container alignItems="center">
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
// color="secondary"
color={"secondary"}
>
انجام عملیات
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Typography variant="body2">
در این مرحله درخواست را بررسی و تایید کنید.
</Typography>
</TimelineContent>
</Grid>
</Grid>
<Grid container gap={SPACING.SMALL}>
<AnimatePresence>
<Grid
container
gap={SPACING.SMALL}
mt={SPACING.SMALL}
mx={SPACING.SMALL}
>
<Grid>
<TextField
label="تعداد واقعی تحویلی"
variant="outlined"
type={"number"}
value={value}
onChange={handleInputChange}
/>
</Grid>
<Grid>
<TextField
label="وزن واقعی بار"
variant="outlined"
type={"number"}
value={realWeight}
onChange={handleInputChangeRealWeight}
/>
</Grid>
<Button
variant="contained"
// disabled={!value || !realWeight}
onClick={() => {
dispatch(LOADING_START());
dispatch(
slaughterHouseVetSendCheckRequest({
kill_house_request_key: item.killHouseRequestKey,
state: "accepted",
accepted_real_quantity: !Number(realWeight)
? 0
: Number(value)
? Number(value)
: 0,
accepted_real_weight: !Number(value)
? 0
: Number(realWeight)
? Number(realWeight)
: 0,
})
).then((r) => {
dispatch(LOADING_END());
if (r.payload.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: r.payload.error,
severity: "error",
});
} else {
dispatch(
slaughterHouseVetNewRequests({
selectedDate1,
selectedDate2,
})
);
dispatch(
DRAWER({
right: false,
bottom: false,
top: false,
content: null,
size: null,
})
);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
});
}}
>
تحویل بار
</Button>
<Button
variant="contained"
color="error"
onClick={() => {
dispatch(
OPEN_MODAL({
title: "عملیات لغو بار",
content: (
<VetFarmCancelBar
killHouseRequestKey={item.killHouseRequestKey}
/>
),
})
);
}}
>
عدم وصول
</Button>
</Grid>
</AnimatePresence>
</Grid>
</Grid>
</TimelineItem>
);
}
SlaughterHouseVetCheckRequest.propTypes = {
file: PropTypes.any,
};

View File

@@ -0,0 +1,36 @@
import { Button, InputAdornment } from "@mui/material";
import { Grid } from "../../../../components/grid/Grid";
import { useState } from "react";
import { SPACING } from "../../../../data/spacing";
import { NumberInput } from "../../../../components/number-format-custom/NumberFormatCustom";
export const SlaughterPayFactorBankGateway = ({
provinceFactorToKillHouse,
price,
isRejected,
barCode,
killHouseFactorToProvince,
}) => {
const [inputValue, setInputValue] = useState("");
return (
<Grid container gap={SPACING.SMALL} mt={SPACING.SMALL} alignItems="center">
<Grid>
<NumberInput
allowLeadingZeros
thousandSeparator=","
id="outlined-basic"
label="مبلغ برای پرداخت را وارد کنید"
variant="outlined"
InputProps={{
endAdornment: <InputAdornment position="end">ریال</InputAdornment>,
}}
value={inputValue}
onChange={(event) => setInputValue(event.target.value)}
/>
</Grid>
<Grid>
<Button variant="contained">ارسال به درگاه پرداخت</Button>
</Grid>
</Grid>
);
};

View File

@@ -0,0 +1,279 @@
import {
Button,
IconButton,
InputAdornment,
TextField,
Typography,
} from "@mui/material";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { BankAccountInformation } from "../bank-account-information/BankAccountInformation";
import ImgUploader from "../../../../components/img-uploader/ImgUploader";
import { slaughterGetPayFactorRequestsService } from "../../../slaughter-house/services/slaughter-get-pay-factor-requests";
import {
DRAWER,
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { slaughterGetPaiedFactorsService } from "../../../slaughter-house/services/slaughter-get-paied-factors";
import { slaughterUpdatePayProvinceFactor } from "../../services/slaughterUpdatePayProvinceFactor";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { slaughterPayProvinceFactor } from "../../services/slaughterPayProvinceFactor";
import { useDispatch } from "react-redux";
import { useContext, useState } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import AddIcon from "@mui/icons-material/Add";
import DeleteIcon from "@mui/icons-material/Delete";
import { NumberInput } from "../../../../components/number-format-custom/NumberFormatCustom";
export const SlaughterPayFactorManual = ({
provinceFactorToKillHouse,
price,
isRejected,
barCode,
killHouseFactorToProvince,
}) => {
const dispatch = useDispatch();
const [, , selectedDate1, , selectedDate2] = useContext(AppContext);
const [openNotif] = useContext(AppContext);
const [inputValues, setInputValues] = useState([
{ id: 11, paymentId: "", doc: "", amount: "" },
{ id: 22, paymentId: "", doc: "", amount: "" },
]);
const totalAmount = inputValues.reduce(
(acc, item) => acc + Number(item.amount),
0
);
return (
<Grid container>
<Grid container alignItems={"start"}>
<Grid>
<BankAccountInformation
card={provinceFactorToKillHouse?.card}
shaba={provinceFactorToKillHouse?.shaba}
info={provinceFactorToKillHouse?.nameOfBankUser}
price={price}
priceText={provinceFactorToKillHouse?.totalAmountChar}
bankName={provinceFactorToKillHouse?.bankName}
bankUser={provinceFactorToKillHouse?.nameOfBankUser}
/>
</Grid>
<Grid
container
direction="column"
gap={SPACING.SMALL}
mt={SPACING.SMALL}
pl={SPACING.SMALL}
>
<Grid>
<Grid container gap={SPACING.MEDIUM}>
<Grid>
<Typography variant={"body2"} color="primary">
مبلغ قابل پرداخت
</Typography>
<Typography variant={"body2"} color="error" fontWeight={"bold"}>
{totalAmount
? (Number(price) - totalAmount)?.toLocaleString()
: Number(price)?.toLocaleString()}{" "}
ریال
</Typography>
</Grid>
<Grid>
<Typography variant={"body2"} color="primary">
شناسه پرداخت
</Typography>
<Typography variant={"body2"} color="error" fontWeight={"bold"}>
{barCode}
</Typography>
</Grid>
</Grid>
<Grid>
<Typography variant={"body1"} fontWeight={"bold"}>
{/* {info} */}
</Typography>
</Grid>
</Grid>
<Grid
container
direction="column"
alignItems="center"
gap={SPACING.SMALL}
>
{inputValues
.sort((a, b) => a.id - b.id)
.map((item, i) => {
return (
<Grid
key={i}
container
alignItems="center"
gap={SPACING.SMALL}
>
<Typography>{i + 1}.</Typography>
<Grid>
<NumberInput
allowLeadingZeros
thousandSeparator=","
InputProps={{
endAdornment: (
<InputAdornment position="end">ریال</InputAdornment>
),
}}
label="مبلغ پرداخت شده"
value={item.amount}
onChange={(e) => {
setInputValues((prevState) => {
const idToRemove = item.id;
const filteredArray = prevState.filter(
(obj) => obj.id !== idToRemove
);
return [
...filteredArray,
{
...item,
id: item.id,
amount: e.target.value,
},
];
});
}}
/>
</Grid>
<Grid>
<TextField
label="شناسه واریز"
value={item.paymentId}
onChange={(e) => {
setInputValues((prevState) => {
const idToRemove = item.id;
const filteredArray = prevState.filter(
(obj) => obj.id !== idToRemove
);
return [
...filteredArray,
{
...item,
id: item.id,
paymentId: e.target.value,
},
];
});
}}
/>
</Grid>
<Grid>
<ImgUploader />
</Grid>
<Grid>
<IconButton
aria-label="delete"
color="error"
onClick={() => {
setInputValues((prevState) => {
const idToRemove = item.id;
const filteredArray = prevState.filter(
(obj) => obj.id !== idToRemove
);
return filteredArray;
});
}}
>
<DeleteIcon />
</IconButton>
</Grid>
</Grid>
);
})}
<Button
color="primary"
aria-label="Add"
onClick={() => {
setInputValues((prevState) => [
...prevState,
{ id: Date.now() },
]);
}}
>
<AddIcon />
افزودن سند
</Button>
<Grid>
<Button
variant={"contained"}
onClick={() => {
dispatch(LOADING_START());
const reqCallback = (r) => {
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
dispatch(
slaughterGetPayFactorRequestsService({
selectedDate1,
selectedDate2,
})
);
dispatch(
slaughterGetPaiedFactorsService({
selectedDate1,
selectedDate2,
})
);
dispatch(
DRAWER({
right: false,
bottom: false,
top: false,
content: null,
size: null,
})
);
// getFileFromApi(roles, id, dispatch);
// setFactorPaymentImages([]);
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
dispatch(LOADING_END());
};
if (isRejected) {
const req = {
// key: killHouseFactorToProvince.factorKey,
// factor_image: factorPaymentImg,
// payment_code: formik.values.paymentId,
role: getRoleFromUrl(),
};
dispatch(slaughterUpdatePayProvinceFactor(req)).then(
reqCallback
);
} else {
const req = {
// key: factorKey,
// factor_image: factorPaymentImg,
// payment_code: formik.values.paymentId,
role: getRoleFromUrl(),
};
dispatch(slaughterPayProvinceFactor(req)).then(reqCallback);
}
}}
>
ثبت
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
);
};

View File

@@ -0,0 +1,226 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Button, TextField, Typography } from "@mui/material";
import { useEffect, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { BankAccountInformation } from "../bank-account-information/BankAccountInformation";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
import { ImageUpload } from "../../../../components/image-upload/ImageUpload";
import { fixBase64 } from "../../../../utils/toBase64";
import { useDispatch } from "react-redux";
import { PropTypes } from "prop-types";
import {
LOADING_END,
LOADING_START,
} from "../../../../lib/redux/slices/appSlice";
import { getFileFromApi } from "../../hooks/useRequestFile";
import useUserProfile from "../../../authentication/hooks/useUserProfile";
import { useParams } from "react-router-dom";
import { useContext } from "react";
import { AppContext } from "../../../../contexts/AppContext";
import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
import { slaughterUpdatePayPoultryFactor } from "../../services/slaughterUpdatePayPoultryFactor";
import { slaughterPayPoultryFactor } from "../../services/slaughterPayPoultryFactor";
export const SlaughterPayPoultryFactorForm = ({
factorKey,
price,
provinceFactorToPoultry,
killHouseFactorToPoultry,
isRejected,
}) => {
const [openNotif] = useContext(AppContext);
const [factorPaymentImages, setFactorPaymentImages] = useState([]);
const [factorPaymentImg, setFactorPaymentImg] = useState();
const dispatch = useDispatch();
const [roles] = useUserProfile();
const { id } = useParams();
const formik = useFormik({
initialValues: {
paymentId: "",
factorPaymentImg: "",
},
validationSchema: Yup.object({
paymentId: Yup.number()
.required("این فیلد اجباری است!")
.typeError("لطفا عدد وارد کنید!"),
factorPaymentImg: Yup.string().required("این فیلد اجباری است!"),
}),
});
const factorPaymentHandler = (imageList, addUpdateIndex) => {
if (imageList[0]) {
setFactorPaymentImg(fixBase64(imageList[0]?.data_url));
formik.setFieldValue(
"factorPaymentImg",
fixBase64(imageList[0]?.data_url)
);
} else {
formik.setFieldValue("factorPaymentImg", "");
}
setFactorPaymentImages(imageList);
};
useEffect(() => {
formik.validateForm();
}, []);
useEffect(() => {
// fill the form if req is rejected
if (isRejected) {
formik.setFieldValue("paymentId", killHouseFactorToPoultry.paymentCode);
}
}, []);
return (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color="secondary" />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
انجام عملیات - پرداخت به مرغدار
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Grid container gap={SPACING.SMALL}>
<Typography variant="body2" display="flex" gap={SPACING.SMALL}>
در این مرحله مبلغ را پرداخت کنید و شناسه پرداخت را وارد و سند
آن را بارگذاری کنید.
</Typography>
</Grid>
</TimelineContent>
</Grid>
</Grid>
<Grid container>
<Grid xs={12} alignItems={"start"}>
<Grid>
<BankAccountInformation
card={provinceFactorToPoultry?.card}
shaba={provinceFactorToPoultry?.shaba}
info={provinceFactorToPoultry?.nameOfBankUser}
price={price}
priceText={provinceFactorToPoultry?.totalAmountChar}
/>
</Grid>
<Grid
container
alignItems={"center"}
gap={SPACING.SMALL}
mt={SPACING.SMALL}
pl={SPACING.SMALL}
>
<Grid>
<TextField
id="paymentId"
label="شناسه پرداخت"
variant="outlined"
value={formik.values.paymentId}
error={
formik.touched.paymentId
? Boolean(formik.errors.paymentId)
: null
}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={
formik.touched.paymentId && Boolean(formik.errors.paymentId)
? formik.errors.paymentId
: null
}
/>
</Grid>
<Grid>
<ImageUpload
onChange={factorPaymentHandler}
images={factorPaymentImages}
maxNumber={1}
title={"بارگذاری سند"}
/>
</Grid>
<Grid>
<Button
disabled={!formik.isValid}
variant={"contained"}
onClick={() => {
dispatch(LOADING_START());
const reqCallback = (r) => {
if (r.error) {
openNotif({
vertical: "top",
horizontal: "center",
msg: "مشکلی پیش آمده است!",
severity: "error",
});
} else {
getFileFromApi(roles, id, dispatch);
setFactorPaymentImages([]);
formik.setFieldValue("paymentId", "");
openNotif({
vertical: "top",
horizontal: "center",
msg: "عملیات با موفقیت انجام شد.",
severity: "success",
});
}
dispatch(LOADING_END());
};
if (isRejected) {
const req = {
key: killHouseFactorToPoultry.factorKey,
factor_image: factorPaymentImg,
payment_code: formik.values.paymentId,
role: getRoleFromUrl(),
};
dispatch(slaughterUpdatePayPoultryFactor(req)).then(
reqCallback
);
} else {
const req = {
key: factorKey,
factor_image: factorPaymentImg,
payment_code: formik.values.paymentId,
role: getRoleFromUrl(),
};
dispatch(slaughterPayPoultryFactor(req)).then(
reqCallback
);
}
}}
>
ثبت
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
</TimelineItem>
);
};
SlaughterPayPoultryFactorForm.propTypes = {
factorKey: PropTypes.string,
price: PropTypes.any,
provinceFactorToPoultry: PropTypes.any,
killHouseFactorToPoultry: PropTypes.any,
isRejected: PropTypes.any,
};

View File

@@ -0,0 +1,166 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { FormControlLabel, Radio, RadioGroup, Typography } from "@mui/material";
import React, { useEffect, useState } from "react";
import { Grid } from "../../../../components/grid/Grid";
import { SPACING } from "../../../../data/spacing";
import { useFormik } from "formik";
import { Yup } from "../../../../lib/yup/yup";
// import { ImageUpload } from "../../../../components/image-upload/ImageUpload";
// import { fixBase64 } from "../../../../utils/toBase64";
import { PropTypes } from "prop-types";
// import { slaughterPayProvinceFactor } from "../../services/slaughterPayProvinceFactor";
// import { useContext } from "react";
// import { AppContext } from "../../../../contexts/AppContext";
// import { slaughterUpdatePayProvinceFactor } from "../../services/slaughterUpdatePayProvinceFactor";
// import { getRoleFromUrl } from "../../../../utils/getRoleFromUrl";
// import { slaughterGetPayFactorRequestsService } from "../../../slaughter-house/services/slaughter-get-pay-factor-requests";
// import { slaughterGetPaiedFactorsService } from "../../../slaughter-house/services/slaughter-get-paied-factors";
// import ImgUploader from "../../../../components/img-uploader/ImgUploader";
import { SlaughterPayFactorManual } from "../slaughter-pay-factor-manual/SlaughterPayFactorManual";
import { SlaughterPayFactorBankGateway } from "../slaughter-pay-factor-bank-gateway/SlaughterPayFactorBankGateway";
export const SlaughterPayProvinceFactorForm = ({
factorKey,
price,
provinceFactorToKillHouse,
killHouseFactorToProvince,
isRejected,
barCode,
item,
}) => {
// const [factorPaymentImages, setFactorPaymentImages] = React.useState([]);
// const [factorPaymentImg, setFactorPaymentImg] = React.useState();
// const dispatch = useDispatch();
// const [roles] = useUserProfile();
// const { id } = useParams();
const formik = useFormik({
initialValues: {
paymentId: "",
// factorPaymentImg: "",
},
validationSchema: Yup.object({
paymentId: Yup.number()
.required("این فیلد اجباری است!")
.typeError("لطفا عدد وارد کنید!"),
// factorPaymentImg: Yup.string().required("این فیلد اجباری است!"),
}),
});
// const factorPaymentHandler = (imageList, addUpdateIndex) => {
// if (imageList[0]) {
// setFactorPaymentImg(fixBase64(imageList[0]?.data_url));
// formik.setFieldValue(
// "factorPaymentImg",
// fixBase64(imageList[0]?.data_url)
// );
// } else {
// formik.setFieldValue("factorPaymentImg", "");
// }
// setFactorPaymentImages(imageList);
// };
useEffect(() => {
formik.validateForm();
}, []);
useEffect(() => {
// fill the form if req is rejected
if (isRejected) {
formik.setFieldValue("paymentId", killHouseFactorToProvince.paymentCode);
}
}, []);
let paymentTo = "";
if (item?.factorPersonType === "union") {
paymentTo = "اتحادیه";
} else {
paymentTo = "مرغدار";
}
const [selectedOption, setSelectedOption] = useState("option1");
const handleChange = (event) => {
setSelectedOption(event.target.value);
};
return (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot color="secondary" />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent
variant="body1"
fontWeight="bold"
color="secondary"
>
انجام عملیات - پرداخت به {paymentTo}
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Grid container gap={SPACING.SMALL}>
<Typography variant="body2" display="flex" gap={SPACING.SMALL}>
در این مرحله مبلغ را پرداخت کنید و شناسه پرداخت را وارد و سند
آن را بارگذاری کنید.
</Typography>
</Grid>
</TimelineContent>
</Grid>
</Grid>
<Grid>
<RadioGroup
aria-labelledby="radio-group-label"
name="radio-buttons-group"
value={selectedOption}
onChange={handleChange}
>
<FormControlLabel
value="bank-gateway"
control={<Radio />}
label="پرداخت از طریق درگاه پرداخت"
/>
<FormControlLabel
value="manual-payment"
control={<Radio />}
label="ثبت سند پرداخت"
/>
</RadioGroup>
</Grid>
<Grid>
{selectedOption === "bank-gateway" && (
<SlaughterPayFactorBankGateway />
)}
{selectedOption === "manual-payment" && (
<SlaughterPayFactorManual
price={price}
provinceFactorToKillHouse={provinceFactorToKillHouse}
barCode={barCode}
isRejected={isRejected}
killHouseFactorToProvince={killHouseFactorToProvince}
/>
)}
</Grid>
</Grid>
</TimelineItem>
);
};
SlaughterPayProvinceFactorForm.propTypes = {
factorKey: PropTypes.string,
price: PropTypes.any,
provinceFactorToKillHouse: PropTypes.any,
killHouseFactorToProvince: PropTypes.any,
isRejected: PropTypes.any,
};

View File

@@ -0,0 +1,68 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Typography } from "@mui/material";
import React from "react";
// import { formatTime } from "../../../../utils/formatTime";
import { PropTypes } from "prop-types";
import { Grid } from "../../../../components/grid/Grid";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { SPACING } from "../../../../data/spacing";
const SlaughterPayProvinceFactor = ({ file }) => {
return (
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
مرحله صدور فاکتور توسط استان
</Typography>
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Grid container gap={SPACING.SMALL}>
<Typography variant="body2" display="flex" gap={SPACING.SMALL}>
در این مرحله اطلاعات مربوط به فاکتور های صادر شده توسط استان
را مشاهده می کنید.
</Typography>
</Grid>
</TimelineContent>
</Grid>
</Grid>
<Grid container>
<Grid xs={12}>
<SimpleTable
columns={[
"کدبار",
"وزن ماشین بدون بار",
"وزن ماشین با بار",
"وزن بار",
]}
data={[
["1000020 کد", "2000 کیلوگرم", "3200 کیلوگرم", "1000 کیلوگرم"],
]}
/>
</Grid>
</Grid>
</Grid>
</TimelineItem>
);
};
SlaughterPayProvinceFactor.propTypes = {
file: PropTypes.object,
};
export default SlaughterPayProvinceFactor;

View File

@@ -0,0 +1,98 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Typography } from "@mui/material";
import React from "react";
import { Grid } from "../../../../components/grid/Grid";
import { PropTypes } from "prop-types";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { SPACING } from "../../../../data/spacing";
import { formatTime } from "../../../../utils/formatTime";
export const SlaughterPaymentFactorPoultry = ({ data, barCode }) => {
return (
<>
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
اطلاعات پرداختی کشتارگاه به مرغدار
</Typography>
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Grid container gap={SPACING.SMALL}>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
اطلاعات پرداختی کشتارگاه در این قسمت نمایش داده میشود.
</Typography>
</Grid>
</TimelineContent>
</Grid>
</Grid>
<Grid container>
<Grid xs={12}>
<SimpleTable
columns={[
"کد بار",
"کشتارگاه",
"تاریخ ثبت شناسه",
"شناسه پرداخت",
"مبلغ",
"وضعیت",
"پیوست",
]}
data={[
[
barCode,
`${data?.killHouseName} (${data?.killHouseUserProvince}/${data?.killHouseUserCity})`,
formatTime(data?.time),
Number(data?.paymentCode),
`${data.totalMoney}`,
data.factorState === "accepted"
? "تایید شده"
: data.factorState === "pending"
? "در انتظار تایید"
: "رد شده",
<a
key={`SlaughterPaymentFactorImage`}
href={data?.factorImage}
>
<img
src={data?.factorImage}
alt="Slaughter Payment Factor"
width="50"
height="50"
className="images-file"
/>
</a>,
],
]}
/>
</Grid>
</Grid>
</Grid>
</TimelineItem>
</>
);
};
SlaughterPaymentFactorPoultry.propTypes = {
data: PropTypes.any,
barCode: PropTypes.any,
};

View File

@@ -0,0 +1,99 @@
import {
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineOppositeContent,
TimelineSeparator,
} from "@mui/lab";
import { Typography } from "@mui/material";
import React from "react";
import { Grid } from "../../../../components/grid/Grid";
import { PropTypes } from "prop-types";
import { SimpleTable } from "../../../../components/simple-table/SimpleTable";
import { SPACING } from "../../../../data/spacing";
import { formatTime } from "../../../../utils/formatTime";
const SlaughterPaymentFactor = ({ data, barCode }) => {
return (
<>
<TimelineItem sx={{ alignSelf: "flex-start", width: "100%" }}>
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<Grid container direction="column" flexWrap="nowrap" flex="1">
<Grid container>
<Grid>
<TimelineOppositeContent>
<Typography variant="body1" fontWeight="bold">
اطلاعات پرداختی کشتارگاه
</Typography>
</TimelineOppositeContent>
</Grid>
<Grid>
<TimelineContent color="textSecondary">
<Grid container gap={SPACING.SMALL}>
<Typography
variant="body2"
display="flex"
gap={SPACING.SMALL}
>
اطلاعات پرداختی کشتارگاه در این قسمت نمایش داده میشود.
</Typography>
</Grid>
</TimelineContent>
</Grid>
</Grid>
<Grid container>
<Grid xs={12}>
<SimpleTable
columns={[
"کد بار",
"کشتارگاه",
"تاریخ ثبت شناسه",
"شناسه پرداخت",
"مبلغ",
"وضعیت",
"پیوست",
]}
data={[
[
barCode,
`${data?.killHouseName} (${data?.killHouseUserProvince}/${data?.killHouseUserCity})`,
formatTime(data.time),
Number(data.paymentCode),
`${data.totalMoney}`,
data.factorState === "accepted"
? "تایید شده"
: data.factorState === "pending"
? "در انتظار تایید"
: "رد شده",
<a
key={`SlaughterPaymentFactorImage`}
href={data.factorImage}
>
<img
src={data.factorImage}
alt="Slaughter Payment Factor"
width="50"
height="50"
className="images-file"
/>
</a>,
],
]}
/>
</Grid>
</Grid>
</Grid>
</TimelineItem>
</>
);
};
SlaughterPaymentFactor.propTypes = {
data: PropTypes.any,
barCode: PropTypes.any,
};
export default SlaughterPaymentFactor;

View File

@@ -0,0 +1,23 @@
import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getAcceptedSlaughterRequest } from "../services/getAcceptedSlaughterRequest";
export const useAcceptedSlaughterRequest = (id) => {
const dispatch = useDispatch();
const { acceptedSlaughterRequest } = useSelector((state) => state.fileSlice);
const [data, setData] = useState(acceptedSlaughterRequest);
useEffect(() => {
dispatch(getAcceptedSlaughterRequest({ id }));
}, []);
useEffect(() => {
setData(
acceptedSlaughterRequest?.filter(
(item) => item.quantity > 0 && item.provinceKillState === "accepted"
)
);
}, [acceptedSlaughterRequest]);
return data ? data : [];
};

View File

@@ -0,0 +1,23 @@
import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getAllocationInformation } from "../services/get-allocation-information";
const useGetAllocationInformation = (id) => {
const dispatch = useDispatch();
const { allocationInformation } = useSelector((state) => state.fileSlice);
const [data, setData] = useState(allocationInformation);
useEffect(() => {
if (id) {
dispatch(getAllocationInformation({ key: id }));
}
}, [id]);
useEffect(() => {
setData(allocationInformation);
}, [allocationInformation]);
return data ? data : [];
};
export default useGetAllocationInformation;

View File

@@ -0,0 +1,55 @@
import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
getFileProcess,
getFileProcessOther,
} from "../services/getFileProcess";
import useUserProfile from "../../authentication/hooks/useUserProfile";
import { getRoleFromUrl } from "../../../utils/getRoleFromUrl";
export function getFileFromApi(roles, id, dispatch) {
if (
(getRoleFromUrl() === "CityOperator" ||
getRoleFromUrl() === "Poultry" ||
getRoleFromUrl() === "KillHouse") &&
(roles.includes("Poultry") ||
roles.includes("CityOperator") ||
roles.includes("KillHouse"))
) {
dispatch(getFileProcessOther(id));
} else {
dispatch(getFileProcess(id));
}
}
const useRequestFile = (id) => {
const dispatch = useDispatch();
const file = useSelector((state) => state.fileSlice);
const [data, setData] = useState(file);
const [roles] = useUserProfile();
useEffect(() => {
if (
(getRoleFromUrl() === "CityOperator" ||
getRoleFromUrl() === "Poultry" ||
getRoleFromUrl() === "KillHouse" ||
getRoleFromUrl() === "KillHouseVet") &&
(roles.includes("Poultry") ||
roles.includes("CityOperator") ||
roles.includes("KillHouse") ||
roles.includes("KillHouseVet"))
) {
dispatch(getFileProcessOther(id));
} else {
dispatch(getFileProcess(id));
}
}, []);
useEffect(() => {
setData(file);
}, [file]);
return data ? data : [];
};
export default useRequestFile;

View File

@@ -0,0 +1,19 @@
import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getAcceptedSlaughterRequest } from "../services/getAcceptedSlaughterRequest";
export const useSlaughterAllocatedRequests = (id) => {
const dispatch = useDispatch();
const { acceptedSlaughterRequest } = useSelector((state) => state.fileSlice);
const [data, setData] = useState(acceptedSlaughterRequest);
useEffect(() => {
dispatch(getAcceptedSlaughterRequest({ id }));
}, []);
useEffect(() => {
setData(acceptedSlaughterRequest);
}, [acceptedSlaughterRequest]);
return data ? data : [];
};

View File

@@ -0,0 +1,25 @@
import { useState, useEffect } from "react";
import { useDispatch } from "react-redux";
import { slaughterGetCars } from "../../slaughter-house/services/slaughter-get-cars";
export const useSlaughterHouseCars = (id, killHouseKey, killRequestKey) => {
const dispatch = useDispatch();
// const { slaughterHouseCars } = useSelector((state) => state.slaughterSlice);
const [data, setData] = useState([]);
useEffect(() => {
if (id) {
dispatch(slaughterGetCars({ id, killHouseKey, killRequestKey })).then(
(r) => setData(r.payload.data)
);
} else {
dispatch(slaughterGetCars()).then((r) => setData(r.payload.data));
}
}, []);
// useEffect(() => {
// setData(slaughterHouseCars);
// }, [slaughterHouseCars]);
return data ? data : [];
};

View File

@@ -0,0 +1,21 @@
import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getSlaughterHousesRequest } from "../services/getSlaughterHousesRequest";
const useSlaughterHousesRequest = (id) => {
const dispatch = useDispatch();
const { slaughterHousesRequest } = useSelector((state) => state.fileSlice);
const [data, setData] = useState(slaughterHousesRequest);
useEffect(() => {
dispatch(getSlaughterHousesRequest({ key: id }));
}, []);
useEffect(() => {
setData(slaughterHousesRequest);
}, [slaughterHousesRequest]);
return data ? data : [];
};
export default useSlaughterHousesRequest;

View File

@@ -0,0 +1,13 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const checkRequestByCity = createAsyncThunk(
"REJECT_REQUEST_CITY",
async (d) => {
const { data, status } = await axios.post(
`city_operator_check_request/`,
d
);
return { data, status };
}
);

View File

@@ -0,0 +1,10 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const checkRequestBySlaughter = createAsyncThunk(
"CHECK_REQUEST_BY_SLAUGHTER",
async (d) => {
const { data, status } = await axios.post(`kill_house_check_request/`, d);
return { data, status };
}
);

View File

@@ -0,0 +1,13 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
export const poultryRequestIndexWeightService = createAsyncThunk(
"POULTRY_REQUEST_INDEX_WEIGHT_SERVICE",
async (d, { dispatch }) => {
dispatch(LOADING_START());
const { data, status } = await axios.get("/poultry_request_index_weight/");
dispatch(LOADING_END());
return { data, status };
}
);

View File

@@ -0,0 +1,10 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const depositeAllocation = createAsyncThunk(
"DEPOSITE_ALLOCATION",
async (d) => {
const { data, status } = await axios.put(`deposit_allocation/0/`, d);
return { data, status };
}
);

View File

@@ -0,0 +1,18 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
export const financialCheckRequest = createAsyncThunk(
"PROVINCE_CHECK_REQUEST",
async (d, { dispatch }) => {
dispatch(LOADING_START());
try {
const { data, status } = await axios.post(`province_check_info/`, d);
dispatch(LOADING_END());
return { data, status };
} catch (e) {
dispatch(LOADING_END());
return { error: e.response.data.result };
}
}
);

View File

@@ -0,0 +1,14 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
import { getRoleFromUrl } from "../../../utils/getRoleFromUrl";
export const getAllocationInformation = createAsyncThunk(
"GET_ALLOCATION_INFORMATION",
async (d) => {
const { data, status } = await axios.get(
`province_check_operator_request/`,
{ params: { ...d, role: getRoleFromUrl() } }
);
return { data, status };
}
);

View File

@@ -0,0 +1,10 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const getMonthlyPercent = createAsyncThunk(
"GET_MONTHLY_PERCENT",
async (d) => {
const { data, status } = await axios.get(`monthly_percent/`);
return { data, status };
}
);

View File

@@ -0,0 +1,17 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
import { getRoleFromUrl } from "../../../utils/getRoleFromUrl";
export const getAcceptedSlaughterRequest = createAsyncThunk(
"GET_ACCEPTED_SLAUGHTER_REQUEST",
async ({ id, role_key }) => {
const { data, status } = await axios.get("province_kill_request", {
params: {
id,
role: getRoleFromUrl(),
role_key: role_key || "",
},
});
return { data, status };
}
);

View File

@@ -0,0 +1,27 @@
import axios from "axios";
import { createAsyncThunk } from "@reduxjs/toolkit";
import { getRoleFromUrl } from "../../../utils/getRoleFromUrl";
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
export const getFileProcess = createAsyncThunk(
"GET_FILE",
async (id, { dispatch }) => {
dispatch(LOADING_START());
const { data, status } = await axios.get(`/Poultry_Request/${id}/`);
dispatch(LOADING_END());
return { data, status };
}
);
export const getFileProcessOther = createAsyncThunk(
"GET_FILE_OTHER",
async (id, { dispatch }) => {
dispatch(LOADING_START());
const { data, status } = await axios.get(
"process/?id=" + id + `&role=${getRoleFromUrl()}`
);
dispatch(LOADING_END());
return { data, status };
}
);

View File

@@ -0,0 +1,12 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const getSlaughterHousesRequest = createAsyncThunk(
"GET_SLAUGHTER_HOUSES_REQUEST",
async (d) => {
const { data, status } = await axios.get("/kill_request", {
params: d,
});
return { data, status };
}
);

View File

@@ -0,0 +1,10 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const getUserInformation = createAsyncThunk(
"USER_INFO_REQUESTS",
async () => {
const { data, status } = await axios.get("user-profile/?type=user");
return { data, status };
}
);

View File

@@ -0,0 +1,10 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const inspectorCheckRequest = createAsyncThunk(
"INSPECTOR_REQUEST_OPERATIONS",
async (d) => {
const { data, status } = await axios.post("inspector/", d);
return { data, status };
}
);

View File

@@ -0,0 +1,17 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
export const postSlaughterCarAllocation = createAsyncThunk(
"POST_SLAUGHTER_CAR_ALLOCATION",
async (d, { dispatch }) => {
try {
const { data, status } = await axios.post(`kill_house_request/`, d);
dispatch(LOADING_START());
return { data, status };
} catch (e) {
dispatch(LOADING_END());
return { error: e.response.data.result };
}
}
);

View File

@@ -0,0 +1,10 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const provinceCheckComplaint = createAsyncThunk(
"PROVINCE_CHECK_COMPLAINT",
async (d) => {
const { data, status } = await axios.post(`check_losses/`, d);
return { data, status };
}
);

View File

@@ -0,0 +1,17 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
export const provinceDoAllocation = createAsyncThunk(
"PROVINCE_DO_ALLOCATION",
async (d, { dispatch }) => {
try {
const { data, status } = await axios.post(`province_kill_request/`, d);
dispatch(LOADING_START());
return { data, status };
} catch (e) {
dispatch(LOADING_END());
return { error: e.response.data.result };
}
}
);

View File

@@ -0,0 +1,15 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
export const provinceRemoveAllocation = createAsyncThunk(
"PROVINCE_REMOVE_ALLOCATION",
async (d, { dispatch }) => {
dispatch(LOADING_START());
const { data, status } = await axios.delete(`province_kill_request/0/`, {
params: d,
});
dispatch(LOADING_END());
return { data, status };
}
);

View File

@@ -0,0 +1,10 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const provinceRequestAuction = createAsyncThunk(
"PROVINCE_REQUEST_AUCTION",
async (d) => {
const { data, status } = await axios.post(`province_request_auction/`, d);
return { data, status };
}
);

View File

@@ -0,0 +1,13 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const provinceAcceptRequest = createAsyncThunk(
"PROVINCE_ACCEPT_REQUEST",
async (d) => {
const { data, status } = await axios.post(
`province_check_operator_request/`,
d
);
return { data, status };
}
);

View File

@@ -0,0 +1,10 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const provinceFinancialSlaughterCheckRequest = createAsyncThunk(
"PROVINCE_FINANCIAL_CHECK_REQUEST",
async (d) => {
const { data, status } = await axios.post(`province_check_factor/`, d);
return { data, status };
}
);

View File

@@ -0,0 +1,13 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const provinceRejectRequest = createAsyncThunk(
"PROVINCE_REJECT_REQUEST",
async (d) => {
const { data, status } = await axios.post(
`province_check_operator_request/`,
d
);
return { data, status };
}
);

View File

@@ -0,0 +1,17 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
export const slaughterHouseVetSendCheckRequest = createAsyncThunk(
"SLAUGHTER_HOUSE_VET_SEND_CHECK_REQUEST",
async (d, { dispatch }) => {
try {
const { data, status } = await axios.post(`vet_check/`, d);
dispatch(LOADING_START());
return { data, status };
} catch (e) {
dispatch(LOADING_END());
return { error: e.response.data.result };
}
}
);

View File

@@ -0,0 +1,18 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
import { LOADING_END, LOADING_START } from "../../../lib/redux/slices/appSlice";
export const slaughterGetExlusiveKillers = createAsyncThunk(
"SLAUGHTER_GET_EXCLUSIVE_KILLERS",
async (d, { dispatch }) => {
dispatch(LOADING_START());
const { data, status } = await axios.get(
"kill_house/?exclusive-killers=true",
{
params: d,
}
);
dispatch(LOADING_END());
return { data, status };
}
);

View File

@@ -0,0 +1,10 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const slaughterPayPoultryFactor = createAsyncThunk(
"SLAUGHTER_PAY_POULTRY_FACTOR",
async (d) => {
const { data, status } = await axios.post(`kill_house_factor_poultry/`, d);
return { data, status };
}
);

View File

@@ -0,0 +1,10 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const slaughterPayProvinceFactor = createAsyncThunk(
"SLAUGHTER_PAY_PROVINCE_FACTOR",
async (d) => {
const { data, status } = await axios.post(`kill_house_factor_province/`, d);
return { data, status };
}
);

View File

@@ -0,0 +1,10 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const slaughterUpdatePayPoultryFactor = createAsyncThunk(
"SLAUGHTER_UPDATE_PAY_POULTRY_FACTOR",
async (d) => {
const { data, status } = await axios.put(`kill_house_factor_poultry/0/`, d);
return { data, status };
}
);

View File

@@ -0,0 +1,13 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const slaughterUpdatePayProvinceFactor = createAsyncThunk(
"SLAUGHTER_UPDATE_PAY_PROVINCE_FACTOR",
async (d) => {
const { data, status } = await axios.put(
`kill_house_factor_province/0/`,
d
);
return { data, status };
}
);

View File

@@ -0,0 +1,18 @@
import moment from "moment/moment";
import { format } from "date-fns-jalali";
export const getAllocatedAndAcceptedRequests = (requests) => {
return requests
.filter((item) => item.provinceKillRequestState === "accepted")
.map((item, i) => {
return {
label: `${item.killHouse.name} (${
item.killHouse.user.fullname
}) - تاریخ کشتار ${format(
new Date(moment(new Date(item.reciveDate)).format("YYYY-MM-DD")),
"yyyy/MM/dd"
)} `,
key: item.key,
};
});
};

View File

@@ -0,0 +1,38 @@
import moment from "moment/moment";
import { format } from "date-fns-jalali";
export const getSlaughterHousesForSelect = (slaughterHouses) => {
return slaughterHouses
.filter((item) => item.remainQuantity > 0)
.map((item, i) => {
const requestedHighWeight = item?.weightType?.highWeight
? "بالای 2.5 کیلو"
: null;
const requestedLowWeight = item?.weightType?.lowWeight
? "بین 2 تا 2.5 کیلو"
: null;
const requestedWeight = [requestedLowWeight, requestedHighWeight]
.filter((item) => item)
.join(" و ");
const requestedBuyTypeCash = item.buyType?.cash ? "نقدی" : null;
const requestedBuyTypeCredit = item.buyType?.credit ? "زمان دار" : null;
const requestedBuyType = [requestedBuyTypeCash, requestedBuyTypeCredit]
.filter((item) => item)
.join(" یا ");
return {
label: `${item.killHouse.name} (${
item.killHouse.killHouseOperator.user.fullname
}) - تاریخ کشتار ${format(
new Date(moment(new Date(item.reciveDate)).format("YYYY-MM-DD")),
"yyyy/MM/dd"
)} با تعداد مانده درخواست ${
item.remainQuantity
} قطعه با وزن درخواستی: ${requestedWeight} و پرداخت بصورت ${requestedBuyType}`,
key: item.key,
remainQuantity: item.remainQuantity,
requestedWeight: requestedWeight,
requestedBuyType: requestedBuyType,
};
});
};