Commit fc7ee6aa authored by XieZhiXiong's avatar XieZhiXiong
parents 4034b55e a90b1bd7
......@@ -33,6 +33,7 @@ import payandSettle from './zh-CN/payandSettle'
import balance from './zh-CN/balance'
import processRuleSetting from './zh-CN/system/processRuleSetting'
import afterService from './zh-CN/afterService';
import marketingAbility from './zh-CN/marketing'
export default {
'global.siteName': '瓴犀',
......@@ -71,4 +72,5 @@ export default {
...processRuleSetting,
...afterService,
...balance,
...marketingAbility,
}
.balanceInfoName {
font-size: 14px;
line-height: 16px;
}
.wrapContainer {
background-color: #FAFBFC;
padding: 12px;
margin-top: 8px;
font-size: 14px;
.item {
margin-bottom: 16px;
&-title {
color: #909399;
}
&-value {
color: #252D37;
margin-left: 8px;
}
}
}
.payChannel {
margin-top: 8px;
.title {
margin-bottom: 12px;
}
.panChanneList {
display: flex;
flex-direction: row;
align-items: center;
.item {
margin-right: 16px;
}
}
}
import { getSettleAccountsPlatformSettlementChannelList } from '@/services/SettleV2Api';
import { Modal, Radio } from 'antd';
import React, { useState, useEffect, useCallback } from 'react';
import styles from './index.less';
import PayItem from './payItem';
import alipay_icon from '@/assets/icons/alipay_icon.png'
import balance_icon from '@/assets/icons/balance_icon.png'
import unionpay_icon from '@/assets/icons/unionpay_icon.png'
import wechat_icon from '@/assets/icons/wechat_icon.png'
import quicklypay_icon from '@/assets/icons/quicklypay_icon.png'
interface Iprops {
visible: boolean,
onConfirm: (params: { payChannel: number }) => void,
onClose: () => void
confirmLoading: boolean,
/** 结算方信息 */
balanceInfo: {
/** 结算方名字 */
name: string,
/** 结算金额 */
amount: number,
payMethods: string,
}
}
const ICON_ENUM = {
11: wechat_icon,
12: alipay_icon,
13: quicklypay_icon,
14: unionpay_icon,
15: balance_icon
}
const OtherPayModal: React.FC<Iprops> = (props: Iprops) => {
const {visible, balanceInfo, onConfirm, onClose, confirmLoading} = props;
const [payChannelOptions, setPayChannelOptions] = useState<{label: string, value: number}[]>([]);
const [activeChannel, setActiveChannel] = useState<number | null>(null);
const handleClose = () => {
onClose?.()
}
const list = [
{
title: '结算方',
value: balanceInfo?.name
},
{
title: '结算金额',
value: balanceInfo.amount
},
{
title: '支付方式',
value: balanceInfo.payMethods
}
]
const getPayChannel = useCallback(async () => {
const { data, code } = await getSettleAccountsPlatformSettlementChannelList();
if (code === 1000) {
setPayChannelOptions(data.map((_item) => ({
label: _item.payChannelName,
value: _item.payChannel,
icon: ICON_ENUM[_item.payChannel] || ''
})))
}
}, [])
useEffect(() => {
if (!visible) {
return;
}
getPayChannel()
}, [visible])
const handleRadioChange = (item: { value: number }) => {
setActiveChannel(item.value)
}
const handleOnOk = () => {
onConfirm?.({
payChannel: activeChannel
})
}
return (
<Modal
width={548}
title="付款"
onCancel={handleClose}
visible={visible}
okText={"确定付款"}
onOk={handleOnOk}
confirmLoading={confirmLoading}
>
<div className={styles.wrapContainer}>
{
list.map((_item) => {
return (
<div className={styles.item} key={_item.title}>
<span className={styles['item-title']}>{_item.title}</span>
<span className={styles['item-value']}>{_item.value}</span>
</div>
)
})
}
{/* <Radio.Group options={payChannelOptions} onChange={handleRadioChange} value={activeChannel} /> */}
</div>
<div className={styles.payChannel}>
<div className={styles.title}>支付渠道</div>
<div className={styles.panChanneList}>
{
payChannelOptions.map((_item) => {
return (
<div className={styles.item} key={_item.value}>
<PayItem {..._item} isActive={_item.value === activeChannel} onClick={handleRadioChange} />
</div>
)
})
}
</div>
</div>
</Modal>
)
}
export default OtherPayModal;
.container {
display: flex;
flex-direction: row;
align-items: center;
font-size: 12px;
padding: 8px 16px;
background-color: #F5F6F7;
border-radius: 8px;
border: 1px solid #F5F6F7;
.img {
width: 16px;
height: 16px;
margin-right: 8px;
}
}
.active {
border: 1px solid #00A98F;
color: #00A98F;
background: rgba(0,169,143,0.04);
}
import { useMemo } from 'react';
import React from 'react';
import styles from './payItem.less';
import classnames from 'classnames';
interface Iprops {
icon?: string,
label: string,
value: number,
isActive: boolean,
onClick?: (data: {value: number}) => void
}
const PayItem: React.FC<Iprops> = (props: Iprops) => {
const { icon, label, value, isActive, onClick } = props;
const handleClick = () => {
onClick?.({ value })
}
return (
<div
className={classnames(styles.container, {
[styles.active]: isActive
})}
onClick={handleClick}
>
<img className={styles.img} src={icon} />
<div>{label}</div>
</div>
)
}
export default PayItem;
import EyePreview from '@/components/EyePreview';
// import StatusTag from '../components/StatusTag';
// import { TO_BE_RECONCILED, TO_BE_PAY, TO_BE_COLLECTED, COMPLETED, PRODUCT_NOTICE_SETTLEMENT_DETAIL, LOGISTICS_DETAIL, ORDER_DETAIL, CONTRACT_FUND_BILL } from '../common/constants';
import { priceFormat } from '@/utils/numberFomat'
import StatusTag from '@/components/StatusTag';
import { STATUS_TEXT } from '@/constants/balance';
import React, { useMemo, useState } from 'react';
// import { payStatus } from '../common';
import moment from 'moment';
import { COMPLETED, CONTRACT_FUND_BILL, LOGISTICS_DETAIL, ORDER_DETAIL, PRODUCT_NOTICE_SETTLEMENT_DETAIL, TO_BE_COLLECTED, TO_BE_PAY, TO_BE_RECONCILED, IS_UNIVERSAL_PAY } from '@/pages/balance/common/constants';
import { useCallback } from 'react';
import { GetSettleAccountsMemberSettlementPagePayableSettlementResponseDetail } from '@/services/SettleV2Api';
import { ColumnsType } from 'antd/lib/table';
const format = "YYYY-MM-DD HH:mm:ss"
const URL_MAP = {
[PRODUCT_NOTICE_SETTLEMENT_DETAIL]: "productNoticeSettlementDetail",
[LOGISTICS_DETAIL]: "logisticsDetail",
[ORDER_DETAIL]: "orderDetail",
[CONTRACT_FUND_BILL]: '',
}
const STATUS_COLOR = ["default", "warning", "primary", "danger", "success"];
type ModalsType = {
/** 查看付款 */
viewPay: boolean,
/** 查看通联支付 */
viewUniversalPay: boolean,
/** 手动结算 */
manualSettlement: boolean,
/** 上传付款凭证 */
uploadPayVoucher: boolean,
/** 通联支付付款 */
universalPay: boolean
}
function useHandleSettlementList() {
const [itemInfo, setItemInfo] = useState<GetSettleAccountsMemberSettlementPagePayableSettlementResponseDetail | null>(null)
const [modals, setModals] = useState<ModalsType>({
viewPay: false,
viewUniversalPay: false,
manualSettlement: false,
uploadPayVoucher: false,
universalPay: false
})
const handleOpen = useCallback((key: keyof ModalsType) => {
setModals({
...modals,
[key]: true
})
}, [])
const handleClose = useCallback((key: keyof ModalsType) => {
setModals({
...modals,
[key]: false
})
}, [])
const handleAction = (record: GetSettleAccountsMemberSettlementPagePayableSettlementResponseDetail, key: keyof ModalsType) => {
setItemInfo(record);
console.log("key", key);
handleOpen(key);
/** 通联支付 */
// if (record.payWay === 2 && record.status === COMPLETED) {
// handleOpen('viewUniversalPay');
// return;
// }
// const KEY_MAP = {
// [TO_BE_RECONCILED]: 'confirmReconciliation',
// [TO_BE_COLLECTED]: 'confirmPay',
// [COMPLETED]: 'viewPay'
// }
// handleOpen(KEY_MAP[record.status])
}
const columns: ColumnsType<GetSettleAccountsMemberSettlementPagePayableSettlementResponseDetail> = [
{
title: '结算单号',
dataIndex: 'settlementNo',
render: (text, record) => {
const prefix = `/memberCenter/balance/accountsPayable/settlementList/` ;
const url = URL_MAP[record.orderType];
let fullUrl = `${prefix}${url}?id=${record.id}`;
if(record.orderType === CONTRACT_FUND_BILL) {
fullUrl = `/memberCenter/contract/funds/bill/details?applyId=${record.orderId}`;
}
return (
<EyePreview url={fullUrl} >
{record.settlementNo}
</EyePreview>
)
}
},
{ title: '结算方式', dataIndex: 'settlementWayName' },
{ title: '结算方', dataIndex: 'settlementName'},
{
title: '结算单据类型',
dataIndex: 'orderTypeName',
filters: [
{
text: '生产通知单',
value: 1,
},
{
text: '物流单',
value: 2,
},
{
text: '订单',
value: 3,
},
{
text: '请款单',
value: 6
}
],
// onFilter: (value: number, record: any) => record.orderType === value,
},
{
title: '结算金额',
dataIndex: 'amount',
sorter: (a, b) => a.amount - b.amount,
render: (text, record) => {
return (
<div>{`¥${priceFormat(record.amount)}`}</div>
)
}
},
{
title: '总单数',
dataIndex: 'totalCount',
sorter: (a, b) => a.totalCount - b.totalCount,
},
{
title: '结算时间',
dataIndex: 'settlementTime',
sorter: (a, b) => moment(a.settlementTime, format).valueOf() - moment(b.settlementTime, format).valueOf(),
},
// {title: '结算日期', dataIndex: 'settlementDate'},
{ title: '预计付款日期', dataIndex: 'prePayTime' },
{ title: '实际付款日期', dataIndex: 'payTime' },
{
title: '结算状态', dataIndex: 'status',
// filters: payStatus,
// onFilter: (value: number, record: any) => record.status == value,
render: (text: string, record: any) => {
return (
<StatusTag type={STATUS_COLOR[record.status] as 'success'} title={STATUS_TEXT[record.status]} />
)
}
},
{
title: '支付方式',
dataIndex: 'payWayName',
// filters: [
// {
// text: '线上支付',
// value: 1,
// },
// {
// text: '线下转账线上确认',
// value: 2,
// },
// {
// text: '授信',
// value: 3,
// },
// {
// text: '货到付款',
// value: 4
// }
// ],
// onFilter: (value: number, record: any) => record.payWay === value,
},
{
title: '操作',
render: (text: string, record: any) => {
const isUniversalPay = record.payWay === IS_UNIVERSAL_PAY;
// 待对账的时候可以手动结算
if (record.status === TO_BE_RECONCILED) {
if (record.orderType !== CONTRACT_FUND_BILL) {
return <a onClick={() => handleAction(record, "manualSettlement")}>手动结算</a>
}
return null
}
if (record.status === TO_BE_PAY) {
return (
<a onClick={() => handleAction(record, isUniversalPay ? 'universalPay' : 'uploadPayVoucher')}>
付款
</a>
)
}
return <a onClick={() => handleAction(record, isUniversalPay ? 'viewUniversalPay' : 'viewPay')}>查看付款凭证</a>
}
}
]
const cacheItemInfo = useMemo(() => itemInfo, [itemInfo])
return {
columns,
handleOpen,
handleClose,
itemInfo: cacheItemInfo,
modals,
}
}
export default useHandleSettlementList
/*
* @Author: Bill
* @Date: 2020-10-20 11:04:07
* @Description: 应付账款结算
*/
import React, { useRef, useCallback, useEffect, useState } from 'react';
import React, { useRef, useCallback, useEffect, useState, useMemo } from 'react';
import { useIntl } from 'umi'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import { Button, Card, DatePicker, Modal } from 'antd';
......@@ -17,12 +11,14 @@ import { useAsyncSelect } from '@/formSchema/effects/useAsyncSelect';
import { schema } from './schema';
import { Moment } from 'moment';
import { fetchOptions } from '../../common'
import useFetchColumns from '../../hooks/useFetchColumns';
import UploadVoucherModal from '../../components/UploadVoucherModal';
import Voucher from '../../components/Voucher';
import useSetSearchValueInTable from '@/hooks/useSetSearchValueInTable';
import { getSettleAccountsCommonGetSettlementOrderType, getSettleAccountsCommonGetSettlementStatus, getSettleAccountsMemberSettlementGetPayablePayProve, getSettleAccountsMemberSettlementPagePayableSettlement, GetSettleAccountsMemberSettlementPagePayableSettlementRequest, postSettleAccountsMemberSettlementPay } from '@/services/SettleV2Api';
import { getSettleAccountsCommonGetSettlementOrderType, getSettleAccountsCommonGetSettlementStatus, getSettleAccountsMemberSettlementGetPayablePayProve, getSettleAccountsMemberSettlementPagePayableSettlement, GetSettleAccountsMemberSettlementPagePayableSettlementRequest, postSettleAccountsMemberSettlementCommunicationPay, postSettleAccountsMemberSettlementPay } from '@/services/SettleV2Api';
import { postReportSettlementMemberManualSettlement } from '@/services/ReportV2Api';
import OtherPayModal from '../components/OtherPayModal';
import useHandleSettlementList from './hooks/useHandleSettlementList';
import ViewUniversalPay from '../../components/ViewUniversalPay';
const { onFieldValueChange$ } = FormEffectHooks
const { RangePicker } = DatePicker;
......@@ -37,16 +33,31 @@ interface SearchParams {
status?: number,
current: number,
pageSize: number,
}
const SettlementList = () => {
const ref = useRef<any>({})
const intl = useIntl();
const { searchData, formatInitialValue, clear } = useSetSearchValueInTable();
const { columns, manualStatus, payModalVisible, balanceInfo, payModalOnCancel, viewModalonCancel, viewVisible, payVoucherInfo } = useFetchColumns("payable");
const [files, setFiles] = useState<any>([]);
const [uploadSubmitLoading, setUploadSubmitLoading] = useState<boolean>()
const [uploadSubmitLoading, setUploadSubmitLoading] = useState<boolean>();
const [universalPayLoading, setUniversalPayLoading] = useState<boolean>(false)
const { itemInfo, modals, handleClose, columns } = useHandleSettlementList();
const [files, setFiles] = useState([]);
const universalPayInfo1 = useMemo(() => ({
name: itemInfo?.settlementName,
amount: itemInfo?.amount,
statusName: itemInfo?.statusName,
payWayName: '通联支付',
settlementDate: itemInfo?.settlementDate
}), [itemInfo])
const universalPayInfo = useMemo(() => ({
name: itemInfo?.payName,
amount: itemInfo?.amount,
payMethods: '通联支付',
}), [itemInfo])
/**
* 分页查询
......@@ -62,6 +73,7 @@ const SettlementList = () => {
status: searchParams.status || '0',
orderType: searchParams.orderType || '0',
}
const { data } = await getSettleAccountsMemberSettlementPagePayableSettlement(postData);
return data
}, [searchData])
......@@ -70,17 +82,22 @@ const SettlementList = () => {
* 手动结算
*/
const fetchManualSettlement = useCallback(async (id: number) => {
const { code, data } = await postReportSettlementMemberManualSettlement({ id })
if (code === 1000) {
const { code, data } = await postReportSettlementMemberManualSettlement({id})
if(code === 1000) {
handleClose("manualSettlement")
formActions.submit();
}
}, [])
useEffect(() => {
if (manualStatus !== null) {
fetchManualSettlement(manualStatus)
if (itemInfo !== null && modals['manualSettlement']) {
fetchManualSettlement(itemInfo.id)
return
}
}, [manualStatus])
if (itemInfo !== null && modals['viewPay']) {
fetchVouchers(itemInfo.id);
}
}, [itemInfo, modals])
const fetchVouchers = useCallback(async (id: number) => {
const { code, data } = await getSettleAccountsMemberSettlementGetPayablePayProve({ id: id.toString() })
......@@ -89,26 +106,38 @@ const SettlementList = () => {
}
}, [])
useEffect(() => {
if (payVoucherInfo !== null) {
fetchVouchers(payVoucherInfo.id);
}
}, [payVoucherInfo])
/**
* 上传凭证
* @param params
*/
const handleUploadVoucher = async (params: { fileList: { name: string, proveUrl: string }[] }) => {
setUploadSubmitLoading(true)
const { data, code } = await postSettleAccountsMemberSettlementPay({ id: balanceInfo.id, proveList: params.fileList })
const { data, code } = await postSettleAccountsMemberSettlementPay({id: itemInfo?.id!, proveList: params.fileList})
setUploadSubmitLoading(false)
if (code === 1000) {
payModalOnCancel();
if(code === 1000) {
// handlePayModalClose();
handleClose('uploadPayVoucher')
formActions.submit();
}
}
/** 通联支付, 付款 */
const handleUniversalPay = async (params: {payChannel: number}) => {
try {
setUniversalPayLoading(true)
const { data, code } = await postSettleAccountsMemberSettlementCommunicationPay({
id: itemInfo.id,
payChannelType: params.payChannel,
})
if (code === 1000) {
// handlePayModalClose();
handleClose('universalPay')
}
} finally {
setUniversalPayLoading(true)
}
}
/**
* 搜索
*/
......@@ -157,18 +186,37 @@ const SettlementList = () => {
/>
</Card>
<UploadVoucherModal
visible={payModalVisible}
visible={modals.uploadPayVoucher}
// id={balanceInfo?.id}
roleId={balanceInfo?.roleId}
settlementId={balanceInfo?.settlementId}
roleId={itemInfo?.roleId}
settlementId={itemInfo?.memberId}
handleUpload={handleUploadVoucher}
onCancel={payModalOnCancel}
onCancel={() => handleClose('uploadPayVoucher')}
confirmLoading={uploadSubmitLoading}
/>
<Modal width={548} title={intl.formatMessage({ id: 'balance.accountsPayable.settlementList.modal.title' })} onCancel={viewModalonCancel} visible={viewVisible} footer={null}>
<Modal
width={548}
title={intl.formatMessage({ id: 'balance.accountsPayable.settlementList.modal.title' })}
onCancel={() => handleClose('viewPay')}
visible={modals['viewPay']}
footer={null}
>
{/* <WrapVoucher id={props.id} type={props.type} /> */}
<Voucher files={files} />
</Modal>
<OtherPayModal
visible={modals.universalPay}
balanceInfo={universalPayInfo}
onClose={() => handleClose('universalPay')}
onConfirm={handleUniversalPay}
confirmLoading={universalPayLoading}
/>
<ViewUniversalPay
visible={modals['viewUniversalPay']}
balanceInfo={universalPayInfo1}
onClose={() => handleClose('viewUniversalPay')}
onOk={() => handleClose('viewUniversalPay')}
/>
</PageHeaderWrapper>
)
}
......
/*
* @Author: Bill
* @Date: 2020-10-20 11:04:07
* @Description: 应付账款结算
*/
import React, { useRef, useState } from 'react';
import { useIntl } from 'umi'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import { Card, Button, DatePicker, Tag, Badge, Drawer } from 'antd';
import { Card, Button, DatePicker, Tag, Badge, Drawer, message } from 'antd';
import NiceForm from '@/components/NiceForm';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { createFormActions } from '@formily/antd';
......@@ -15,7 +9,7 @@ import { StandardTable } from 'god';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { useAsyncSelect } from '@/formSchema/effects/useAsyncSelect';
import { schema } from './schema';
import InvoiceCreate from '../../components/InvoiceCreate'
// import InvoiceCreate from '../../components/InvoiceCreate'
// import StatusTag from '../../components/StatusTag';
import StatusTag, { STATUS_TYPE } from '@/components/StatusTag'
import { fetchOptions } from '../../common';
......@@ -24,8 +18,17 @@ import { numFormat, priceFormat } from '@/utils/numberFomat';
import {
getSettleAccountsCommonGetPayStatus,
getSettleAccountsCommonGetReceiptInvoiceStatus,
getSettleAccountsMemberSettlementPageReceiptInvoice
getSettleAccountsMemberSettlementGetInvoiceProveDetail,
GetSettleAccountsMemberSettlementGetInvoiceProveDetailResponse,
getSettleAccountsMemberSettlementGetReturnInvoiceProveDetail,
GetSettleAccountsMemberSettlementGetReturnInvoiceProveDetailResponse,
getSettleAccountsMemberSettlementPageReceiptInvoice,
GetSettleAccountsMemberSettlementPageReceiptInvoiceResponseDetail,
postSettleAccountsMemberSettlementInvoiceByReturn,
postSettleAccountsMemberSettlementInvoiceProve
} from '@/services/SettleV2Api';
// import { ColumnType } from 'antd/lib/table';
import InvoiceDrawerInfo from '../../components/InvoiceCreate/invoiceDrawerInfo'
const RangePicker = DatePicker.RangePicker;
const formActions = createFormActions();
......@@ -34,15 +37,15 @@ const SettlementList = () => {
const intl = useIntl();
const ref = useRef<any>({});
const [visible, setVisible] = useState(false);
const [activeData, setActiveData] = useState({});
const [activeData, setActiveData] = useState<GetSettleAccountsMemberSettlementPageReceiptInvoiceResponseDetail>(null);
const { searchData, formatInitialValue } = useSetSearchValueInTable();
const [invoiceInfo, setInvoiceInfo] = useState<any>(null)
/**
* 获取开票管理列表
* @param params
*/
const fetchListData = async (params) => {
// /settle/accounts/member/settlement/pageReceiptInvoice
const searchParams = {
...params,
invoiceStatus: params?.invoiceStatus || 2,
......@@ -54,8 +57,8 @@ const SettlementList = () => {
}
/**
* 搜索
*/
* 搜索
*/
const handleSearch = (values) => {
const format = 'YYYY-MM-DD'
const payStartTime = values.payStartTime?.format(format);
......@@ -65,33 +68,105 @@ const SettlementList = () => {
ref.current.reload({ ...values, payStartTime, payEndTime, orderStartTime, orderEndTime });
}
const handleShow = (record) => {
document.body.parentNode.style.overflowY = "hidden";
const handleShow = async (record: GetSettleAccountsMemberSettlementPageReceiptInvoiceResponseDetail) => {
(document.body.parentNode as HTMLBodyElement).style.overflowY = "hidden";
setActiveData(record)
const hide = message.loading('正在加载中', 0);
/** 退货类型 */
const service = record.settlementOrderType === 5
? getSettleAccountsMemberSettlementGetReturnInvoiceProveDetail
: getSettleAccountsMemberSettlementGetInvoiceProveDetail
const { code, data, message: msg } = await service({ id: record.id.toString() });
hide()
if (code !== 1000) {
message.error(msg);
return
}
if (record.settlementOrderType === 5) {
if ((data as GetSettleAccountsMemberSettlementGetReturnInvoiceProveDetailResponse).length === 0) {
message.error("无发票信息");
return
}
setVisible(true)
setInvoiceInfo(data);
return;
}
setVisible(true)
setActiveData({
id: record.id,
type: record.invoiceStatus,
settlementOrderType: record.settlementOrderType || 5,
// payRoleId: record.payRoleId,
// payMemberId: record.payMemberId
})
setInvoiceInfo([(data as GetSettleAccountsMemberSettlementGetInvoiceProveDetailResponse)]);
}
const handleOnCancel = () => {
document.body.parentNode.style.overflowY = "auto";
(document.body.parentNode as HTMLBodyElement).style.overflowY = "auto";
setVisible(false)
setActiveData({})
setActiveData(null)
}
const handleForm = async (value) => {
const keys = Object.keys(value);
if(keys.length === 0) {
message.error({
content: '请添加发票信息'
})
return;
}
let res = {}
keys.forEach((item) => {
const array = value[item];
res[item] = array
})
/** 退货类型 */
if (activeData.settlementOrderType === 5) {
const postDataList = {
receiptInvoiceId: activeData.id,
addList: invoiceInfo.map((_item, key) => {
const { kindName, typeName, ...rest } = _item;
return {
...rest,
// TODO, 修改
kind: kindName == '增值税普通发票' ? 1 : 2,
type: typeName == '企业' ? 1 : 2,
proveList: res[`list-${key}`]
}
})
}
const { data, code, message: msg } = await postSettleAccountsMemberSettlementInvoiceByReturn(postDataList);
if (code !== 1000) {
message.error(msg);
return
}
formActions.submit();
setVisible(false)
return;
}
/** 普通发票开具 */
const { kindName, typeName, ...rest } = invoiceInfo[0]
const defaultPostData = {
receiptInvoiceId: activeData.id,
...rest,
kind: kindName == '增值税普通发票' ? 1 : 2,
type: typeName == '企业' ? 1 : 2,
proveList: res[`list-0`]
}
const { data, code, message: msg } = await postSettleAccountsMemberSettlementInvoiceProve(defaultPostData);
if (code === 1000) {
setVisible(false)
formActions.submit();
}
message.error(msg);
}
const columns = [
{
title: intl.formatMessage({ id: 'balance.accountsReceivable.invoice.columns.orderNo' }),
dataIndex: 'orderNo',
render: (text, record: any) => {
render: (text, record) => {
const typeNum = record.settlementOrderType % STATUS_TYPE.length;
return (
<div>
<p>{record.orderNo}</p>
<StatusTag title={record.settlementOrderTypeName} type={STATUS_TYPE[record.settlementOrderType] as "success"} />
<StatusTag title={record.settlementOrderTypeName} type={STATUS_TYPE[typeNum] as "success"} />
</div>
)
}
......@@ -191,7 +266,7 @@ const SettlementList = () => {
tableProps={{
rowKey: 'id',
}}
columns={columns}
columns={columns as any}
currentRef={ref}
fetchTableData={(params: any) => fetchListData(params)}
controlRender={
......@@ -230,14 +305,14 @@ const SettlementList = () => {
}
/>
</Card>
<InvoiceCreate
{...activeData as any}
title={intl.formatMessage({ id: 'balance.accountsReceivable.invoice.invoiceCreate.title' })}
width={800}
<InvoiceDrawerInfo
mode={activeData?.invoiceStatus === 0 ? 'edit' : 'view'}
visible={visible}
invoiceInfoData={invoiceInfo}
onCancel={handleOnCancel}
refresh={() => formActions.submit()}
onSubmit={handleForm}
/>
</PageHeaderWrapper>
)
}
......
import EyePreview from '@/components/EyePreview';
// import StatusTag from '../components/StatusTag';
// import { TO_BE_RECONCILED, TO_BE_PAY, TO_BE_COLLECTED, COMPLETED, PRODUCT_NOTICE_SETTLEMENT_DETAIL, LOGISTICS_DETAIL, ORDER_DETAIL, CONTRACT_FUND_BILL } from '../common/constants';
import { priceFormat } from '@/utils/numberFomat'
import StatusTag from '@/components/StatusTag';
import { STATUS_TEXT } from '@/constants/balance';
import React, { useMemo, useState } from 'react';
// import { payStatus } from '../common';
import moment from 'moment';
import { COMPLETED, CONTRACT_FUND_BILL, LOGISTICS_DETAIL, ORDER_DETAIL, PRODUCT_NOTICE_SETTLEMENT_DETAIL, TO_BE_COLLECTED, TO_BE_RECONCILED } from '@/pages/balance/common/constants';
import { useCallback } from 'react';
import { GetSettleAccountsMemberSettlementPageReceivableSettlementResponseDetail } from '@/services/SettleV2Api';
import { ColumnsType } from 'antd/lib/table';
const format = "YYYY-MM-DD HH:mm:ss"
const URL_MAP = {
[PRODUCT_NOTICE_SETTLEMENT_DETAIL]: "productNoticeSettlementDetail",
[LOGISTICS_DETAIL]: "logisticsDetail",
[ORDER_DETAIL]: "orderDetail",
[CONTRACT_FUND_BILL]: '',
}
const KEY_MAP_TEXT = {
[TO_BE_RECONCILED]: '确认对账完成',
[TO_BE_COLLECTED]: '确认付款凭证',
[COMPLETED]: '查看付款凭证'
}
const STATUS_COLOR = ["default", "warning", "primary", "danger", "success"];
type ModalsType = {
/**确认对账 */
confirmReconciliation: boolean,
/** 确认付款凭证 */
confirmPay: boolean,
/** 查看付款 */
viewPay: boolean,
/** 查看通联支付 */
viewUniversalPay: boolean
}
function useHandleSettlementList() {
const [itemInfo, setItemInfo] = useState<GetSettleAccountsMemberSettlementPageReceivableSettlementResponseDetail>([])
const [modals, setModals] = useState<ModalsType>({
confirmReconciliation: false,
confirmPay: false,
viewPay: false,
viewUniversalPay: false,
})
const handleOpen = useCallback((key: keyof ModalsType) => {
setModals({
...modals,
[key]: true
})
}, [])
const handleClose = useCallback((key: keyof ModalsType) => {
setModals({
...modals,
[key]: false
})
}, [])
const handleAction = (record: GetSettleAccountsMemberSettlementPageReceivableSettlementResponseDetail) => {
setItemInfo(record);
/** 通联支付 */
if (record.payWay === 2 && record.status === COMPLETED) {
handleOpen('viewUniversalPay');
return;
}
const KEY_MAP = {
[TO_BE_RECONCILED]: 'confirmReconciliation',
[TO_BE_COLLECTED]: 'confirmPay',
[COMPLETED]: 'viewPay'
}
handleOpen(KEY_MAP[record.status])
}
const columns: ColumnsType<GetSettleAccountsMemberSettlementPageReceivableSettlementResponseDetail> = [
{
title: '结算单号',
dataIndex: 'settlementNo',
render: (text, record) => {
const prefix = '/memberCenter/balance/accountsReceivable/settlementList/';
const url = URL_MAP[record.orderType];
let fullUrl = `${prefix}${url}?id=${record.id}`;
if(record.orderType === CONTRACT_FUND_BILL) {
fullUrl = `/memberCenter/contract/funds/bill/details?applyId=${record.orderId}`;
}
return (
<EyePreview url={fullUrl} >
{record.settlementNo}
</EyePreview>
)
}
},
{ title: '结算方式', dataIndex: 'settlementWayName' },
{ title: '付款方', dataIndex: 'payName'},
{
title: '结算单据类型',
dataIndex: 'orderTypeName',
filters: [
{
text: '生产通知单',
value: 1,
},
{
text: '物流单',
value: 2,
},
{
text: '订单',
value: 3,
},
{
text: '请款单',
value: 6
}
],
onFilter: (value: number, record: any) => record.orderType === value,
},
{
title: '结算金额',
dataIndex: 'amount',
sorter: (a, b) => a.amount - b.amount,
render: (text, record) => {
return (
<div>{`¥${priceFormat(record.amount)}`}</div>
)
}
},
{
title: '总单数',
dataIndex: 'totalCount',
sorter: (a, b) => a.totalCount - b.totalCount,
},
{
title: '结算时间',
dataIndex: 'settlementTime',
sorter: (a, b) => moment(a.settlementTime, format).valueOf() - moment(b.settlementTime, format).valueOf(),
},
{ title: '预计付款日期', dataIndex: 'prePayTime' },
{ title: '实际付款日期', dataIndex: 'payTime' },
{
title: '结算状态', dataIndex: 'status',
render: (text: string, record: GetSettleAccountsMemberSettlementPageReceivableSettlementResponseDetail) => {
return (
<StatusTag type={STATUS_COLOR[record.status] as 'success'} title={STATUS_TEXT[record.status]} />
)
}
},
{
title: '支付方式',
dataIndex: 'payWayName',
},
{
title: '操作',
render: (text: string, record: GetSettleAccountsMemberSettlementPageReceivableSettlementResponseDetail) => {
const keyText = KEY_MAP_TEXT[record.status];
return (<a onClick={() => handleAction(record)}>{keyText}</a>)
}
}
];
const cacheItemInfo = useMemo(() => itemInfo, [itemInfo])
return {
columns,
handleOpen,
handleClose,
itemInfo: cacheItemInfo,
modals,
}
}
export default useHandleSettlementList
/*
* @Author: Bill
* @Date: 2020-10-20 11:04:07
* @Description: 应付账款结算
*/
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useIntl } from 'umi'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
......@@ -17,13 +11,13 @@ import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilte
import { useAsyncSelect } from '@/formSchema/effects/useAsyncSelect';
import { schema } from './schema';
import { fetchOptions } from '../../common';
import useFetchColumns from '../../hooks/useFetchColumns'
import Voucher from '../../components/Voucher';
import ConfirmAccount from '../../components/ConfirmAccount';
import { usePageStatus } from '@/hooks/usePageStatus';
import useSetSearchValueInTable from '@/hooks/useSetSearchValueInTable';
import { Moment } from 'moment';
import { getSettleAccountsCommonGetSettlementOrderType, getSettleAccountsCommonGetSettlementStatus, getSettleAccountsMemberSettlementGetReceivablePayProve, getSettleAccountsMemberSettlementPageReceivableSettlement, postSettleAccountsMemberSettlementConfirmAccountComplete, postSettleAccountsMemberSettlementConfirmPayProve } from '@/services/SettleV2Api';
import useHandleSettlementList from './hooks/useHandleSettlementList';
import ViewUniversalPay from '../../components/ViewUniversalPay';
const { RangePicker } = DatePicker;
......@@ -46,7 +40,20 @@ const SettlementList = () => {
const intl = useIntl();
const { searchData, formatInitialValue, clear } = useSetSearchValueInTable();
const [files, setFiles] = useState<any>([]);
const { columns, confirmPayInfo, confirmPayVisible, reconciliationInfo, reconciliationVisible, viewVisible, payVoucherInfo, viewModalonCancel, confirmPayOnCancel, reconciliationOnCancel } = useFetchColumns("receiveable")
const {
columns,
modals,
itemInfo,
handleClose,
handleOpen
} = useHandleSettlementList()
const universalPayInfo = useMemo(() => ({
name: itemInfo.settlementName,
amount: itemInfo.amount,
statusName: itemInfo.statusName,
payWayName: '通联支付',
settlementDate: itemInfo.settlementDate
}), [itemInfo])
const fetchListData = async (params: requestDataType) => {
const searchParams = {
......@@ -68,7 +75,8 @@ const SettlementList = () => {
const handleConfirm = async (params: { id: number }) => {
const { code, data } = await postSettleAccountsMemberSettlementConfirmAccountComplete({ settlementId: params.id });
if (code === 1000) {
reconciliationOnCancel();
// reconciliationOnCancel();
handleClose("confirmReconciliation")
formActions.submit();
}
}
......@@ -79,7 +87,8 @@ const SettlementList = () => {
const handleConfirmPayStatus = async (params: { status: 0 | 1, id: number }) => {
const { code } = await postSettleAccountsMemberSettlementConfirmPayProve({ id: params.id, status: params.status });
if (code) {
confirmPayOnCancel();
// confirmPayOnCancel();
handleClose('confirmPay')
formActions.submit();
}
}
......@@ -91,10 +100,10 @@ const SettlementList = () => {
}, [])
useEffect(() => {
if (payVoucherInfo !== null) {
fetchVouchers(payVoucherInfo.id);
if (itemInfo !== null && (itemInfo.status === 4 || itemInfo.status === 3)) {
fetchVouchers(itemInfo.id);
}
}, [payVoucherInfo])
}, [itemInfo])
/**
* 搜索
......@@ -146,32 +155,32 @@ const SettlementList = () => {
<Modal
width={400}
title={intl.formatMessage({ id: 'balance.accountsReceivable.settlementList.modal.1.title' })}
visible={reconciliationVisible}
onCancel={reconciliationOnCancel}
onOk={() => handleConfirm({ id: reconciliationInfo?.id })}
visible={modals['confirmReconciliation']}
onCancel={() => handleClose('confirmReconciliation')}
onOk={() => handleConfirm({ id: itemInfo?.id})}
>
<ConfirmAccount settlementDate={reconciliationInfo?.settlementDate} payName={reconciliationInfo?.payName} />
<ConfirmAccount settlementDate={itemInfo?.settlementDate} payName={itemInfo?.payName} />
</Modal>
<Modal width={548} title={intl.formatMessage({ id: 'balance.accountsReceivable.settlementList.modal.2.title' })} onCancel={viewModalonCancel} visible={viewVisible} footer={null}>
<Modal width={548} title={intl.formatMessage({ id: 'balance.accountsReceivable.settlementList.modal.2.title' })} onCancel={() => handleClose('viewPay')} visible={modals['viewPay']} footer={null}>
<Voucher files={files} />
</Modal>
<Modal
width={548}
title={intl.formatMessage({ id: 'balance.accountsReceivable.settlementList.modal.3.title' })}
onCancel={confirmPayOnCancel}
visible={confirmPayVisible}
onCancel={() => handleClose('confirmPay')}
visible={modals['confirmPay']}
footer={(
<Space>
<Button onClick={confirmPayOnCancel}>{intl.formatMessage({ id: 'balance.accountsReceivable.settlementList.modal.3.button.1' })}</Button>
<Button onClick={() => handleClose('confirmPay')}>{intl.formatMessage({ id: 'balance.accountsReceivable.settlementList.modal.3.button.1' })}</Button>
<Button
danger
onClick={() => handleConfirmPayStatus({ status: 0, id: confirmPayInfo.id })}
onClick={() => handleConfirmPayStatus({status: 0, id: itemInfo.id})}
>
{intl.formatMessage({ id: 'balance.accountsReceivable.settlementList.modal.3.button.2' })}
</Button>
<Button
type={"primary"}
onClick={() => handleConfirmPayStatus({ status: 1, id: confirmPayInfo.id })}
onClick={() => handleConfirmPayStatus({status: 1, id: itemInfo.id})}
>
{intl.formatMessage({ id: 'balance.accountsReceivable.settlementList.modal.3.button.3' })}
</Button>
......@@ -180,6 +189,12 @@ const SettlementList = () => {
>
<Voucher files={files} />
</Modal>
<ViewUniversalPay
visible={modals['viewUniversalPay']}
balanceInfo={universalPayInfo}
onClose={() => handleClose('viewUniversalPay')}
onOk={() => handleClose('viewUniversalPay')}
/>
</PageHeaderWrapper>
)
}
......
......@@ -67,3 +67,10 @@ export const ORDER_DETAIL = 3
* 结算单据类型-合同请款单
*/
export const CONTRACT_FUND_BILL = 6
/**
* 应付账款管理, 应收账款管理, 平台代收账款管理列表 支付方式
* 1. 线下支付, 2通联支付
*/
export const IS_UNIVERSAL_PAY = 2
.container {
display: flex;
flex-direction: row;
// align-items: center;
:global {
.ant-form-item {
margin-bottom: 12px;
}
.ant-input,
.ant-picker {
background-color: #F5F6F7;
border-color: #F5F6F7;
&:focus {
border-color: #F5F6F7;
box-shadow: none;
}
}
.ant-input-focused,
.ant-picker-focused {
border-color: #F5F6F7;
box-shadow: none;
}
}
.remove {
background-color: #F5F6F7;
width: 32px;
height: 32px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-left: 12px;
cursor: pointer;
}
}
.add {
width: 100%;
background-color: #F5F6F7;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
font-size: 12px;
color: #5C626A;
padding: 8px;
cursor: pointer;
.addText {
margin-left: 8px;
}
}
import React from 'react'
import {
SchemaField,
SchemaMarkupField as Field
} from '@formily/antd'
import { ArrayList } from '@formily/react-shared-components'
import { toArr, isFn, FormPath } from '@formily/shared'
import styles from './arrayList.less';
import { MinusOutlined, PlusOutlined, PlusSquareOutlined } from '@ant-design/icons'
const ArrayCustom = props => {
const { value, schema, className, editable, path, mutators } = props
const xComponentProps = props.props['x-component-props'];
const onAdd = () => {
const items = Array.isArray(schema.items)
? schema.items[schema.items.length - 1]
: schema.items
mutators.push(items.getEmptyValue())
}
return (
<ArrayList
value={value}
minItems={schema.minItems}
maxItems={schema.maxItems}
editable={editable}
>
{xComponentProps?.header || null}
{toArr(value).map((item, index) => {
return (
<div className={styles.container} key={index}>
<SchemaField path={FormPath.parse(path).concat(index)} />
<div className={styles.remove} onClick={() => mutators.remove(index)}>
<MinusOutlined />
</div>
</div>
)
})}
<div className={styles.add} onClick={onAdd}>
<PlusOutlined size={12} />
<span className={styles.addText}>添加</span>
</div>
</ArrayList>
)
}
ArrayCustom.isFieldComponent = true
export default ArrayCustom;
import InvoiceDrawer from './InvoiceDrawer'
export default InvoiceDrawer
import React from 'react';
import { Row, Col } from 'antd';
// import { InvoiceInfoProps } from '../../common/type';
import styles from './invoiceInfo.less';
import { getIntl } from 'umi';
const intl = getIntl()
interface Iprops {
props: {
'x-component-props': {
infos: {
typeName: string,
kindName: string,
invoiceTitle: string,
taxNo: string,
bankOfDeposit: string,
account: string,
address: string,
tel: string,
originalProveList?: {
number: number,
invoiceDate: string,
invoiceAmount: string,
remark: string
}[]
}
}
}
}
const infoList = [
{ title: intl.formatMessage({ id: 'balance.components.invoiceCreate.invoiceInfo.infoList.typeName' }), dataIndex: 'typeName' },
{ title: intl.formatMessage({ id: 'balance.components.invoiceCreate.invoiceInfo.infoList.kindName' }), dataIndex: 'kindName' },
{ title: intl.formatMessage({ id: 'balance.components.invoiceCreate.invoiceInfo.infoList.invoiceTitle' }), dataIndex: 'invoiceTitle' },
{ title: intl.formatMessage({ id: 'balance.components.invoiceCreate.invoiceInfo.infoList.taxNo' }), dataIndex: 'taxNo' },
{ title: intl.formatMessage({ id: 'balance.components.invoiceCreate.invoiceInfo.infoList.bankOfDeposit' }), dataIndex: 'bankOfDeposit' },
{ title: intl.formatMessage({ id: 'balance.components.invoiceCreate.invoiceInfo.infoList.account' }), dataIndex: 'account' },
{ title: intl.formatMessage({ id: 'balance.components.invoiceCreate.invoiceInfo.infoList.address' }), dataIndex: 'address' },
{ title: intl.formatMessage({ id: 'balance.components.invoiceCreate.invoiceInfo.infoList.tel' }), dataIndex: 'tel' }
]
const InvoiceInfo: React.FC<Iprops> & { isVirtualFieldComponent: boolean } = (props) => {
console.log(props);
const xComponentProps = props.props['x-component-props']
const { infos } = xComponentProps;
return (
<>
{
infoList.map((item) => {
return (
<Row className={styles.row} key={item.dataIndex}>
<Col span={3} className={styles.label}>{item.title}</Col>
<Col span={16}>{infos && infos[item.dataIndex]}</Col>
</Row>
)
})
}
{
infos?.originalProveList && (
<div className={styles.originalInvoice}>
<p className={styles.title}>原订单发票信息</p>
<div className={styles.header}>
<div className={styles.defaultWidth}>原订单发票号码</div>
<div className={styles.defaultWidth}>原订单开票日期</div>
<div className={styles.defaultWidth}>原订单开票金额</div>
<div className={styles.specialWidth}>备注</div>
</div>
<div className={styles.list}>
{
infos.originalProveList.map((_item, key) => {
return (
<div className={styles.item} key={key}>
<div className={styles.defaultWidth}>{_item.number}</div>
<div className={styles.defaultWidth}>{_item.invoiceDate}</div>
<div className={styles.defaultWidth}>{_item.invoiceAmount}</div>
<div className={styles.specialWidth}>{_item.remark}</div>
</div>
)
})
}
</div>
</div>
)
}
</>
)
}
InvoiceInfo.isVirtualFieldComponent = true
export default InvoiceInfo
.header {
display: flex;
flex-direction: row;
align-items: center;
color: #91959B;
margin-bottom: 8px;
.header-item {
width: 128px;
margin-right: 20px;
}
}
.required {
color: #F25767;
}
import {
createFormActions,
FormMegaLayout,
SchemaForm,
SchemaMarkupField as Field
} from '@formily/antd'
import { Button, Drawer } from 'antd';
import React, { useEffect, useState } from 'react';
import ArrayList from './arrayList';
import { Input, DatePicker } from '@formily/antd-components';
import styles from './invoiceDrawerInfo.less';
import InvoiceInfo from './invoice'
import { getIntl } from 'umi'
const intl = getIntl();
const formActions = createFormActions();
interface Iprops {
visible: boolean,
onCancel: () => void,
onSubmit?: (values: any) => void,
mode?: 'edit' | 'view',
invoiceInfoData: any
}
type ProveListType = {
number: string,
invoiceDate: string,
invoiceAmount: number
remark: string,
}
const InvoiceDrawerInfo: React.FC<Iprops> = (props: Iprops) => {
const { visible, onCancel, invoiceInfoData, onSubmit, mode } = props;
const [initialValue, setInitialValue] = useState<{ [key: string]: ProveListType}>({});
const handleCancel = () => {
onCancel?.()
}
const renderFooter = () => {
return (
<div style={{textAlign: 'right'}}>
<Button onClick={handleCancel} style={{ marginRight: 8 }}>
{intl.formatMessage({ id: 'balance.components.invoiceCreate.invoiceDrawer.renderFooter.button.1' })}
</Button>
<Button onClick={() => formActions.submit()} type="primary">
{intl.formatMessage({ id: 'balance.components.invoiceCreate.invoiceDrawer.renderFooter.button.2' })}
</Button>
</div>
)
}
const handleSubmit = (values) => {
console.log(values)
onSubmit?.(values)
}
useEffect(() => {
if (mode === 'view' && invoiceInfoData) {
const data = {};
invoiceInfoData?.forEach((_item, index) => {
const { proveList } = _item;
data[`list-${index}`] = proveList
})
setInitialValue(data);
}
}, [mode, invoiceInfoData])
return (
<Drawer
visible={visible}
width={800}
title="开具发票"
onClose={handleCancel}
footer={renderFooter()}
>
<SchemaForm
value={initialValue}
onSubmit={handleSubmit}
components={{ ArrayCustom: ArrayList, Input: Input, DatePicker, InvoiceInfo }}
actions={formActions}
editable={mode === 'edit'}
>
{
invoiceInfoData?.map((_item, key) => {
return (
<div key={key} style={{display: 'flex', flexDirection: 'column'}}>
<Field
type="object"
x-component='InvoiceInfo'
x-component-props={
{
infos: _item
}
}
/>
<Field
name={`list-${key}`}
type="array"
x-component="ArrayCustom"
x-component-props={{
header: (
<div className={styles.header}>
<div className={styles['header-item']}>
发票管理<span className={styles.required}>*</span>
</div>
<div className={styles['header-item']}>
开票日期
<span className={styles.required}>*</span>
</div>
<div className={styles['header-item']}>
开票金额(元)
<span className={styles.required}>*</span>
</div>
<div className={styles['header-item']}>备注</div>
</div>
)
}}
>
<Field type="object">
<FormMegaLayout inline>
<Field
name="number"
x-component="Input"
x-component-props={{
style: {
width: '128px'
}
}}
x-rules={
[
{required: true, message: '请填写发票号码'}
]
}
/>
<Field
name="invoiceDate"
x-component="DatePicker"
x-rules={
[
{required: true, message: '请填写开票日期'}
]
}
/>
<Field
name="invoiceAmount"
x-component="Input"
x-component-props={{
style: {
width: '128px'
}
}}
x-rules={
[
{required: true, message: '请填写开票金额(元)'}
]
}
/>
<Field
name="remark"
x-component="Input"
x-component-props={{
style: {
width: '268px'
}
}}
/>
</FormMegaLayout>
</Field>
</Field>
</div>
)
})
}
</SchemaForm>
</Drawer>
)
}
export default InvoiceDrawerInfo
......@@ -3,7 +3,7 @@
@margin-top: 50px;
.row {
margin-bottom: @margin-lg;
margin-bottom: @margin-lg;
font-size: @font-size;
.label {
......@@ -24,4 +24,40 @@
width: 140px;
margin-right: @margin-md;
}
}
\ No newline at end of file
}
.originalInvoice {
display: flex;
flex-direction: column;
margin-top: 8px;
.title {
font-size: 12px;
}
.header {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 8px;
}
.list {
display: flex;
flex-direction: column;
.item {
display: flex;
flex-direction: row;
align-items: center;
}
}
.defaultWidth {
width: 128px;
margin-right: 8px;
}
.specialWidth {
flex: 1;
}
}
/*
* @Author: bILL
* @Date: 2020-10-20 17:39:16
* @Description: 新增会员结算结算方式
*/
import React, { useEffect, useState } from 'react';
import { useIntl, getIntl } from 'umi'
......
.balanceInfoName {
font-size: 14px;
line-height: 16px;
}
.wrapContainer {
background-color: #FAFBFC;
border-radius: 8px;
padding: 12px 12px 4px 12px;
margin-top: 8px;
font-size: 14px;
.item {
margin-bottom: 8px;
&-title {
color: #909399;
}
&-value {
color: #252D37;
margin-left: 16px;
}
}
}
import { Modal } from 'antd';
import React from 'react';
import styles from './index.less';
interface Iprops {
visible: boolean,
balanceInfo: {
/** 结算方名字 */
name: string,
amount: number,
/** 付款状态, 成功失败 */
/** 支付状态 */
statusName: string,
/** 支付时间 */
settlementDate: string,
/** 支付方式 */
payWayName: string,
},
onOk: () => void,
onClose: () => void
}
/** 查看通联支付付款 */
const ViewUniversalPay: React.FC<Iprops> = (props: Iprops) => {
const { visible, balanceInfo, onClose, onOk } = props;
const handleClose = () => {
onClose?.()
}
const handleOnOk = () => {
onOk?.();
}
const list = [
{
title: '结算金额',
value: balanceInfo?.amount
},
{
title: '付款方式',
value: balanceInfo?.payWayName
},
{
title: '付款时间',
value: balanceInfo?.settlementDate
},
{
title: '付款状态',
value: balanceInfo?.statusName
}
]
return (
<Modal
width={548}
title="查看付款"
onCancel={handleClose}
visible={visible}
onOk={handleOnOk}
>
<div className={styles.balanceInfoName}>结算方: {balanceInfo?.name}</div>
<div className={styles.wrapContainer}>
{
list.map((_item) => {
return (
<div className={styles.item} key={_item.title}>
<span className={styles['item-title']}>{_item.title}</span>
<span className={styles['item-value']}>{_item.value}</span>
</div>
)
})
}
</div>
</Modal>
)
}
export default ViewUniversalPay
......@@ -235,7 +235,7 @@ function useFetchColumns(mode: 'payable' | 'receiveable') {
}
return <a onClick={() => handleViewPayModal({ id: record.id })}>{intl.formatMessage({ id: 'balance.hooks.useFetchColumns.columns.operation.button.3' })}</a>
}
// 待收张狂结算
// 待收账款结算
if (record.status === TO_BE_RECONCILED) {
return <a onClick={() => handleReconciledComfirm({ id: record.id, payName: record.payName, settlementDate: record.settlementDate })}>{intl.formatMessage({ id: 'balance.hooks.useFetchColumns.columns.operation.button.4' })}</a>
}
......
import { getSettleAccountsPlatformSettlementGetReceivablePayProve } from "@/services/SettleV2Api";
import { useCallback, useState } from "react";
type FileType = {
name: string
/**
* 凭证地址
*/
proveUrl: string
}
type ConfirmPayInfoType = {
id: number,
/** 支付状态 */
statusName: string,
/** 支付时间 */
settlementDate: string,
/** 结算金额 */
amount: number
/** 结算方 */
name: string,
/** 1. 线下支付, 2.通联支付 */
payWay: 1 | 2,
/** 支付方式 */
payWayName: string,
}
/** 确认付款凭证 */
function useConfirmPayInfo() {
const [payFiles, setPayFiles] = useState<FileType[]>([]);
const [visible, setVisible] = useState<boolean>(false);
const [confirmPayInfo, setConfirmPayInfo] = useState<ConfirmPayInfoType | null>(null)
const fetchVouchers = useCallback(async (params: {id: number}) => {
const { code, data } = await getSettleAccountsPlatformSettlementGetReceivablePayProve({id: params.id.toString()})
if (code === 1000) {
setPayFiles(data);
}
}, [])
const handleOpen = (params: ConfirmPayInfoType) => {
setConfirmPayInfo(params)
fetchVouchers({id: params.id}).then(() => {
setVisible(true)
})
}
const handleClose = () => {
setVisible(false)
}
return {
payFiles,
confirmPayInfo,
confirmPayVisible: visible,
handleConfirmCompletePaymentStatus: handleOpen,
confirmPayOnCancel: handleClose,
}
}
export default useConfirmPayInfo
import { useState, useEffect } from 'react';
type ReconciliationInfoType = {
/** 结算id */
id: number,
/** 结算时间 */
settlementDate: string,
/** 付款方名字 */
payName: string
}
/** 确认对账完成 */
function useConfirmReconciliation() {
const [visible, setVisible] = useState<boolean>(false);
const [reconciliationInfo, setReconciliationInfo] = useState<ReconciliationInfoType | null>(null)
const handleReconciliationOpen = (params: ReconciliationInfoType) => {
setReconciliationInfo(params)
setVisible(true)
}
const handleReconciliationClose = () => {
setVisible(false);
}
return {
reconciliationModalVisible: visible,
handleReconciliationClose,
handleReconciliationOpen,
reconciliationInfo
}
}
export default useConfirmReconciliation
import { getSettleAccountsPlatformSettlementGetReceivablePayProve } from '@/services/SettleV2Api';
import { useState, useEffect, useCallback } from 'react'
type RecordType = {
id: number
}
type PayInfoType = {
id: number,
/** 支付状态 */
statusName: string,
/** 支付时间 */
settlementDate: string,
/** 结算金额 */
amount: number
/** 结算方 */
name: string,
/** 1. 线下支付, 2.通联支付 */
payWay: 1 | 2,
/** 支付方式 */
payWayName: string,
}
/** 查看付款凭证 */
function useViewPayInfo() {
const [visible, setVisible] = useState<boolean>(false);
const [files, setFiles] = useState<any>([]);
const [payInfo, setPayInfo] = useState<PayInfoType | null>(null)
const fetchVouchers = useCallback(async (params: {id: number}) => {
const { code, data } = await getSettleAccountsPlatformSettlementGetReceivablePayProve({id: params.id.toString()})
if (code === 1000) {
setFiles(data);
}
}, [])
const handleOpen = (params: PayInfoType) => {
setPayInfo(params)
if (params.payWay === 1) {
fetchVouchers({id: params.id}).then(() => {
setVisible(true)
})
return;
}
setVisible(true)
}
const handleClose = () => {
setVisible(false)
}
return {
files,
payInfo,
viewVisible: visible,
viewModalonCancel: handleClose,
handleViewPayModal: handleOpen
}
}
export default useViewPayInfo;
/*
* @Author: your name
* @Date: 2020-10-20 09:37:53
* @Description: 平台代收账款结算
*/
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useIntl } from 'umi'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
......@@ -28,6 +22,10 @@ import { STATUS_TEXT } from '@/constants/balance';
import { numFormat, priceFormat } from '@/utils/numberFomat';
import useSetSearchValueInTable from '@/hooks/useSetSearchValueInTable';
import { getSettleAccountsCommonGetSettlementStatus, getSettleAccountsPlatformSettlementGetReceivablePayProve, getSettleAccountsPlatformSettlementPageReceivableSettlement, GetSettleAccountsPlatformSettlementPageReceivableSettlementRequest, postSettleAccountsPlatformSettlementConfirmAccountComplete, postSettleAccountsPlatformSettlementConfirmPayProve } from '@/services/SettleV2Api';
import useConfirmReconciliation from './hooks/useConfirmReconciliation';
import useViewPayInfo from './hooks/useViewPayInfo';
import useConfirmPayInfo from './hooks/useConfirmPayInfo';
import ViewUniversalPay from '../../components/ViewUniversalPay';
const formActions = createFormActions();
const { RangePicker } = DatePicker;
......@@ -38,21 +36,10 @@ const PLATFORM_BENEFICIARY = 3;
const AccountReceivable = () => {
const intl = useIntl();
const ref = useRef<any>({})
const {
confirmPayInfo,
confirmPayVisible,
reconciliationInfo,
reconciliationVisible,
viewVisible,
payVoucherInfo,
viewModalonCancel,
confirmPayOnCancel,
reconciliationOnCancel,
handleReconciledComfirm,
handleComfirmCompletePaymentStatus,
handleViewPayModal
} = useFetchColumns("receiveable");
const [files, setFiles] = useState([]);
const { reconciliationInfo, reconciliationModalVisible, handleReconciliationOpen, handleReconciliationClose } = useConfirmReconciliation();
const { files, viewVisible, payInfo, viewModalonCancel, handleViewPayModal } = useViewPayInfo();
const { confirmPayInfo, payFiles, handleConfirmCompletePaymentStatus, confirmPayOnCancel, confirmPayVisible } = useConfirmPayInfo();
// const [files, setFiles] = useState([]);
const { searchData, formatInitialValue, clear } = useSetSearchValueInTable();
const columns = [
......@@ -89,15 +76,17 @@ const AccountReceivable = () => {
{
title: intl.formatMessage({id: 'balance.platformSettlement.accountReceivable.columns.operation'}),
render: (text, record) => {
// 待收张狂结算
// 待收账款结算
if (record.status === TO_BE_RECONCILED) {
return <a onClick={() => handleReconciledComfirm({ id: record.id, payName: intl.formatMessage({id: 'balance.platformSettlement.accountReceivable.columns.operation.button.1.payName'}), settlementDate: record.settlementDate})}>{intl.formatMessage({id: 'balance.platformSettlement.accountReceivable.columns.operation.button.1'})}</a>
return <a onClick={() => handleReconciliationOpen({ id: record.id, payName: intl.formatMessage({id: 'balance.platformSettlement.accountReceivable.columns.operation.button.1.payName'}), settlementDate: record.settlementDate})}>
{intl.formatMessage({id: 'balance.platformSettlement.accountReceivable.columns.operation.button.1'})}
</a>
}
if (record.status === TO_BE_COLLECTED) {
return <a onClick={() => handleComfirmCompletePaymentStatus({id: record.id})}>{intl.formatMessage({id: 'balance.platformSettlement.accountReceivable.columns.operation.button.2'})}</a>
return <a onClick={() => handleConfirmCompletePaymentStatus(record)}>{intl.formatMessage({id: 'balance.platformSettlement.accountReceivable.columns.operation.button.2'})}</a>
}
if (record.status === COMPLETED) {
return <a onClick={() => handleViewPayModal({id: record.id})}>{intl.formatMessage({id: 'balance.platformSettlement.accountReceivable.columns.operation.button.3'})}</a>
return <a onClick={() => handleViewPayModal(record)}>{intl.formatMessage({id: 'balance.platformSettlement.accountReceivable.columns.operation.button.3'})}</a>
}
}
}
......@@ -124,14 +113,15 @@ const AccountReceivable = () => {
const handleConfirm = async (params: {id: number}) => {
const { code } = await postSettleAccountsPlatformSettlementConfirmAccountComplete({settlementId: params.id})
if(code === 1000) {
reconciliationOnCancel();
// reconciliationOnCancel();
handleReconciliationClose();
formActions.submit();
}
}
/**
* 确认付款凭证
*/
* 确认付款凭证
*/
const handleConfirmPayStatus = async (params: { status: 0 | 1, id: number }) => {
const { code } = await postSettleAccountsPlatformSettlementConfirmPayProve({id: params.id, status: params.status});
if (code) {
......@@ -140,18 +130,6 @@ const AccountReceivable = () => {
}
}
const fetchVouchers = useCallback(async (id: number) => {
const { code, data } = await getSettleAccountsPlatformSettlementGetReceivablePayProve({id: id.toString()})
if (code === 1000) {
setFiles(data);
}
}, [])
useEffect(() => {
if (payVoucherInfo !== null) {
fetchVouchers(payVoucherInfo.id);
}
}, [payVoucherInfo])
/**
* 搜索
......@@ -199,15 +177,12 @@ const AccountReceivable = () => {
<Modal
width={400}
title={intl.formatMessage({id: 'balance.platformSettlement.accountReceivable.modal.1.title'})}
visible={reconciliationVisible}
onCancel={reconciliationOnCancel}
visible={reconciliationModalVisible}
onCancel={handleReconciliationClose}
onOk={() => handleConfirm({ id: reconciliationInfo?.id})}
>
<ConfirmAccount settlementDate={reconciliationInfo?.settlementDate} payName={reconciliationInfo?.payName} />
</Modal>
<Modal width={548} title={intl.formatMessage({id: 'balance.platformSettlement.accountReceivable.modal.2.title'})} onCancel={viewModalonCancel} visible={viewVisible} footer={null}>
<Voucher files={files} />
</Modal>
<Modal
width={548}
title={intl.formatMessage({id: 'balance.platformSettlement.accountReceivable.modal.3.title'})}
......@@ -231,6 +206,24 @@ const AccountReceivable = () => {
</Space>
)}
>
<Voucher files={payFiles} />
</Modal>
{/* 通联支付付款凭证 */}
<ViewUniversalPay
visible={viewVisible && payInfo.payWay === 2}
balanceInfo={confirmPayInfo}
onOk={viewModalonCancel}
onClose={viewModalonCancel}
/>
<Modal
width={548}
title="查看付款凭证"
onCancel={viewModalonCancel}
visible={viewVisible && payInfo.payWay === 1}
footer={null}
>
<Voucher files={files} />
</Modal>
</PageHeaderWrapper>
......
......@@ -26,11 +26,13 @@ import { fetchOptions } from '../../common';
import {
getSettleAccountsCommonGetStrategySettlementOrderType,
getSettleAccountsPlatformConfigGetMemberSettlementStrategyDetail,
getSettleAccountsPlatformSettlementTypeList,
postSettleAccountsPlatformConfigAddMemberSettlementStrategy,
postSettleAccountsPlatformConfigUpdateMemberSettlementStrategy
} from '@/services/SettleV2Api';
import { getMemberManageLowerPageBynamerole, getMemberManageRoleSubList, getMemberManageUpperPage } from '@/services/MemberV2Api';
import { getManageRuleConfigurationList } from '@/services/ManageV2Api';
import { getOrderPlatformSettlementTypeList } from '@/services/OrderNewV2Api';
const formActions = createFormActions();
......@@ -163,6 +165,7 @@ const MemberSettleAdd: React.FC = () => {
settlementWay: value.settlementWay.active,
settlementDays: value.settlementWay.otherValues[0],
settlementDate: value.settlementWay.otherValues[1],
settlementPaymentType: value.settlementPaymentType,
}
const serviceActions = isAdd
? postSettleAccountsPlatformConfigAddMemberSettlementStrategy
......@@ -223,7 +226,8 @@ const MemberSettleAdd: React.FC = () => {
settlementWay: {
active: res.data.settlementWay,
otherValues: [res.data.settlementDays, res.data.settlementDate],
}
},
settlementPaymentType: res.data.settlementOrderType.toString(),
})
const list = res.data.memberList.map((item) => ({
...item,
......@@ -241,7 +245,15 @@ const MemberSettleAdd: React.FC = () => {
}
getInfo();
}
}, [id])
}, [])
const fetchPaymentType = async () => {
const { data, code } = await getSettleAccountsPlatformSettlementTypeList();
if (code === 1000) {
return data.map((_item) => ({value: _item.methodCode, label: _item.methodName}))
}
return []
}
return (
<PageHeaderWrapper
......@@ -270,6 +282,10 @@ const MemberSettleAdd: React.FC = () => {
useAsyncSelect(
"settlementOrderType",
fetchOptions(getSettleAccountsCommonGetStrategySettlementOrderType)
),
useAsyncSelect(
"settlementPaymentType",
fetchPaymentType
)
}}
/>
......
......@@ -114,6 +114,14 @@ export const addSchema = {
'x-rules': [
{ required: true, message: intl.formatMessage({ id: 'balance.settleRules.memberSettle.info.schema.addSchema.basicTab.settlementOrderType.message' }) },
]
},
settlementPaymentType: {
type: 'string',
enum: [],
title: '结算支付方式',
'x-rules': [
{required: true, message: '请填写结算支付方式'},
]
}
},
}
......
......@@ -246,7 +246,7 @@ export const GeneralEffect = (int, data) => {
return [
{
col: [
{ label: `${intl.formatMessage({ id: 'marketingAbility.theNumberOfClusters'})}`, extra: `${data.assembleNum} {intl.formatMessage({ id: 'marketingAbility.ren' })}` },
{ label: `${intl.formatMessage({ id: 'marketingAbility.theNumberOfClusters'})}`, extra: `${data.assembleNum} ${intl.formatMessage({ id: 'marketingAbility.ren' })}` },
{ label: `${intl.formatMessage({ id: 'marketingAbility.activityDescription'})}`, extra: data.describe },
]
},
......
import { useIntl } from 'umi';
import { getIntl } from 'umi';
import React, { useEffect, useState } from 'react';
import { Row, Col, Space, Image } from 'antd';
import style from './index.less';
......@@ -26,7 +26,7 @@ const PIC_MAP = {
3: IMG_LEVEL3,
4: IMG_LEVEL4,
};
const intl = getIntl();
const ActivityUserLayout: React.FC<ActivityUserLayoutProps> = (props: any) => {
const { title, isFlag, dataScoure, allUsers } = props;
const [data, setData] = useState<any>({});
......
import { useIntl } from 'umi';
import React, { useEffect, useMemo, useState } from 'react';
import { Button, message, Table, Form, FormInstance } from 'antd';
import { Columns } from './columns';
......@@ -11,6 +10,7 @@ import { remindLayout, RemindLayoutProps } from '@/pages/transaction/marketingAb
import CouponsListLayout from '@/pages/transaction/marketingAbility/components/couponsListLayout';
import { number } from 'yargs';
import { postMarketingMerchantActivityGetFilterSkuId } from '@/services/MarketingV2Api';
import { getIntl } from 'umi';
type optionProps = {
/** key */
......@@ -40,7 +40,7 @@ interface ProductListProps {
}
const ProductListLayout: React.FC<ProductListProps> = (props: any) => {
const intl = useIntl();
const intl = getIntl();
const { activityId, form, focus$, shopIdList, fieldApi, getActivityDefinedBO, filterSkuId, itrue } = props;
const [value, setValue] = useState<number>(1);
const [productVisible, setProductVisible] = useState<boolean>(false);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment