Android_Retail/src/Pages/WholeSaleReport/WholeSalesSalesReport.jsx

960 lines
25 KiB
JavaScript

import React, { useEffect, useState, useRef } from 'react';
import { useDispatch } from 'react-redux';
import { Tooltip, Form, Divider, Rate } from 'antd';
import moment from 'moment';
import { DatePicProd } from '../../Components/Forms/DatePickerProduct.jsx';
import { Tables } from '../../Components/Tables/Table.jsx';
import { BiSolidPrinter } from 'react-icons/bi';
import './WholeSaleSalesReport.scss';
import { changeBreadCrumb } from '../../Features/AppPage/CenterPage.js';
import { getWholeSaleSalesReport } from '../../Features/BookingScreen/BookingData/BookingData.js';
import { extractLastNumber, getSession } from '../../Services/Others.js';
import { printDiv } from '../../Services/WSOthers.js';
import SalesPrintpdf from '../PurchaseScreen/WholeSalePrint/wholeSaleSaleReportPrintPdf.jsx';
import { isMobile } from 'react-device-detect';
import Search from '../../Components/Forms/Search.jsx';
import { DefaultModal } from '../../Components/Modal/DefaultModal.jsx';
const subDirectory = import.meta.env.BASE_URL;
const WholeSaleSalesReport = () => {
const formRef = useRef();
const dispatch = useDispatch();
const [datewiseData, setDatewiseData] = useState();
const CompId = getSession('CompId');
const BranchId = getSession('BranchId');
const UserRole = getSession('UserType');
const AppId = getSession('AppId');
const [OrderFromDate, setOrderFromDate] = useState();
const [OrderToDate, setOrderToDate] = useState();
const [UserId, setUserId] = useState(
UserRole != 'Employee' ? 0 : getSession('UserId')
);
const [page, setpage] = useState(1);
const [page1, setpage1] = useState(1);
const [receiptText, setreceiptText] = useState(null);
const [WholeDataSource, setWholeDataSource] = useState([]);
const [searchedText, setSearchedText] = useState('');
const [isSalesReportModel, SetisSalesReportModel] = useState(false);
const [insideWholeDataSource, SetinsideWholeDataSource] = useState([]);
const OthersDataSource =
datewiseData?.[0]?.ExtraChargeDetails?.length > 0
? datewiseData?.[0]?.ExtraChargeDetails
: [];
const [selectedCus, setselectedCus] = useState('');
console.log(datewiseData?.[0]?.ExtraChargeDetails, 'sssssssssssssssssss');
console.log(insideWholeDataSource, 'insideWholeDataSource');
useEffect(() => {
if (WholeDataSource?.length > 0) {
mobileDateWisePrintFun(WholeDataSource);
}
}, [WholeDataSource]);
const reprintDate = (date) => {
const salesDate = new Date(date);
const formattedDate = salesDate.toLocaleDateString('en-GB', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
});
return formattedDate;
};
const mobileDateWisePrintFun = async (data) => {
let Dataa = WholeDataSource;
let Tabledata = Dataa?.map((data, index) => {
const snoSpacing = Math.max(0, 3 - String(index + 1).length);
// Calculate dynamic spacing for Rate
const rateSpacing = Math.max(0, 9 - String(data?.NetAmount).length);
const QtySpacing = Math.max(
0,
3 - String(data?.CountOfPaymentType).length
);
// Generate formatted string with dynamic spacings
const formattedString =
' '.repeat(snoSpacing) +
parseInt(index + 1) +
' ' +
(data?.PaymentMethod + ' '.repeat(22)).substring(0, 22) +
' ' +
' '.repeat(QtySpacing) +
String(data?.CountOfPaymentType) +
' ' +
' '.repeat(rateSpacing) +
String(data?.NetAmount) +
' ' +
'\n';
return formattedString;
});
const AmountSpace = Math.max(
0,
6 - String(parseFloat(TotalBill).toFixed(2)).length
);
const Billamountspace = Math.max(
0,
6 -
String(datewiseData?.[0]?.WholeSaleExpenseNetAmount?.toFixed(2)).length
);
const Taxamountspace = Math.max(
0,
6 -
String(datewiseData?.[0]?.WholeSaleExpenseTaxAmount?.toFixed(2)).length
);
const Netamountspace = Math.max(
0,
6 -
String(datewiseData?.[0]?.WholeSaleExpenseNetAmount?.toFixed(2)).length
);
var receiptTextdata =
"[C]<b><font size='big'>" +
'Datewise Sales' +
'</font></b>\n' +
'[L]<b>From Date :' +
reprintDate(OrderFromDate) +
'[R]<b>' +
' ' +
'To Date :' +
reprintDate(OrderToDate) +
'</b>\n' +
'[C]------------------------------------------------\n' +
'[L]<b>' +
'' +
'S.No' +
' ' +
' Payment Type ' +
' ' +
'Count ' +
' ' +
'Amount ' +
'' +
'</b>' +
'[L]\n' +
'[C]------------------------------------------------\n' +
Tabledata.join('') +
'[C]<b>------------------------------------------------</b>\n' +
'[L]<b>' +
'Total Orders:' +
datewiseData?.[0]?.Orders +
'</b>' +
'[R]<b>' +
'TotalAmount:' +
parseFloat(TotalBill).toFixed(2) +
' '.repeat(AmountSpace) +
'</b>\n' +
'[R]<b>' +
'Total Bill:' +
parseFloat(datewiseData?.[0]?.WholeSaleExpenseNetAmount).toFixed(2) +
' '.repeat(Billamountspace) +
'</b>\n' +
'[R]<b>' +
'Total Tax:' +
parseFloat(datewiseData?.[0]?.WholeSaleExpenseTaxAmount).toFixed(2) +
' '.repeat(Taxamountspace) +
'</b>\n' +
'[L]<b>------------------------------------------------</b>\n' +
'[R]<b>' +
'Net:' +
parseFloat(datewiseData?.[0]?.WholeSaleExpenseNetAmount).toFixed(2) +
' '.repeat(Netamountspace) +
'</b>\n';
setreceiptText(receiptTextdata);
};
const items = [
{
name: 'Home',
link: `${subDirectory}app-page/home`,
},
];
const style = `<style>
@import url('https://fonts.googleapis.com/css2?family=Calistoga&display=swap');
@media print {
body {
font-family:"Calistoga", serif;
font-size: 10px;
margin: 0;
padding: 0;
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family:"Calistoga", serif;
}
.purchase-report {
font-family:"Calistoga", serif;
max-width: max-content;
margin: 0 auto;
border: 1px solid #000;
padding: 1px 1px;
text-align: center;
background-color: #ffffff;
}
.wc-header {
display: flex;
align-items: flex-start;
gap: 4px;
padding: 4px 4px;
}
.imagelogo {
width: 65px;
height: 60px;
}
.mandiName {
font-size: 13px;
font-weight: 700;
width: 100%;
}
.wcadd1 {
font-size: 10px;
font-weight: 600;
}
.wcadd2 {
font-size: 10px;
font-weight: 600;
}
.wcphone {
font-size: 8px;
font-weight: 600;
}
.infoOfMandi {
width: 100%;
// text-align: center;
}
.wc-datetime {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 8px;
width: 95%;
}
.wc-date {
font-size: 11px;
font-weight: 600;
padding: 1px 0;
}
.wc-supName {
font-size: 11px;
font-weight: 600;
}
.header {
text-align: center;
margin-bottom: 1px;
padding-bottom: 10px;
display: flex;
gap: 10px;
}
.logo {
width: 65px;
height: 90px;
margin-bottom: 1px;
}
.date-time {
display: flex;
font-size: 10px;
align-items: center;
justify-content: space-between;
width: 95%;
padding: 0px 1px;
padding-bottom: 2px;
border-bottom: 1px solid #000;
}
.table-container {
width: 100%;
}
.table {
width: 95%;
border-collapse: collapse;
// margin-left:2px;
}
.table th, .table td {
border: 1px solid #000;
padding: 1px 1px;
text-align: center;
}
.total {
text-align: right;
}
.footer {
margin-top: 20px;
text-align: center;
// border-top: 1px solid #000;
padding-top: 10px;
}
.summary {
text-align: right;
margin-bottom: 10px;
font-size: 16px;
font-weight: bold;
}
.boldText {
}
.noneBorder {
border: none !important;
}
.infoOfMandi {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 2px;
}
.printmandiName {
border-bottom: 1px solid #000;
text-align: left;
font-size: 20px;
word-wrap: break-word;
padding: 6px 0;
font-weight: 500;
}
.databody {
> tr:nth-child(1) {
width: 10%;
}
> tr:nth-child(2) {
width: 30%;
}
> tr:nth-child(3) {
width: 30%;
}
> tr:nth-child(4) {
width: 30%;
}
> tr > td {
font-size: 10px !important;
}
}
.prtTitle {
font-size: 16px;
width: 100%;
text-align: center;
padding:4px 4px;
}
.tableHead {
font-size: 10px !important;
}
table th, .table td {
text-align: center;
border-width: 1px;
border-style: solid;
border-color: rgb(0, 0, 0);
border-image: initial;
padding: 4px 1px !important;
}
.Add-Shortname{
display: flex;
width: 95%;
justify-content: space-between;
}
.Address{
display:flex;
flex-direction:column;
width:77%
}
.ShortNameDiv{
display:flex;
width:23%;
font-size: 16px;
font-weight: 700;
background: #252525 !important;
color:white;
text-align:center;
justify-content:center;
align-items:center;
margin:2px ;
padding: 0px 5px;
border: 1px solid black;
border-radius:5px;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
</style>`;
useEffect(() => {
dispatch(changeBreadCrumb({ items: items }));
fetchInitialData();
}, []);
const fetchInitialData = async () => {
let currentDate = new Date().toJSON().slice(0, 10);
formRef?.current?.setFieldsValue({
Fromdate: currentDate,
Todate: currentDate,
});
setOrderFromDate(currentDate + 'T00:00:00');
setOrderToDate(currentDate + 'T00:00:00');
let data = {
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
OrderFromDate: currentDate,
OrderToDate: currentDate,
UserId: UserRole != 'Employee' ? 0 : UserId,
};
let response = await dispatch(getWholeSaleSalesReport(data)).unwrap();
if (response?.data?.statusCode === 1) {
setDatewiseData(response?.data?.data);
setWholeDataSource(response?.data?.data);
} else {
setDatewiseData([]);
}
};
const addinsideWholeDataSource = (record) => {
SetinsideWholeDataSource(
record?.ProductDetails?.flatMap((item, index) =>
item?.SupplierList?.map((item1, index1) => ({
SINO: index1 + 1,
ProdName: item?.ProdName,
QualityName: item?.QualityName,
OrderId: item1?.OrderId,
GradeOverAllCount: item1?.SalesQty,
GradeOverAllAmount: item1?.TotalAmt,
Rate: item1?.Rate,
Amount: item1?.Amount,
TotalAmount: item1?.TotalAmount,
CustSuppName: item1?.CustSuppName,
}))
)
);
setselectedCus(
record?.CustShortName || record?.CustSuppName || record?.CustSuppMobileNo
);
};
const columns = [
{
title: 'SI NO',
dataIndex: 'SINO',
key: 'SINO',
align: 'center',
render: (text, object, index) => (
<a style={{ color: 'black' }}>{(page - 1) * 10 + index + 1}</a>
),
onCell: (record) => ({
onClick: () => {
SetisSalesReportModel(true);
addinsideWholeDataSource(record);
},
}),
},
{
title: 'Customer Name',
dataIndex: 'CustShortName',
key: 'CustShortName',
render: (text, record, index) => (
<a style={{ color: 'black' }}>
{record?.CustShortName ||
record?.CustSuppName ||
record?.CustSuppMobileNo}
</a>
),
onCell: (record) => ({
onClick: () => {
SetisSalesReportModel(true);
addinsideWholeDataSource(record);
},
}),
filteredValue: [searchedText],
onFilter: (value, record) => {
return String(
record?.CustShortName ||
record?.CustSuppName ||
record?.CustSuppMobileNo
)
?.toLowerCase()
?.includes(value?.toLowerCase());
},
},
{
title: 'Qty',
dataIndex: 'OverAllCount',
key: 'OverAllCount',
align: 'right',
render: (text, record, index) => (
<a style={{ color: 'black' }}>{record?.OverAllCount} </a>
),
onCell: (record) => ({
onClick: () => {
SetisSalesReportModel(true);
addinsideWholeDataSource(record);
},
}),
},
{
title: 'Amount',
dataIndex: 'OverAllAmount',
key: 'OverAllAmount',
align: 'right',
render: (text, record, index) => (
<a style={{ color: 'black' }}>{record?.OverAllAmount} </a>
),
onCell: (record) => ({
onClick: () => {
SetisSalesReportModel(true);
addinsideWholeDataSource(record);
},
}),
},
];
const Otherscolumns = [
{
title: 'SI NO',
dataIndex: 'SINO',
key: 'SINO',
align: 'center',
render: (text, object, index) => (
<a style={{ color: 'black' }}>{(page - 1) * 10 + index + 1}</a>
),
},
{
title: 'Charge Name',
dataIndex: 'ExtraChargeTypeName',
width: '150px',
key: 'ExtraChargeTypeName',
align: 'left',
render: (text, record, index) => (
<a style={{ color: 'black' }}>{record?.ExtraChargeTypeName}</a>
),
},
{
title: 'Amount',
dataIndex: 'TotalAmt',
key: 'TotalAmt',
align: 'right',
},
];
const Insidecolumns = [
{
title: 'SI NO',
dataIndex: 'SINO',
key: 'SINO',
align: 'center',
render: (text, object, index) => (
<a style={{ color: 'black' }}>{(page1 - 1) * 10 + index + 1}</a>
),
},
{
title: 'Receipt No',
dataIndex: 'OrderId',
key: 'OrderId',
align: 'left',
render: (text, record, index) => (
<a style={{ color: 'black' }}>{extractLastNumber(record?.OrderId)}</a>
),
},
{
title: 'Seller',
dataIndex: 'CustSuppName',
key: 'CustSuppName',
align: 'left',
render: (text, record, index) => (
<a style={{ color: 'black' }}>{record?.CustSuppName}</a>
),
},
{
title: 'Product Name',
dataIndex: 'ProdName',
key: 'ProdName',
align: 'left',
render: (text, record, index) => (
<a style={{ color: 'black' }}>
{record?.ProdName}{' '}
{record?.QualityName?.includes('Grade')
? record?.QualityName.split('Grade')[1].trim().replace(/^-/, '')
: record?.QualityName}
</a>
),
},
{
title: 'Rate',
dataIndex: 'Rate',
key: 'Rate',
align: 'right',
render: (text, record, index) => (
<a style={{ color: 'black' }}>{record?.Rate}</a>
),
},
{
title: 'Qty',
dataIndex: 'GradeOverAllCount',
key: 'GradeOverAllCount',
align: 'right',
render: (text, record, index) => (
<a style={{ color: 'black' }}>{record?.GradeOverAllCount}</a>
),
},
{
title: 'Amount',
dataIndex: 'GradeOverAllAmount',
key: 'GradeOverAllAmount',
align: 'right',
render: (text, record, index) => (
<a style={{ color: 'black' }}>{record?.GradeOverAllAmount}</a>
),
},
];
const OrderFromDatefetch = async (date, dateString) => {
if (dateString === '') {
setOrderFromDate();
}
if (dateString) {
const Date3 = moment(dateString, ['DD-MM-YYYY']).format(
'YYYY-MM-DDTHH:mm:ss'
);
formRef.current?.setFieldsValue({ Fromdate: Date3 });
await setOrderFromDate(Date3);
}
};
const OrderToDatefetch = async (date, dateString) => {
if (dateString === '') {
setOrderToDate();
}
if (dateString) {
const Date4 = moment(dateString, ['DD-MM-YYYY']).format(
'YYYY-MM-DDTHH:mm:ss'
);
formRef.current?.setFieldsValue({ Todate: Date4 });
await setOrderToDate(Date4);
}
};
const Print = async () => {
let LogoImage = '';
let OrderId = '';
let UpiId = '';
let TokenData = '';
let FooterPrint = '';
if (isMobile) {
var textEncoded = encodeURI(receiptText);
var TypeCheck = 'PrintReceipt';
var scheme = 'pozoprinter';
var packageName = 'com.example.pozoprinter';
window.location.href =
scheme +
'://' +
textEncoded +
'#Intent;scheme=' +
scheme +
';package=' +
packageName +
'ImgS' +
LogoImage +
'ImgE' +
TypeCheck +
'TokenS' +
TokenData +
'TokenE' +
'EstimateS' +
'' +
'EstimateE' +
'HasFooterTextS' +
FooterPrint +
'HasFooterTextE' +
';end;';
} else {
await printDiv('RePrint', style);
}
};
const onFinish = async (values) => {
let data = {
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
OrderFromDate: OrderFromDate?.split('T')?.[0],
OrderToDate: OrderToDate?.split('T')?.[0],
UserId: UserId,
};
let response = await dispatch(getWholeSaleSalesReport(data)).unwrap();
if (response?.data?.statusCode === 1) {
setDatewiseData(response?.data?.data);
setWholeDataSource(response?.data?.data);
} else {
setDatewiseData([]);
setWholeDataSource([]);
}
};
const TotalBill = 0;
let totalCount = WholeDataSource?.reduce((accumulator, currentValue) => {
return accumulator + currentValue?.OverAllCount;
}, 0);
let TotalAmt = WholeDataSource?.reduce((accumulator, currentValue) => {
return accumulator + currentValue?.OverAllAmount;
}, 0);
let TotalCharges = WholeDataSource?.[0]?.OverallExtraChargesAmount;
let TotalCommision = WholeDataSource?.[0]?.OverallCommissionAmount;
const handlePageChange = (current) => {
setpage(current);
};
const handlePageChangeInside = (current) => {
setpage1(current);
};
const onSearch = (value) => {
setSearchedText(value);
};
const onSearchChange = (e) => {
setSearchedText(e?.target?.value);
};
return (
<div className="SalesReport-container">
<div style={{ display: 'none' }}>
<SalesPrintpdf
OrderFromDate={OrderFromDate?.split('T')?.[0]}
OrderToDate={OrderToDate?.split('T')?.[0]}
dataSource={WholeDataSource}
TotalBill={TotalAmt}
TotalOrders={totalCount}
TotalBillAmount={TotalAmt}
TotalNetAmount={TotalAmt}
TotalCharges={TotalCharges}
TotalCommision={TotalCommision}
ExtraChargeDetails={OthersDataSource}
/>
</div>
<Form ref={formRef} onFinish={onFinish}>
<div className="SalesReport-dateandheading" style={{ display: 'flex' }}>
<p className="SalesReport-heading"> Sales Report</p>
<div className="SalesReport-dateaAnd-buttons">
<div
className="SalesReport-Date-picker"
style={{ display: 'flex', flexDirection: 'row', rowGap: '1rem' }}
>
<div className="SalesReport-datepic">
<div className="SalesReport-DateFrom">
<div className="SalesReport-Date">
<p className="SalesReport-Date-from-heading">From Date</p>
</div>
<Form.Item
name="Fromdate"
rules={[
{
required: true,
pattern: /^(?!\s*$).+/,
message: 'Please Enter the From Date ',
},
]}
>
<DatePicProd
onChange={OrderFromDatefetch}
style={{ width: '24vw', height: '2.6rem' }}
valueData={OrderFromDate}
canSelectPast={true}
cancelFuture={true}
/>
</Form.Item>
</div>
<div>
<div>
<p>To Date</p>
</div>
<Form.Item
name="Todate"
rules={[
{
required: true,
pattern: /^(?!\s*$).+/,
message: 'Please Enter the To Date ',
},
]}
>
<DatePicProd
onChange={OrderToDatefetch}
style={{ width: '24vw', height: '2.6rem' }}
valueData={OrderToDate}
canSelectPast={true}
cancelFuture={true}
minDate={OrderFromDate}
/>
</Form.Item>
</div>
</div>
</div>
<div className="SalesReport-submit-prnt">
<div>
<Tooltip title="Submit to search">
<button type="submit" className="SalesReport-submit-btn">
SUBMIT
</button>
</Tooltip>
</div>
<div className="PurchaseSearch">
<Search
placeholder="Search"
onSearch={onSearch}
onSearchChange={onSearchChange}
/>
</div>
<div>
<Tooltip title="Print">
<BiSolidPrinter
className={
datewiseData?.length > 0
? 'SalesReport-printerIcon'
: 'SalesReport-printerIcon-disabled'
}
onClick={Print}
/>
</Tooltip>
</div>
</div>
</div>
</div>
<div className="SalesReport-coontent-body">
<div className="SalesReport-table-withoutDenom">
<div className="tables-container">
<div className="SalesReport-table">
<Tables
columns={columns}
data={WholeDataSource}
pagination={handlePageChange}
/>
</div>
<div className="OthersReport-table">
<Tables
columns={Otherscolumns}
data={OthersDataSource}
pagination={handlePageChange}
/>
</div>
</div>
<div className="SalesReport-Amount-Collected-container">
<div className="SalesReport-Amount-Collected-table">
<table className="SalesReport-Amount-Collected-table-div">
<thead>
<tr>
<th className="reportHeaderEnd">
Qty <span>:</span>
</th>
<th className="reportValueEnd">
{WholeDataSource?.reduce(
(accumulator, currentValue) => {
return accumulator + currentValue?.OverAllCount;
},
0
)}
</th>
</tr>
<tr>
<th className="reportHeaderEnd">
Amount <span>:</span>
</th>
<th className="reportValueEnd">{TotalAmt || 0}</th>
</tr>
<tr>
<th className="reportHeaderEnd">
Charges(+) <span>:</span>
</th>
<th className="reportValueEnd">{TotalCharges || 0}</th>
</tr>
<tr>
<th className="reportHeaderEnd">
Commission(-)<span>:</span>
</th>
<th className="reportValueEnd">{TotalCommision || 0}</th>
</tr>
<tr>
<th className="reportHeaderEnd">
Total<span>:</span>
</th>
<th className="reportValueEnd">
{Math.round(TotalAmt + TotalCharges - TotalCommision) ||
0}
</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
</Form>
<DefaultModal
open={isSalesReportModel}
title={'Sales Details'}
handleCancel={() => {
SetisSalesReportModel(false);
}}
footer={false}
width={750}
className={'WholeSalePurchaseList'}
children={
<div>
<a style={{ color: 'black' }}>{selectedCus}</a>
<div className="PurchaseReport-table-inside">
<Tables
columns={Insidecolumns}
data={insideWholeDataSource}
pagination={handlePageChangeInside}
/>
</div>{' '}
</div>
}
></DefaultModal>
</div>
);
};
export default WholeSaleSalesReport;