612 lines
29 KiB
Vue
612 lines
29 KiB
Vue
<template>
|
||
<div class="app-container">
|
||
<el-form :inline="true" :model="query" class="mb8">
|
||
<el-form-item label="账单号">
|
||
<el-input v-model="query.billNo" clearable placeholder="账单号" style="width: 180px" />
|
||
</el-form-item>
|
||
<el-form-item label="供应商">
|
||
<el-input v-model="query.supplierName" clearable placeholder="供应商" style="width: 180px" />
|
||
</el-form-item>
|
||
<el-form-item label="状态">
|
||
<el-select v-model="query.status" clearable placeholder="全部" style="width: 140px">
|
||
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" icon="Search" @click="loadList">查询</el-button>
|
||
<el-button type="primary" plain icon="Plus" @click="openCreate" v-hasPermi="['price:payBill:add']">生成账单</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<el-table v-loading="loading" :data="rows" border>
|
||
<el-table-column prop="billNo" label="账单号" min-width="170" />
|
||
<el-table-column prop="supplierName" label="供应商" min-width="140" show-overflow-tooltip />
|
||
<el-table-column prop="currency" label="币种" width="80" align="center" />
|
||
<el-table-column prop="orderCount" label="订单数" width="80" align="center" />
|
||
<el-table-column prop="totalAmount" label="我方金额" width="110" align="right" />
|
||
<el-table-column prop="paidAmount" label="已核销" width="100" align="right" />
|
||
<el-table-column prop="dueDate" label="到期日" width="120" />
|
||
<el-table-column label="来源" width="90" align="center">
|
||
<template #default="{ row }">{{ sourceText(row.sourceType) }}</template>
|
||
</el-table-column>
|
||
<el-table-column label="状态" width="90" align="center">
|
||
<template #default="{ row }">{{ statusText(row.status) }}</template>
|
||
</el-table-column>
|
||
<el-table-column prop="createTime" label="生成时间" width="170" />
|
||
<el-table-column label="操作" width="280" align="center" fixed="right">
|
||
<template #default="{ row }">
|
||
<el-button link type="primary" @click="openDetail(row)">查看</el-button>
|
||
<el-button v-if="row.status === 'DRAFT'" link type="primary" @click="submitRow(row)" v-hasPermi="['price:payBill:submit', 'price:payBill:confirm']">提交审核</el-button>
|
||
<el-button v-if="row.status === 'PENDING'" link type="primary" @click="approveRow(row)" v-hasPermi="['price:payBill:approve', 'price:payBill:confirm']">通过</el-button>
|
||
<el-button v-if="row.status === 'PENDING'" link type="warning" @click="openReject(row)" v-hasPermi="['price:payBill:approve', 'price:payBill:confirm']">驳回</el-button>
|
||
<el-button v-if="canRed(row)" link type="warning" @click="openRed(row)" v-hasPermi="['price:payBill:approve', 'price:payBill:confirm']">红字</el-button>
|
||
<el-button v-if="row.status === 'DRAFT' || row.status === 'PENDING'" link type="danger" @click="openVoid(row)" v-hasPermi="['price:payBill:void']">作废</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<pagination v-show="total > 0" :total="total" v-model:page="query.pageNum" v-model:limit="query.pageSize" @pagination="loadList" />
|
||
|
||
<el-dialog v-model="createVisible" title="生成应付账单" width="1180px" append-to-body>
|
||
<el-form label-width="90px">
|
||
<el-form-item label="选出方式">
|
||
<el-radio-group v-model="command.sourceType">
|
||
<el-radio value="ORDER">订单号</el-radio>
|
||
<el-radio value="TIME">计费日</el-radio>
|
||
<el-radio value="LADING">提单</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<el-form-item v-if="command.sourceType === 'ORDER'" label="订单号">
|
||
<el-input v-model="command.orderText" type="textarea" :rows="4" placeholder="可用逗号、空格或换行分隔" />
|
||
</el-form-item>
|
||
<el-form-item v-if="command.sourceType === 'TIME'" label="计费日" class="pay-bill-date">
|
||
<el-date-picker v-model="dateRange" type="daterange" value-format="YYYY-MM-DD" start-placeholder="开始" end-placeholder="结束" />
|
||
</el-form-item>
|
||
<el-form-item v-if="command.sourceType === 'LADING'" label="提单号">
|
||
<el-input v-model="command.ladingText" type="textarea" :rows="4" placeholder="多张提单可用逗号、空格或换行分隔" />
|
||
</el-form-item>
|
||
<el-form-item label="供应商" required>
|
||
<el-select v-model="command.supplierId" filterable placeholder="选择供应商" style="width: 280px">
|
||
<el-option v-for="item in suppliers" :key="item.supplierId" :label="item.supplierName" :value="item.supplierId" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="到期日">
|
||
<el-date-picker v-model="command.dueDate" type="date" value-format="YYYY-MM-DD" placeholder="不填则按供应商账期" style="width: 220px" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<div class="mb8">
|
||
<el-button @click="runPreview">查询订单</el-button>
|
||
<span v-if="previewRows.length" class="preview-msg">查询到 {{ previewRows.length }} 票,件数 {{ piecesTotal }},可生成 {{ preview.orders.length }} 票</span>
|
||
<span v-if="preview.message" class="preview-msg">{{ preview.message }}</span>
|
||
</div>
|
||
<el-table :data="previewRows" border size="small" max-height="360" empty-text="先查询订单">
|
||
<el-table-column prop="orderNo" label="订单号" min-width="140" show-overflow-tooltip />
|
||
<el-table-column prop="trackingNo" label="运单号" min-width="130" show-overflow-tooltip />
|
||
<el-table-column prop="ladingNo" label="提单号" min-width="120" show-overflow-tooltip />
|
||
<el-table-column prop="supplierName" label="供应商" min-width="120" show-overflow-tooltip />
|
||
<el-table-column label="目的地" min-width="140" show-overflow-tooltip>
|
||
<template #default="{ row }">{{ destText(row) }}</template>
|
||
</el-table-column>
|
||
<el-table-column prop="pieces" label="件数" width="70" align="center" />
|
||
<el-table-column prop="chargeWeight" label="计费重" width="90" align="right" />
|
||
<el-table-column prop="channelName" label="渠道" min-width="120" show-overflow-tooltip />
|
||
<el-table-column prop="productName" label="产品" min-width="120" show-overflow-tooltip />
|
||
<el-table-column prop="feeText" label="费用" min-width="180" show-overflow-tooltip />
|
||
<el-table-column prop="currency" label="币种" width="70" align="center" />
|
||
<el-table-column prop="payTotal" label="应付总额" width="100" align="right" />
|
||
<el-table-column prop="bizDate" label="计费日" width="160" />
|
||
<el-table-column label="状态" width="170" show-overflow-tooltip>
|
||
<template #default="{ row }">{{ previewStatus(row) }}</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<template #footer>
|
||
<el-button @click="createVisible = false">取消</el-button>
|
||
<el-button type="primary" :loading="saving" @click="runGenerate">生成</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<el-drawer v-model="detailVisible" :title="detailTitle" size="78%">
|
||
<template v-if="detail">
|
||
<el-descriptions :column="3" border size="small" class="mb8">
|
||
<el-descriptions-item label="供应商">{{ detail.supplierName }}</el-descriptions-item>
|
||
<el-descriptions-item label="币种">{{ detail.currency }}</el-descriptions-item>
|
||
<el-descriptions-item label="状态">{{ statusText(detail.status) }}</el-descriptions-item>
|
||
<el-descriptions-item label="我方金额">{{ detail.totalAmount }}</el-descriptions-item>
|
||
<el-descriptions-item label="对方金额">{{ detail.supplierAmount }}</el-descriptions-item>
|
||
<el-descriptions-item label="已核销">{{ detail.paidAmount || 0 }}</el-descriptions-item>
|
||
<el-descriptions-item label="不含税">{{ detail.amountNet || 0 }}</el-descriptions-item>
|
||
<el-descriptions-item label="税额">{{ detail.taxAmount || 0 }}</el-descriptions-item>
|
||
<el-descriptions-item label="汇率">{{ detail.exchangeRate || 1 }}</el-descriptions-item>
|
||
<el-descriptions-item label="本位币">{{ detail.baseAmount || 0 }}</el-descriptions-item>
|
||
<el-descriptions-item label="到期日">{{ detail.dueDate || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="订单数">{{ detail.orderCount }}</el-descriptions-item>
|
||
<el-descriptions-item label="单据">{{ detail.billKind === 'RED' ? '红字' : '蓝字' }}</el-descriptions-item>
|
||
<el-descriptions-item label="作废原因">{{ detail.voidReason || '-' }}</el-descriptions-item>
|
||
</el-descriptions>
|
||
<el-tabs>
|
||
<el-tab-pane label="费用">
|
||
<div class="mb8">
|
||
<el-button v-if="detail.status === 'DRAFT'" type="primary" @click="saveDiff" v-hasPermi="['price:payBill:add', 'price:payBill:submit']">保存对方金额</el-button>
|
||
<el-button v-if="detail.status === 'DRAFT'" @click="openFinance" v-hasPermi="['price:payBill:add', 'price:payBill:submit']">价税汇率</el-button>
|
||
<el-button @click="downloadStatement" v-hasPermi="['price:payBill:query']">导出对账单</el-button>
|
||
<el-upload v-if="detail.status === 'DRAFT'" class="inline-upload" :show-file-list="false" accept=".xlsx" :http-request="importSupplier" v-hasPermi="['price:payBill:add', 'price:payBill:submit']">
|
||
<el-button>导入对方金额</el-button>
|
||
</el-upload>
|
||
</div>
|
||
<el-table :data="detail.lines || []" border size="small" max-height="360">
|
||
<el-table-column prop="orderNo" label="订单号" min-width="130" />
|
||
<el-table-column prop="ladingNo" label="提单号" min-width="110" />
|
||
<el-table-column prop="feeName" label="费用" min-width="120" />
|
||
<el-table-column prop="amount" label="我方金额" width="100" align="right" />
|
||
<el-table-column label="对方金额" width="130">
|
||
<template #default="{ row }">
|
||
<el-input-number v-if="detail.status === 'DRAFT'" v-model="row.supplierAmount" :precision="4" :controls="false" style="width: 110px" />
|
||
<span v-else>{{ row.supplierAmount ?? '-' }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="差异" width="90" align="center">
|
||
<template #default="{ row }">{{ diffText(row.diffStatus) }}</template>
|
||
</el-table-column>
|
||
<el-table-column label="处理" width="180" align="center">
|
||
<template #default="{ row }">
|
||
<template v-if="detail.status === 'DRAFT' && row.diffStatus === 'OPEN'">
|
||
<el-button link type="primary" @click="acceptDiff(row, 'OURS')">接受我方</el-button>
|
||
<el-button link type="primary" @click="acceptDiff(row, 'THEIRS')">接受对方</el-button>
|
||
</template>
|
||
<el-button v-if="detail.status === 'DRAFT'" link type="danger" @click="removeLine(row)">剔除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
<el-tab-pane label="凭证">
|
||
<el-form v-if="detail.status !== 'VOID' && detail.status !== 'RED'" :inline="true" class="mb8">
|
||
<el-form-item label="类型">
|
||
<el-select v-model="fileForm.fileType" style="width: 120px">
|
||
<el-option label="发票" value="INVOICE" />
|
||
<el-option label="对账单" value="STATEMENT" />
|
||
<el-option label="费用通知" value="DEBIT" />
|
||
<el-option label="其他" value="OTHER" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="发票号">
|
||
<el-input v-model="fileForm.invoiceNo" style="width: 140px" />
|
||
</el-form-item>
|
||
<el-form-item label="价税合计">
|
||
<el-input-number v-model="fileForm.amount" :precision="2" :controls="false" style="width: 120px" />
|
||
</el-form-item>
|
||
<el-form-item label="税额">
|
||
<el-input-number v-model="fileForm.taxAmount" :precision="2" :controls="false" style="width: 110px" />
|
||
</el-form-item>
|
||
<el-form-item label="销方">
|
||
<el-input v-model="fileForm.sellerName" style="width: 140px" />
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-upload :action="uploadAction" :headers="uploadHeaders" :show-file-list="false" :on-success="onFileUploaded">
|
||
<el-button type="primary" v-hasPermi="['price:payVoucher:add', 'price:payBill:add']">上传</el-button>
|
||
</el-upload>
|
||
</el-form-item>
|
||
</el-form>
|
||
<el-table :data="detail.files || []" border size="small">
|
||
<el-table-column label="类型" width="100">
|
||
<template #default="{ row }">{{ fileTypeText(row.fileType) }}</template>
|
||
</el-table-column>
|
||
<el-table-column prop="invoiceNo" label="发票号" width="140" />
|
||
<el-table-column prop="amount" label="价税合计" width="110" align="right" />
|
||
<el-table-column prop="taxAmount" label="税额" width="90" align="right" />
|
||
<el-table-column prop="matchedAmount" label="已勾稽" width="90" align="right" />
|
||
<el-table-column prop="fileName" label="文件" min-width="160" show-overflow-tooltip />
|
||
<el-table-column prop="createBy" label="上传人" width="100" />
|
||
<el-table-column prop="createTime" label="时间" width="170" />
|
||
<el-table-column label="操作" width="120" align="center">
|
||
<template #default="{ row }">
|
||
<el-link :href="row.fileUrl" target="_blank" type="primary">查看</el-link>
|
||
<el-button v-if="detail.status === 'DRAFT' || detail.status === 'PENDING'" link type="danger" @click="removeFile(row)" v-hasPermi="['price:payVoucher:remove', 'price:payBill:void']">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
<el-tab-pane label="审核">
|
||
<el-table :data="detail.approvals || []" border size="small">
|
||
<el-table-column prop="createTime" label="时间" width="170" />
|
||
<el-table-column prop="operatorName" label="操作人" width="100" />
|
||
<el-table-column label="动作" width="100">
|
||
<template #default="{ row }">{{ actionText(row.action) }}</template>
|
||
</el-table-column>
|
||
<el-table-column prop="opinion" label="意见" min-width="180" />
|
||
</el-table>
|
||
</el-tab-pane>
|
||
<el-tab-pane label="操作记录">
|
||
<el-table :data="detail.logs || []" border size="small">
|
||
<el-table-column prop="createTime" label="时间" width="170" />
|
||
<el-table-column prop="operatorName" label="操作人" width="100" />
|
||
<el-table-column label="动作" width="110">
|
||
<template #default="{ row }">{{ actionText(row.operationType) }}</template>
|
||
</el-table-column>
|
||
<el-table-column label="状态" width="160">
|
||
<template #default="{ row }">{{ statusText(row.fromStatus) }} → {{ statusText(row.toStatus) }}</template>
|
||
</el-table-column>
|
||
<el-table-column prop="amountBefore" label="改前" width="90" align="right" />
|
||
<el-table-column prop="amountAfter" label="改后" width="90" align="right" />
|
||
<el-table-column prop="operationDesc" label="说明" min-width="180" show-overflow-tooltip />
|
||
</el-table>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</template>
|
||
</el-drawer>
|
||
|
||
<el-dialog v-model="rejectVisible" title="驳回应付账单" width="460px" append-to-body>
|
||
<el-input v-model="rejectOpinion" type="textarea" :rows="3" placeholder="驳回意见" />
|
||
<template #footer>
|
||
<el-button @click="rejectVisible = false">取消</el-button>
|
||
<el-button type="warning" @click="runReject">确认驳回</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<el-dialog v-model="redVisible" title="应付红字" width="460px" append-to-body>
|
||
<el-input v-model="redReason" type="textarea" :rows="3" placeholder="红字原因" />
|
||
<template #footer>
|
||
<el-button @click="redVisible = false">取消</el-button>
|
||
<el-button type="warning" @click="runRed">生成红字</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<el-dialog v-model="financeVisible" title="价税与汇率" width="460px" append-to-body>
|
||
<el-form label-width="90px">
|
||
<el-form-item label="税率">
|
||
<el-input-number v-model="financeForm.taxRate" :min="0" :max="0.9999" :precision="4" :step="0.01" :controls="false" style="width: 180px" />
|
||
</el-form-item>
|
||
<el-form-item label="汇率">
|
||
<el-input-number v-model="financeForm.exchangeRate" :min="0.000001" :precision="6" :controls="false" style="width: 180px" />
|
||
</el-form-item>
|
||
<el-form-item label="汇率日期">
|
||
<el-date-picker v-model="financeForm.rateDate" type="date" value-format="YYYY-MM-DD" style="width: 180px" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<div class="preview-msg">税率填小数,0.06 表示 6%。金额按价税合计拆成不含税和税额,再按汇率折人民币。</div>
|
||
<template #footer>
|
||
<el-button @click="financeVisible = false">取消</el-button>
|
||
<el-button type="primary" @click="saveFinance">保存</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<el-dialog v-model="voidVisible" title="作废应付账单" width="460px" append-to-body>
|
||
<el-input v-model="voidReason" type="textarea" :rows="3" placeholder="作废原因" />
|
||
<template #footer>
|
||
<el-button @click="voidVisible = false">取消</el-button>
|
||
<el-button type="danger" @click="runVoid">确认作废</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
</div>
|
||
</template>
|
||
|
||
<script setup name="PayBill">
|
||
import { getToken } from '@/utils/auth'
|
||
import useUserStore from '@/store/modules/user'
|
||
import { listSupplier } from '@/api/customersuppliermanagement/supplierinfo/supplier'
|
||
import { listPayBill, getPayBill, previewPayBill, generatePayBill, voidPayBill, submitPayBill, approvePayBill, rejectPayBill, savePayBillDiff, acceptPayBillDiff, removePayBillLine, savePayBillFile, deletePayBillFile, redPayBill, savePayFinance, exportPayStatement, importPaySupplier } from '@/api/price/payBill'
|
||
|
||
const { proxy } = getCurrentInstance()
|
||
const userStore = useUserStore()
|
||
const loading = ref(false)
|
||
const rows = ref([])
|
||
const total = ref(0)
|
||
const query = reactive({ pageNum: 1, pageSize: 10, billNo: '', supplierName: '', status: '' })
|
||
const statusOptions = [
|
||
{ label: '草稿', value: 'DRAFT' },
|
||
{ label: '待审核', value: 'PENDING' },
|
||
{ label: '已确认', value: 'CONFIRMED' },
|
||
{ label: '部分付款', value: 'PARTIAL' },
|
||
{ label: '已付清', value: 'PAID' },
|
||
{ label: '已红冲', value: 'RED' },
|
||
{ label: '已作废', value: 'VOID' }
|
||
]
|
||
const uploadAction = import.meta.env.VITE_APP_BASE_API + '/common/upload'
|
||
const uploadHeaders = { Authorization: 'Bearer ' + getToken() }
|
||
const fileForm = reactive({ fileType: 'INVOICE', invoiceNo: '', amount: null, taxAmount: 0, sellerName: '' })
|
||
const rejectVisible = ref(false)
|
||
const rejectOpinion = ref('')
|
||
const rejectId = ref(null)
|
||
const redVisible = ref(false)
|
||
const redReason = ref('')
|
||
const redId = ref(null)
|
||
const detailTitle = computed(() => detail.value?.billNo || '应付账单')
|
||
const createVisible = ref(false)
|
||
const saving = ref(false)
|
||
const suppliers = ref([])
|
||
const dateRange = ref([])
|
||
const command = reactive({ sourceType: 'ORDER', orderText: '', ladingText: '', supplierId: null, beginDate: '', endDate: '', dueDate: '' })
|
||
const financeVisible = ref(false)
|
||
const financeForm = reactive({ taxRate: 0, exchangeRate: 1, rateDate: '' })
|
||
const preview = reactive({ orders: [], occupied: [], missingNos: [], message: '' })
|
||
const detailVisible = ref(false)
|
||
const detail = ref(null)
|
||
const voidVisible = ref(false)
|
||
const voidReason = ref('')
|
||
const voidId = ref(null)
|
||
|
||
const previewRows = computed(() => [...(preview.orders || []), ...(preview.occupied || [])])
|
||
const piecesTotal = computed(() => previewRows.value.reduce((sum, item) => sum + (Number(item.pieces) || 0), 0))
|
||
|
||
function destText(row) {
|
||
const country = [row.countryName, row.countryCode].filter(Boolean).join(' ')
|
||
return [country, row.destPostcode].filter(Boolean).join(' / ') || '-'
|
||
}
|
||
|
||
function statusText(value) {
|
||
return statusOptions.find(item => item.value === value)?.label || value || '-'
|
||
}
|
||
|
||
function sourceText(value) {
|
||
return { ORDER: '订单号', TIME: '计费日', LADING: '提单' }[value] || value || '-'
|
||
}
|
||
|
||
function diffText(value) {
|
||
return { NONE: '-', OPEN: '待处理', ACCEPT_OURS: '接受我方', ACCEPT_THEIRS: '接受对方' }[value] || value || '-'
|
||
}
|
||
|
||
function fileTypeText(value) {
|
||
return { INVOICE: '发票', STATEMENT: '对账单', DEBIT: '费用通知', OTHER: '其他' }[value] || value || '-'
|
||
}
|
||
|
||
function actionText(value) {
|
||
return {
|
||
CREATE: '生成', SUBMIT: '提交审核', APPROVE: '审核通过', REJECT: '驳回', CONFIRM: '确认',
|
||
VOID: '作废', REMOVE: '剔除', DIFF: '登记差异', ACCEPT: '处理差异', FILE: '上传凭证',
|
||
FILE_DEL: '删除凭证', RED: '红字', PAY: '付款核销', TAX: '价税汇率', EXPORT: '导出对账单', REVERSE: '反核销'
|
||
}[value] || value || '-'
|
||
}
|
||
|
||
function previewStatus(row) {
|
||
if (row.unbilledCount > 0 && row.occupiedBillNo) return '部分可出 ' + row.occupiedBillNo
|
||
if (row.occupiedBillNo) return '已入账 ' + row.occupiedBillNo
|
||
return '可生成'
|
||
}
|
||
|
||
function canRed(row) {
|
||
return (row.status === 'CONFIRMED' || row.status === 'PARTIAL') && row.billKind !== 'RED' && !(Number(row.paidAmount) > 0)
|
||
}
|
||
|
||
function reloadDetail() {
|
||
if (!detail.value?.billId) return
|
||
getPayBill(detail.value.billId).then(res => { detail.value = res.data })
|
||
}
|
||
|
||
function loadList() {
|
||
loading.value = true
|
||
listPayBill(query).then(res => {
|
||
rows.value = res.rows || []
|
||
total.value = res.total || 0
|
||
}).finally(() => {
|
||
loading.value = false
|
||
})
|
||
}
|
||
|
||
function ensureSuppliers() {
|
||
if (!suppliers.value.length) {
|
||
listSupplier({ pageNum: 1, pageSize: 500 }).then(res => {
|
||
suppliers.value = res.rows || []
|
||
})
|
||
}
|
||
}
|
||
|
||
function openFinance() {
|
||
financeForm.taxRate = Number(detail.value.taxRate || 0)
|
||
financeForm.exchangeRate = Number(detail.value.exchangeRate || 1)
|
||
financeForm.rateDate = detail.value.rateDate || ''
|
||
financeVisible.value = true
|
||
}
|
||
|
||
function saveFinance() {
|
||
savePayFinance({ billId: detail.value.billId, taxRate: financeForm.taxRate, exchangeRate: financeForm.exchangeRate, rateDate: financeForm.rateDate }).then(() => {
|
||
proxy.$modal.msgSuccess('价税和汇率已保存')
|
||
financeVisible.value = false
|
||
reloadDetail()
|
||
})
|
||
}
|
||
|
||
function downloadStatement() {
|
||
exportPayStatement(detail.value.billId).then(data => {
|
||
const blob = new Blob([data])
|
||
const url = URL.createObjectURL(blob)
|
||
const link = document.createElement('a')
|
||
link.href = url
|
||
link.download = (detail.value.billNo || '对账单') + '.xlsx'
|
||
link.click()
|
||
URL.revokeObjectURL(url)
|
||
})
|
||
}
|
||
|
||
function importSupplier(option) {
|
||
importPaySupplier(detail.value.billId, option.file).then(() => {
|
||
proxy.$modal.msgSuccess('对方金额已导入')
|
||
reloadDetail()
|
||
})
|
||
}
|
||
|
||
function openCreate() {
|
||
preview.orders = []
|
||
preview.occupied = []
|
||
preview.missingNos = []
|
||
preview.message = ''
|
||
createVisible.value = true
|
||
ensureSuppliers()
|
||
}
|
||
|
||
function buildCommand() {
|
||
const data = { ...command }
|
||
if (command.sourceType === 'TIME' && dateRange.value?.length === 2) {
|
||
data.beginDate = dateRange.value[0]
|
||
data.endDate = dateRange.value[1]
|
||
}
|
||
return data
|
||
}
|
||
|
||
function runPreview() {
|
||
previewPayBill(buildCommand()).then(res => {
|
||
const data = res.data || {}
|
||
preview.orders = data.orders || []
|
||
preview.occupied = data.occupied || []
|
||
preview.missingNos = data.missingNos || []
|
||
preview.message = data.message || ''
|
||
})
|
||
}
|
||
|
||
function runGenerate() {
|
||
saving.value = true
|
||
generatePayBill(buildCommand()).then(res => {
|
||
const desc = (res.data?.logs || []).find(item => item.operationType === 'CREATE')?.operationDesc || ''
|
||
if (desc.includes('未并入')) {
|
||
proxy.$modal.msgWarning(desc)
|
||
} else {
|
||
proxy.$modal.msgSuccess('应付账单已生成')
|
||
}
|
||
createVisible.value = false
|
||
loadList()
|
||
}).finally(() => {
|
||
saving.value = false
|
||
})
|
||
}
|
||
|
||
function openDetail(row) {
|
||
getPayBill(row.billId).then(res => {
|
||
detail.value = res.data
|
||
detailVisible.value = true
|
||
})
|
||
}
|
||
|
||
function submitRow(row) {
|
||
proxy.$modal.confirm('提交这张应付账单审核?有未处理差异时不能提交。').then(() => submitPayBill(row.billId)).then(() => {
|
||
proxy.$modal.msgSuccess('已提交审核')
|
||
loadList()
|
||
}).catch(() => {})
|
||
}
|
||
|
||
function approveRow(row) {
|
||
const limit = String(userStore.id) === '1' ? '' : ',审核人不能是提交人'
|
||
proxy.$modal.confirm('审核通过?蓝字需要发票价税合计、税额和账单一致' + limit + '。').then(() => approvePayBill(row.billId)).then(() => {
|
||
proxy.$modal.msgSuccess('已审核通过')
|
||
loadList()
|
||
if (detail.value?.billId === row.billId) reloadDetail()
|
||
}).catch(() => {})
|
||
}
|
||
|
||
function openReject(row) {
|
||
rejectId.value = row.billId
|
||
rejectOpinion.value = ''
|
||
rejectVisible.value = true
|
||
}
|
||
|
||
function runReject() {
|
||
if (!rejectOpinion.value.trim()) {
|
||
proxy.$modal.msgWarning('请填写驳回意见')
|
||
return
|
||
}
|
||
rejectPayBill({ billId: rejectId.value, opinion: rejectOpinion.value.trim() }).then(() => {
|
||
proxy.$modal.msgSuccess('已驳回')
|
||
rejectVisible.value = false
|
||
loadList()
|
||
})
|
||
}
|
||
|
||
function openRed(row) {
|
||
redId.value = row.billId
|
||
redReason.value = ''
|
||
redVisible.value = true
|
||
}
|
||
|
||
function runRed() {
|
||
redPayBill({ billId: redId.value, reason: redReason.value.trim() }).then(() => {
|
||
proxy.$modal.msgSuccess('红字草稿已生成,审核通过后原费用才可以再次出账')
|
||
redVisible.value = false
|
||
loadList()
|
||
})
|
||
}
|
||
|
||
function saveDiff() {
|
||
savePayBillDiff({ billId: detail.value.billId, lines: detail.value.lines }).then(() => {
|
||
proxy.$modal.msgSuccess('对方金额已保存')
|
||
reloadDetail()
|
||
})
|
||
}
|
||
|
||
function acceptDiff(row, handleType) {
|
||
const text = handleType === 'THEIRS' ? '接受对方金额?差额会另写一条对账调整,原来的计算金额不变。' : '接受我方金额?'
|
||
proxy.$modal.confirm(text).then(() => acceptPayBillDiff({ billId: detail.value.billId, lineId: row.lineId, handleType })).then(() => {
|
||
proxy.$modal.msgSuccess('差异已处理')
|
||
reloadDetail()
|
||
}).catch(() => {})
|
||
}
|
||
|
||
function removeLine(row) {
|
||
proxy.$modal.confirm('从这张草稿剔除这条费用?剔除后它可以进入别的账单。').then(() => removePayBillLine({ billId: detail.value.billId, lineId: row.lineId })).then(() => {
|
||
proxy.$modal.msgSuccess('已剔除')
|
||
reloadDetail()
|
||
loadList()
|
||
}).catch(() => {})
|
||
}
|
||
|
||
function onFileUploaded(res) {
|
||
if (res.code !== 200) {
|
||
proxy.$modal.msgError(res.msg || '上传失败')
|
||
return
|
||
}
|
||
savePayBillFile({
|
||
billId: detail.value.billId,
|
||
fileType: fileForm.fileType,
|
||
invoiceNo: fileForm.invoiceNo,
|
||
amount: fileForm.amount,
|
||
taxAmount: fileForm.taxAmount,
|
||
sellerName: fileForm.sellerName,
|
||
fileName: res.originalFilename || res.newFileName,
|
||
fileUrl: res.url || res.fileName
|
||
}).then(() => {
|
||
proxy.$modal.msgSuccess('凭证已上传')
|
||
fileForm.fileType = 'INVOICE'
|
||
fileForm.invoiceNo = ''
|
||
fileForm.amount = null
|
||
fileForm.taxAmount = 0
|
||
fileForm.sellerName = ''
|
||
reloadDetail()
|
||
})
|
||
}
|
||
|
||
function removeFile(row) {
|
||
proxy.$modal.confirm('删除这张凭证?').then(() => deletePayBillFile(row.fileId)).then(() => {
|
||
proxy.$modal.msgSuccess('已删除')
|
||
reloadDetail()
|
||
}).catch(() => {})
|
||
}
|
||
|
||
function openVoid(row) {
|
||
voidId.value = row.billId
|
||
voidReason.value = ''
|
||
voidVisible.value = true
|
||
}
|
||
|
||
function runVoid() {
|
||
if (!voidReason.value.trim()) {
|
||
proxy.$modal.msgWarning('请填写作废原因')
|
||
return
|
||
}
|
||
voidPayBill({ billId: voidId.value, voidReason: voidReason.value.trim() }).then(() => {
|
||
proxy.$modal.msgSuccess('已作废,历史账单仍可查看')
|
||
voidVisible.value = false
|
||
loadList()
|
||
})
|
||
}
|
||
|
||
loadList()
|
||
</script>
|
||
|
||
<style scoped>
|
||
.preview-msg { margin-left: 12px; color: #909399; }
|
||
.inline-upload { display: inline-block; margin: 0 8px; vertical-align: middle; }
|
||
.mb8 { margin-bottom: 8px; }
|
||
.pay-bill-date :deep(.el-date-editor) {
|
||
width: 280px !important;
|
||
max-width: 280px;
|
||
flex: 0 0 280px;
|
||
--el-date-editor-width: 280px;
|
||
}
|
||
</style>
|