379 lines
20 KiB
TypeScript
379 lines
20 KiB
TypeScript
/*
|
|
* @Author: cclu
|
|
* @Date: 2022-03-10 16:59:45
|
|
* @LastEditTime: 2024-01-23 18:45:00
|
|
* @LastEditors: cclu 1106109051@qq.com
|
|
* @Description: 销售流水页面
|
|
* @FilePath: \cloud-platform\src\pages\merchantManagement\reports\SalesFlow\index.tsx
|
|
*/
|
|
import { connect } from 'umi';
|
|
import useRequest from '@ahooksjs/use-request';
|
|
import { PageContainer } from '@ant-design/pro-layout';
|
|
import ProTable from '@ant-design/pro-table';
|
|
import FlowDetail from './components/FlowDetail';
|
|
import ProCard from '@ant-design/pro-card';
|
|
import { MenuFoldOutlined } from '@ant-design/icons';
|
|
import { Button, Descriptions, message, Modal, Space, Tree, Typography } from 'antd';
|
|
import { useRef, useState } from 'react';
|
|
|
|
import type { ConnectState } from '@/models/connect';
|
|
import type { ProFormInstance } from '@ant-design/pro-form';
|
|
import type { ActionType, ProColumns } from '@ant-design/pro-table';
|
|
import type { YSSELLMASTERModel } from './data';
|
|
import type { CurrentUser } from '@/models/user';
|
|
|
|
import moment from 'moment';
|
|
import numeral from 'numeral';
|
|
|
|
import { exportExcel } from '@/utils/utils';
|
|
import { getYSSellMasterList } from './service';
|
|
import { getMoney, getUserShopTree } from '@/services/options';
|
|
|
|
import '../../style.less';
|
|
import './salesFlow.less'
|
|
import { getYSSellMasterListAllData } from '@/pages/reports/BusinessAnalysis/saleFlow/service';
|
|
|
|
const { Text } = Typography;
|
|
|
|
/**
|
|
* @description: 商户销售流水查询
|
|
* @param {CurrentUser} CurrentUser 当前登录的用户信息
|
|
* @return {React.FC} 页面主题
|
|
*/
|
|
const CommoditysaleTable: React.FC<{ currentUser: CurrentUser | undefined }> = (props) => {
|
|
const { currentUser } = props
|
|
const actionRef = useRef<ActionType>();
|
|
const formRef = useRef<ProFormInstance>();
|
|
|
|
const [currentRow, setCurrentRow] = useState<YSSELLMASTERModel | undefined>(); // 选中的流水
|
|
const [visible, setVisible] = useState<boolean>(); // 流水明显弹出框
|
|
const [reqDetailList, setReqDetailList] = useState<YSSELLMASTERModel[]>();
|
|
|
|
const [collapsible, setCollapsible] = useState<boolean>(false) // 是否隐藏门店服务区筛选
|
|
const { loading: shopLoading, data: shopTree } = useRequest(() => { return getUserShopTree(currentUser?.ID) })
|
|
const defaultShops = currentUser?.ServerpartShopIds ? currentUser?.ServerpartShopIds.split(',').map(Number) : []
|
|
const [shopId, setShopId] = useState<[]>(); // 选择的门店 根据选择的门店筛选数据结果
|
|
const [otherData, setOtherData] = useState<any>()
|
|
|
|
const columns: ProColumns<YSSELLMASTERModel>[] = [
|
|
|
|
{
|
|
dataIndex: 'index',
|
|
title: '序号',
|
|
hideInSearch: true,
|
|
// valueType: 'index',
|
|
// fixed: true,
|
|
align: 'center',
|
|
width: 48,
|
|
render: (_, reocrd) => {
|
|
return reocrd.index
|
|
}
|
|
},
|
|
{
|
|
dataIndex: 'SELLMASTER_DATE',
|
|
valueType: "date",
|
|
title: '销售时间',
|
|
align: 'center',
|
|
initialValue: moment().add(-1, 'day'),
|
|
render: (_, record) => {
|
|
return record?.SELLMASTER_DATE
|
|
},
|
|
fieldProps: {
|
|
disabledDate: (current: any) => current && current > moment().endOf('day').add(-1, 'day')
|
|
}
|
|
|
|
},
|
|
{
|
|
dataIndex: 'TICKET_CODE',
|
|
title: '小票编号',
|
|
hideInSearch: true,
|
|
align: 'center',
|
|
},
|
|
{
|
|
dataIndex: 'SELLMASTER_COUNT',
|
|
title: '销售数量',
|
|
hideInSearch: true,
|
|
align: 'right',
|
|
sorter: (a, b) => a.SELLMASTER_COUNT - b.SELLMASTER_COUNT
|
|
},
|
|
|
|
|
|
{
|
|
dataIndex: 'SELLMASTER_AMOUNT',
|
|
title: '实收金额',
|
|
hideInSearch: true,
|
|
valueType: "money",
|
|
align: 'right',
|
|
sorter: (a, b) => a.SELLMASTER_AMOUNT - b.SELLMASTER_AMOUNT
|
|
},
|
|
{
|
|
dataIndex: 'SELLMASTER_OFFPRICE',
|
|
title: '优惠金额',
|
|
hideInSearch: true,
|
|
valueType: "money",
|
|
align: 'right',
|
|
sorter: (a, b) => a.SELLMASTER_OFFPRICE - b.SELLMASTER_OFFPRICE
|
|
},
|
|
{
|
|
dataIndex: 'PAYMENT_TYPE_TEXT',
|
|
title: '支付方式',
|
|
hideInSearch: true,
|
|
align: 'center',
|
|
},
|
|
|
|
{
|
|
dataIndex: 'SHOPNAME',
|
|
hideInSearch: true,
|
|
title: '门店名称',
|
|
align: 'center',
|
|
width: '12%',
|
|
},
|
|
{
|
|
dataIndex: 'MACHINECODE',
|
|
hideInSearch: true,
|
|
title: '收银机号',
|
|
align: 'center',
|
|
},
|
|
{
|
|
dataIndex: 'SELLWORKER_NAME',
|
|
hideInSearch: true,
|
|
title: '收银人员',
|
|
align: 'center',
|
|
}
|
|
|
|
];
|
|
|
|
return (
|
|
<PageContainer header={{
|
|
title: '',
|
|
breadcrumb: {},
|
|
}}>
|
|
<ProCard split="vertical" style={{ backgroundColor: '#fff' }}>
|
|
|
|
<ProCard
|
|
className="pageTable-leftnav"
|
|
bodyStyle={{ padding: 0, paddingTop: 20, paddingLeft: 20 }}
|
|
extra={<MenuFoldOutlined onClick={() => { setCollapsible(!collapsible) }} />}
|
|
colSpan={!collapsible ? "240px" : "60px"}
|
|
title={!collapsible ? "可筛选门店" : ""}
|
|
headerBordered
|
|
collapsed={collapsible}
|
|
>
|
|
|
|
{shopTree && <Tree
|
|
checkable
|
|
treeData={!shopLoading ? shopTree : []}
|
|
fieldNames={{
|
|
title: "label",
|
|
key: "value"
|
|
}}
|
|
// defaultCheckedKeys={defaultShops}
|
|
defaultExpandedKeys={defaultShops}
|
|
blockNode
|
|
// onSelect={onSelect}
|
|
onCheck={(checkedKeys: React.Key[] | any, checkedInfo: any) => {
|
|
if (checkedInfo.checkedNodes.length > 0) {
|
|
|
|
const checkedPart = checkedInfo.checkedNodes.reduce((accumulator: any[], current: { type: number; value: any; }) => {
|
|
if (current.type === 2) {
|
|
|
|
accumulator.push(current.value)
|
|
}
|
|
return accumulator
|
|
}, [])
|
|
setShopId(checkedPart.toString())
|
|
} else {
|
|
setShopId([])
|
|
|
|
}
|
|
// actionRef.current?.reload()
|
|
return checkedKeys
|
|
}}
|
|
|
|
>
|
|
</Tree>}
|
|
</ProCard>
|
|
<ProCard className="report-table-card" bodyStyle={{ paddingTop: 0, paddingBottom: 0, paddingRight: 0 }}>
|
|
<ProTable<YSSELLMASTERModel>
|
|
rowKey="SELLMASTER_CODE"
|
|
headerTitle={<Text type="success" style={{ color: "#1890ff", fontSize: 14 }} strong>销售流水明细</Text>}
|
|
formRef={formRef}
|
|
actionRef={actionRef}
|
|
search={{ span: 6 }}
|
|
request={async (params) => {
|
|
if (shopId && shopId.length > 0) {
|
|
const data = await getYSSellMasterListAllData({
|
|
...params,
|
|
SERVERPARTSHOP_ID: shopId && shopId.length > 0 ? shopId.toString() : currentUser?.ServerpartShopIds,
|
|
});
|
|
setReqDetailList(data.List);
|
|
console.log('data', data);
|
|
const list: any = JSON.parse(JSON.stringify(data.List))
|
|
if (list && list.length > 0) {
|
|
list.forEach((item: any, index: number) => {
|
|
item.index = index + 1
|
|
})
|
|
}
|
|
console.log('list', list);
|
|
data.List = list
|
|
setOtherData(data.OtherData)
|
|
return { data: data.List, success: true };
|
|
}
|
|
return { data: [], success: true }
|
|
}}
|
|
rowClassName="saleflow-row"
|
|
bordered
|
|
columns={columns}
|
|
toolbar={{
|
|
actions: [
|
|
<Button
|
|
key="new"
|
|
type="primary"
|
|
onClick={async () => {
|
|
const success = await exportExcel(
|
|
columns.slice(2),
|
|
reqDetailList || [],
|
|
`销售流水统计_${moment().format('YYYY/MM/DD')}`,
|
|
);
|
|
if (success.message !== 'ok') {
|
|
message.info({ content: success.message });
|
|
}
|
|
}}
|
|
>
|
|
导出excel
|
|
</Button>
|
|
],
|
|
}}
|
|
tableExtraRender={
|
|
(_, data) => {
|
|
if (data) {
|
|
const devicesList: any = []
|
|
const reduceData = data.reduce((
|
|
p: {
|
|
SELLMASTER_OFFPRICE: number,
|
|
SELLMASTER_COUNT: number,
|
|
SELLMASTER_AMOUNT: number,
|
|
MACHINECODE: string[],
|
|
payway: {},
|
|
mobilePay: {}
|
|
},
|
|
|
|
currentValue: YSSELLMASTERModel) => {
|
|
const previousValue = { ...p }
|
|
previousValue.SELLMASTER_COUNT += currentValue.SELLMASTER_COUNT || 0; // 销售数量
|
|
previousValue.SELLMASTER_OFFPRICE += currentValue.SELLMASTER_OFFPRICE || 0; // 优惠金额
|
|
previousValue.SELLMASTER_AMOUNT += currentValue.SELLMASTER_AMOUNT || 0; // 实收金额
|
|
|
|
if (devicesList.indexOf(currentValue.MACHINECODE) === -1) {
|
|
devicesList.push(currentValue.MACHINECODE)
|
|
}
|
|
|
|
if (currentValue.PAYMENT_TYPE === 1010 || currentValue.PAYMENT_TYPE === 1020) {
|
|
previousValue.payway['移动'] += currentValue.SELLMASTER_AMOUNT
|
|
if (!previousValue.mobilePay[currentValue.PAYMENT_TYPE_TEXT]) { // 移动支付方式
|
|
previousValue.mobilePay[currentValue.PAYMENT_TYPE_TEXT] = 0
|
|
}
|
|
previousValue.mobilePay[currentValue.PAYMENT_TYPE_TEXT] += currentValue.SELLMASTER_AMOUNT
|
|
} else {
|
|
if (!previousValue.payway[currentValue.PAYMENT_TYPE_TEXT]) { // 支付方式
|
|
previousValue.payway[currentValue.PAYMENT_TYPE_TEXT] = 0
|
|
}
|
|
previousValue.payway[currentValue.PAYMENT_TYPE_TEXT] += currentValue.SELLMASTER_AMOUNT
|
|
}
|
|
if (!previousValue.MACHINECODE.includes(currentValue.MACHINECODE)) {
|
|
|
|
previousValue.MACHINECODE.push(currentValue.MACHINECODE); // 收银机号
|
|
}
|
|
return previousValue
|
|
}, {
|
|
SELLMASTER_OFFPRICE: 0,
|
|
SELLMASTER_COUNT: 0,
|
|
SELLMASTER_AMOUNT: 0,
|
|
MACHINECODE: [],
|
|
payway: { '移动': 0, '现金': 0, },
|
|
mobilePay: {}
|
|
});
|
|
return <div style={{ paddingLeft: 24 }}>
|
|
<Descriptions
|
|
title={<Text type="success" style={{ color: "#1890ff", fontSize: 14 }}>合计信息</Text>}
|
|
size="small" column={7}
|
|
className="commity-sale-description"
|
|
contentStyle={{ fontWeight: "bolder" }} labelStyle={{ color: "#00000073" }}
|
|
>
|
|
<Descriptions.Item label="客单数量">{numeral(data.length).format('0,0')}<Text
|
|
type="secondary"> 笔</Text></Descriptions.Item>
|
|
<Descriptions.Item
|
|
label="实收金额">¥{numeral(reduceData.SELLMASTER_AMOUNT).format('0,0.00')}</Descriptions.Item>
|
|
<Descriptions.Item
|
|
label="优惠金额">¥{numeral(reduceData.SELLMASTER_OFFPRICE).format('0,0.00')}</Descriptions.Item>
|
|
<Descriptions.Item
|
|
label="客单均价">¥{numeral(reduceData.SELLMASTER_AMOUNT / data.length).format('0,0.00')}</Descriptions.Item>
|
|
<Descriptions.Item label="销售数量">{numeral(reduceData.SELLMASTER_COUNT).format('0,0')}<Text
|
|
type="secondary"> 件</Text></Descriptions.Item>
|
|
<Descriptions.Item label="设备数量">{devicesList && devicesList.length > 0 ? devicesList.length : '-'}台</Descriptions.Item>
|
|
<Descriptions.Item label="统计时间">{moment().format('YYYY-MM-DD')}</Descriptions.Item>
|
|
</Descriptions>
|
|
|
|
<Descriptions
|
|
title={<Text type="success" style={{ color: "#1890ff", fontSize: 14 }}>支付明细</Text>}
|
|
size="small" column={7}
|
|
className="commity-sale-description"
|
|
contentStyle={{ fontWeight: "bolder" }} labelStyle={{ color: "#00000073" }}
|
|
>
|
|
<Descriptions.Item
|
|
label="现金支付">{otherData?.CASH ? `¥${numeral(getMoney(otherData?.CASH)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
<Descriptions.Item
|
|
label="微信支付">{otherData?.TICKETBILL ? `¥${numeral(getMoney(otherData?.TICKETBILL)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
<Descriptions.Item label="支付宝支付">{otherData?.OTHERPAY ? `¥${numeral(getMoney(otherData?.OTHERPAY)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
<Descriptions.Item label="云闪付">{otherData?.CREDITCARD ? `¥${numeral(getMoney(otherData?.CREDITCARD)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
<Descriptions.Item label="银联记账">{otherData?.YUNSHANFU ? `¥${numeral(getMoney(otherData?.YUNSHANFU)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
<Descriptions.Item label="企业会员">{otherData?.COUPONTYPE_2010 ? `¥${numeral(getMoney(otherData?.COUPONTYPE_2010)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
<Descriptions.Item label="电子优惠券">{otherData?.COUPONTYPE_2020 ? `¥${numeral(getMoney(otherData?.COUPONTYPE_2020)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
</Descriptions>
|
|
<Descriptions size="small" className="commity-sale-description" column={7}
|
|
contentStyle={{ fontWeight: "bolder" }} labelStyle={{ color: "#00000073" }}>
|
|
<Descriptions.Item label="大巴优惠券">{otherData?.COUPONTYPE_2030 ? `¥${numeral(getMoney(otherData?.COUPONTYPE_2030)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
<Descriptions.Item label="团购餐券">{otherData?.COUPONTYPE_2040 ? `¥${numeral(getMoney(otherData?.COUPONTYPE_2040)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
<Descriptions.Item label="促销流水">{otherData?.SELLMASTERTYPE_1010 ? `¥${numeral(getMoney(otherData?.SELLMASTERTYPE_1010)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
<Descriptions.Item label="香烟销售">{otherData?.SELLMASTERTYPE_1020 ? `¥${numeral(getMoney(otherData?.SELLMASTERTYPE_1020)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
<Descriptions.Item label="在线订单">{otherData?.SELLMASTERTYPE_1030 ? `¥${numeral(getMoney(otherData?.SELLMASTERTYPE_1030)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
<Descriptions.Item label="稽核补录">{otherData?.SELLMASTERTYPE_1040 ? `¥${numeral(getMoney(otherData?.SELLMASTERTYPE_1040)).format('0,0.00')}` : '¥0.00'}</Descriptions.Item>
|
|
</Descriptions>
|
|
</div>
|
|
}
|
|
return <></>
|
|
}
|
|
}
|
|
onRow={(record) => {
|
|
return {
|
|
onClick: () => {
|
|
setCurrentRow(record)
|
|
setVisible(true)
|
|
}
|
|
}
|
|
}}
|
|
pagination={{ defaultPageSize: 10 }}
|
|
/>
|
|
|
|
</ProCard>
|
|
</ProCard>
|
|
<Modal
|
|
title={currentRow ? `${currentRow?.SERVERPART_NAME + currentRow?.SHOPNAME}销售流水明细` : '销售流水明细'}
|
|
centered
|
|
visible={visible}
|
|
onOk={() => setVisible(false)}
|
|
onCancel={() => setVisible(false)}
|
|
width={1024}
|
|
bodyStyle={{ padding: 0 }}
|
|
destroyOnClose
|
|
>
|
|
{currentRow && <FlowDetail id={currentRow?.SELLMASTER_CODE} />}
|
|
</Modal>
|
|
</PageContainer>
|
|
);
|
|
};
|
|
|
|
export default connect(({ user }: ConnectState) => ({
|
|
currentUser: user.currentUser
|
|
}))(CommoditysaleTable);
|