发票开出

szh-new
sunzehua 2 months ago
parent 0e7c21532a
commit facdf8f055

@ -522,21 +522,21 @@ export const columns: BasicColumn[] = [
title: '装货港', title: '装货港',
align: 'center', align: 'center',
width: 180, width: 180,
dataIndex: 'portload', dataIndex: 'portLoad',
customCell: sharedOnCell, customCell: sharedOnCell,
}, },
{ {
title: '卸货港', title: '卸货港',
align: 'center', align: 'center',
width: 180, width: 180,
dataIndex: 'portdischarge', dataIndex: 'portDischarge',
customCell: sharedOnCell, customCell: sharedOnCell,
}, },
{ {
title: '卸货港国家', title: '卸货港国家',
align: 'center', align: 'center',
width: 180, width: 180,
dataIndex: 'portdischargeCountry', dataIndex: 'portDischargeCountry',
customCell: sharedOnCell, customCell: sharedOnCell,
}, },
{ {

@ -227,7 +227,7 @@ export const feeColumns: BasicColumn[] = [
}, },
{ {
title: '申请金额', title: '申请金额',
dataIndex: 'amount', dataIndex: 'applyAmount',
width: 80, width: 80,
}, },
{ {

@ -584,7 +584,7 @@ export const feeColumns: BasicColumn[] = [
}, },
{ {
title: '申请金额', title: '申请金额',
dataIndex: 'orderAmount', dataIndex: 'applyAmount',
width: 80, width: 80,
}, },
{ {

@ -260,8 +260,11 @@ function changeApply() {
exchangeArr.push(item) exchangeArr.push(item)
} }
}) })
if (exchangeArr.length > 0) { const filteredItems = exchangeArr.filter((item, index, self) =>
const promises = exchangeArr.map(item => { index === self.findIndex((t) => t.currency === item.currency)
);
if (filteredItems.length > 0) {
const promises = filteredItems.map(item => {
return new Promise((resolve) => { return new Promise((resolve) => {
const data = { const data = {
currencyFrom: 'RMB', currencyFrom: 'RMB',
@ -278,7 +281,7 @@ function changeApply() {
exchangeFlag.value = true exchangeFlag.value = true
}); });
} }
if (exchangeArr.length == 0) { if (filteredItems.length == 0) {
const arr = getSelectRowsFee() const arr = getSelectRowsFee()
let total = 0 let total = 0
arr.forEach(item => { arr.forEach(item => {

@ -169,3 +169,17 @@ export function FreeInvoiceGetFees(parameter) {
data: parameter, data: parameter,
}) })
} }
export function FreeInvoiceSave(parameter) {
return request({
url: '/feeApi/FreeInvoice/Save',
method: 'post',
data: parameter,
})
}
export function GetCurrencies(parameter) {
return request({
url: '/feeApi/FreeInvoice/GetCurrencies',
method: 'post',
data: parameter,
})
}

@ -713,7 +713,7 @@ export const feeColumnsDetail: BasicColumn[] = [
}, },
{ {
title: '申请金额', title: '申请金额',
dataIndex: 'orderAmount', dataIndex: 'applyAmount',
width: 80, width: 80,
}, },
{ {
@ -748,12 +748,12 @@ export const feeColumnsDetail: BasicColumn[] = [
}, },
{ {
title: '装货港', title: '装货港',
dataIndex: 'saleName', dataIndex: 'saleName2',
width: 80, width: 80,
}, },
{ {
title: '卸货港', title: '卸货港',
dataIndex: 'saleName', dataIndex: 'saleName1',
width: 80, width: 80,
}, },
] ]

@ -3,7 +3,7 @@
<a-modal width="1600px" @cancel="open = false" :visible="open" title="添加发票申请明细" :footer="null"> <a-modal width="1600px" @cancel="open = false" :visible="open" title="添加发票申请明细" :footer="null">
<div style="padding-bottom:5px ;"> <div style="padding-bottom:5px ;">
<div> <div>
<BasicTable class="ds-table" @row-click="handleClick" @register="registerTable" > <BasicTable class="ds-table" @row-click="handleClick" @register="registerTable">
<template #right> <template #right>
<div style="width: 40%;margin-left: 10px;margin-top:10px;"> <div style="width: 40%;margin-left: 10px;margin-top:10px;">
<div> <div>
@ -14,11 +14,6 @@
</div> </div>
</template> </template>
<template v-slot:bodyCell="{ column, record }"> <template v-slot:bodyCell="{ column, record }">
<template v-if="column.dataIndex == 'applyAmount'">
<a-input-number @change="onSelectAmount" :precision="2" size="small"
:controls="false" :max="record.restAmount"
v-model:value="record.applyAmount" />
</template>
<template v-if="column.dataIndex == 'feeType'"> <template v-if="column.dataIndex == 'feeType'">
<span v-if="record.feeType == 1"></span> <span v-if="record.feeType == 1"></span>
<span v-if="record.feeType == 2"></span> <span v-if="record.feeType == 2"></span>
@ -62,20 +57,23 @@
v-model:value="item.reverseRate" /> v-model:value="item.reverseRate" />
</div> </div>
</div> </div>
</a-modal> </a-modal>
<a-modal width="1600px" @cancel="freeFlag = false" :visible="freeFlag" title="添加发票申请明细" :footer="null"> <a-modal width="1600px" @cancel="freeFlag = false" :visible="freeFlag" title="添加发票申请明细" :footer="null">
<div style="padding-bottom:5px ;"> <div style="padding-bottom:5px ;">
<div> <div>
<BasicTable class="ds-table" @row-click="handleClickFree" @register="registerTableFree"> <BasicTable class="ds-table" @row-click="handleClickFree" @register="registerTableFree">
<template #right> <template #right>
<div style="width: 40%;margin-left: 10px;margin-top:10px;"> <div style="width: 40%;margin-left: 10px;">
<div> <div>
<BasicTable class="ds-table" @register="registerTable1"> <BasicTable class="ds-table" @register="registerTableFreeDetail">
<template #tableTitle> <template #tableTitle>
<div> <div>
<span class="bold">发票申请明细</span> <span class="bold">发票申请明细</span>
</div> </div>
<a-button type="link" @click="handleAddDetial">
<span class="iconfont icon-jia"></span>
添加到发票费用明细
</a-button>
</template> </template>
<template v-slot:bodyCell="{ column, record }"> <template v-slot:bodyCell="{ column, record }">
<template v-if="column.dataIndex == 'applyAmount'"> <template v-if="column.dataIndex == 'applyAmount'">
@ -97,14 +95,12 @@
<div> <div>
<div> <div>
<span class="bold">发票申请</span> <span class="bold">发票申请</span>
<a-button v-repeat type="link" @click="addDetailed()"> <a-button v-repeat type="link" @click="addDetailFree">
<span class="iconfont icon-jia"></span> <span class="iconfont icon-jia"></span>
添加申请明细 添加申请明细
</a-button> </a-button>
</div> </div>
</div> </div>
</template> </template>
<template v-slot:bodyCell="{ column, record }"> <template v-slot:bodyCell="{ column, record }">
<template v-if="column.dataIndex == 'businessType'"> <template v-if="column.dataIndex == 'businessType'">
@ -112,6 +108,21 @@
</template> </template>
</template> </template>
</BasicTable> </BasicTable>
<div class="total">
<span style="margin-right: 10px;">合计:</span>
<span class="total-item">
<span class="text">RMB未开:</span>
<span class="number">{{ rmbTotal }}</span>
</span>
<span class="total-item">
<span class="text">USD未开:</span>
<span class="number">{{ usdTotal }}</span>
</span>
<span class="total-item">
<span class="text">其他未开:</span>
<span class="number">{{ otherTotal }}</span>
</span>
</div>
</div> </div>
</div> </div>
</a-modal> </a-modal>
@ -123,15 +134,75 @@
import { formatParams } from '/@/hooks/web/common' import { formatParams } from '/@/hooks/web/common'
import { ref, defineExpose, watch } from 'vue' import { ref, defineExpose, watch } from 'vue'
import { BasicTable, useTable, TableAction } from '/@/components/Table' import { BasicTable, useTable, TableAction } from '/@/components/Table'
import { applyColums, applySearch, applyColumsDetail,freeSearch,freeColums } from '../columns' import { applyColums, applySearch, applyColumsDetail, freeSearch, freeColums } from '../columns'
import { GetApplicationList, GetApplicationDetails, GetExchangeRate,FreeInvoiceGetBizList,FreeInvoiceGetFees } from '../api.js' import { GetApplicationList, GetApplicationDetails, GetExchangeRate, FreeInvoiceGetBizList, FreeInvoiceGetFees, GetCurrencies } from '../api.js'
import { useMessage } from '/@/hooks/web/useMessage' import { useMessage } from '/@/hooks/web/useMessage'
const { createMessage } = useMessage() const { createMessage } = useMessage()
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
const route = useRoute() const route = useRoute()
const open = ref(false) const open = ref(false)
const columnsFreeDetail = [
{
title: '结费单位',
dataIndex: 'customerName',
width: 100,
},
{
title: '收付',
dataIndex: 'feeType',
width: 50,
},
{
title: '费用名称',
dataIndex: 'feeName',
width: 80,
},
{
title: '金额',
dataIndex: 'amount',
width: 60,
},
{
title: '币别',
dataIndex: 'currency',
width: 60,
},
{
title: '未开票金额',
dataIndex: 'restAmount',
width: 100,
},
{
title: '本次开票金额',
dataIndex: 'applyAmount',
width: 100,
},
{
title: '原始汇率',
dataIndex: 'exchangeRate',
width: 80,
},
{
title: '录入人',
dataIndex: 'createByName',
width: 80,
},
{
title: '销项/进项',
dataIndex: 'name',
width: 80,
},
{
title: '录入方式',
dataIndex: 'inputMethod',
width: 80,
},
]
const queryDataFree = ref({})
const dataSource = ref([]) as any const dataSource = ref([]) as any
const freeDetailList = ref([]) as any
const [registerTable, { getForm, setSelectedRowKeys, getSelectRows, setProps, getRawDataSource, setLoading }] = useTable({ const [registerTable, { getForm, setSelectedRowKeys, getSelectRows, setProps, getRawDataSource, setLoading }] = useTable({
api: async (p) => { api: async (p) => {
const res: API.DataResult = await GetApplicationList(p) const res: API.DataResult = await GetApplicationList(p)
@ -176,7 +247,7 @@ const [registerTable1, { getSelectRows: getSelectRowsFee, setProps: setPropsFee,
canResize: true, canResize: true,
immediate: false, immediate: false,
}) })
const [registerTableFree, { getForm:getFormFree, setSelectedRowKeys:setSelectedRowKeysFree, getSelectRows:getSelectRowsFree }] = useTable({ const [registerTableFree, { getForm: getFormFree, setSelectedRowKeys: setSelectedRowKeysFree, getSelectRows: getSelectRowsFree, getRawDataSource: getRawDataSourceFree }] = useTable({
api: async (p) => { api: async (p) => {
const res: API.DataResult = await FreeInvoiceGetBizList(p) const res: API.DataResult = await FreeInvoiceGetBizList(p)
return new Promise((resolve) => { return new Promise((resolve) => {
@ -184,18 +255,23 @@ const [registerTableFree, { getForm:getFormFree, setSelectedRowKeys:setSelectedR
}) })
}, },
beforeFetch: (p) => { beforeFetch: (p) => {
return formatParams(p) const data = formatParams(p)
data.otherQueryCondition = getFormFree().getFieldsValue().FeeRange
queryDataFree.value = JSON.parse(JSON.stringify(p))
return data
}, },
columns: freeColums, columns: freeColums,
formConfig: { formConfig: {
labelWidth: 120, labelWidth: 120,
schemas: freeSearch, schemas: freeSearch,
}, },
rowSelection: {
onChange: onSelectChange
},
useSearchForm: true, useSearchForm: true,
showIndexColumn: false, showIndexColumn: false,
maxHeight: '600', maxHeight: '600',
pagination: true, pagination: true,
rowSelection: {},
striped: true, striped: true,
bordered: true, bordered: true,
indexColumnProps: { indexColumnProps: {
@ -207,44 +283,191 @@ const [registerTableFree, { getForm:getFormFree, setSelectedRowKeys:setSelectedR
const exchangeFlag = ref(false) const exchangeFlag = ref(false)
const freeFlag = ref(false) const freeFlag = ref(false)
const loading = ref(false) const loading = ref(false)
const [registerTableFreeDetail, { getSelectRows: getSelectRowsFeeDetail, setProps: setPropsFeeDetail, setTableData: setTableDataDetail }] = useTable({
columns: columnsFreeDetail,
useSearchForm: false,
showIndexColumn: false,
maxHeight: '600',
pagination: false,
dataSource: freeDetailList.value,
striped: true,
rowKey: 'recordId',
rowSelection: {
// onChange: onSelectAmount
},
bordered: true,
indexColumnProps: {
width: 60,
},
canResize: true,
immediate: false,
})
const rmbTotal = ref(0)
const usdTotal = ref(0)
const otherTotal = ref(0)
function onSelectChange(selectedRowKeys) {
const list = getSelectRowsFree()
console.log(list, selectedRowKeys)
rmbTotal.value = 0
usdTotal.value = 0
otherTotal.value = 0
list.forEach(item => {
rmbTotal.value += Number(item.unBilledRMB)
usdTotal.value += Number(item.unBilledUSD)
otherTotal.value += Number(item.unBilledOther)
})
}
function handleAddDetial() {
let arr = getSelectRowsFeeDetail() ? getSelectRowsFeeDetail() : []
if (arr.length == 0) {
createMessage.error('请选择费用明细')
return false
}
changeApply()
}
function changeApply() {
const arr = getSelectRowsFeeDetail()
const exchangeArr = [] as any
if (arr.length > 0) {
exchangarr.value = []
arr.forEach(item => {
if (item.currency != 'RMB') {
exchangeArr.push(item)
}
})
const filteredItems = exchangeArr.filter((item, index, self) =>
index === self.findIndex((t) => t.currency === item.currency)
);
if (filteredItems.length > 0) {
const promises = filteredItems.map(item => {
return new Promise((resolve) => {
const data = {
currencyFrom: 'RMB',
currencyTo: item.currency,
feeType: item.feeType
}
GetExchangeRate(data).then(res => {
exchangarr.value.push(res.data)
resolve(true);
})
});
});
return Promise.all(promises).then(() => {
freeType.value = 'right'
exchangeFlag.value = true
});
}
if (filteredItems.length == 0) {
open.value = false
emits('updateListFree', arr)
}
}
}
const freeType = ref('')
function addDetailFree() {
let arr = getSelectRowsFree() ? getSelectRowsFree() : []
if (arr.length == 0) {
createMessage.error('请选择发票')
return false
}
let freeList = [] as any
arr.forEach(item => {
freeList.push({
id: item.id,
businessType: item.businessType,
customerId: item.customerId
})
})
GetCurrencies(freeList).then(res => {
const cuArr = []
res.data.forEach(item => {
if (item != 'RMB') {
cuArr.push(1)
}
})
if (cuArr.length > 0) {
const promises = cuArr.map(item => {
return new Promise((resolve) => {
const data = {
currencyFrom: 'RMB',
currencyTo: item,
}
GetExchangeRate(data).then(res => {
exchangarr.value.push(res.data)
resolve(true);
})
});
});
return Promise.all(promises).then(() => {
freeType.value = 'left'
exchangeFlag.value = true
});
}
if (cuArr.length == 0) {
open.value = false
emits('updateListFreeLeft', arr)
}
})
}
const emits = defineEmits(['updateList', 'addLeft', 'updateListFree', 'updateListFreeLeft'])
const emits = defineEmits(['updateList', 'addLeft'])
// RMB // RMB
function handleSureExhange() { function handleSureExhange() {
applications.value.forEach(item => { if (route.query.type == 'apply') {
if (item.currency != 'RMB') { applications.value.forEach(item => {
if (item.currency != 'RMB') {
exchangarr.value.forEach(ite => {
if (item.currency == ite.currencyTo) {
item.exchangeRate = ite.reverseRate
}
})
} else {
item.exchangeRate = 1
}
})
const resultMap = new Map();
applications.value.forEach(item => {
const { applicationId, currency, exchangeRate } = item;
if (!resultMap.has(applicationId)) {
resultMap.set(applicationId, {
applicationId,
exchangeRates: []
});
}
const entry = resultMap.get(applicationId);
entry.exchangeRates.push({
currency,
exchangeRate
});
});
const result = Array.from(resultMap.values());
emits('updateList', result)
open.value = false
exchangeFlag.value = false
}
if (route.query.type == 'free') {
let arr = [] as any
if (freeType.value == 'left') {
arr = getSelectRowsFree()
} else {
arr = getSelectRowsFeeDetail()
}
arr.forEach(item => {
exchangarr.value.forEach(ite => { exchangarr.value.forEach(ite => {
if (item.currency == ite.currencyTo) { if (item.currency == item.currencyTo) {
item.exchangeRate = ite.reverseRate item.exchangeRate = ite.reverseRate
} }
}) })
})
open.value = false
exchangeFlag.value = false
if (freeType.value == 'left') {
emits('updateListFreeLeft', arr)
} else { } else {
item.exchangeRate = 1 emits('updateListFree', arr)
}
})
const resultMap = new Map();
applications.value.forEach(item => {
const { applicationId, currency, exchangeRate } = item;
if (!resultMap.has(applicationId)) {
resultMap.set(applicationId, {
applicationId,
exchangeRates: []
});
} }
const entry = resultMap.get(applicationId); }
entry.exchangeRates.push({
currency,
exchangeRate
});
});
const result = Array.from(resultMap.values());
emits('updateList', result)
open.value = false
exchangeFlag.value = false
} }
function handleClick(record, index) { function handleClick(record, index) {
setSelectedRowKeys([record.id]) setSelectedRowKeys([record.id])
@ -270,21 +493,26 @@ function handleClickFree(record, index) {
const data = { const data = {
id: record.id, id: record.id,
businessType: record.businessType, businessType: record.businessType,
// customerId: record.customerId customerId: record.customerId
} }
loading.value = true loading.value = true
FreeInvoiceGetFees(data).then(res => { FreeInvoiceGetFees([data]).then(res => {
if (res.succeeded) { if (res.succeeded) {
freeDetailList.value = res.data.items
freeDetailList.value.forEach(item => {
item.applyAmount = item.restAmount ? item.restAmount : 0
item.applyAmount = item.applyAmount.toFixed(2)
})
setTableDataDetail(freeDetailList.value)
} }
loading.value = false loading.value = false
}) })
} }
function init(data) { function init(data) {
if(route.query.type=='apply'){ if (route.query.type == 'apply') {
open.value = true open.value = true
} }
if(route.query.type=='free'){ if (route.query.type == 'free') {
freeFlag.value = true freeFlag.value = true
} }
@ -293,7 +521,7 @@ function init(data) {
const amountArr = ref([]) as any const amountArr = ref([]) as any
// //
function onSelectAmount() { function onSelectAmount() {
const arr = getSelectRowsFee() const arr = getRawDataSourceFree()
amountArr.value = [] amountArr.value = []
arr.forEach(item => { arr.forEach(item => {
amountArr.value.push({ amountArr.value.push({

@ -296,7 +296,7 @@
</div> </div>
</div> </div>
</a-spin> </a-spin>
<applyInvoice @updateList="handleUpdate" ref="applyInvoiceRef"></applyInvoice> <applyInvoice @updateListFreeLeft="updateListFreeLeft" @updateList="handleUpdate" @updateListFree="updateListFree" ref="applyInvoiceRef"></applyInvoice>
<a-modal width="1400px" @cancel="feeFlag = false" :visible="feeFlag" title="费用明细" :footer="null"> <a-modal width="1400px" @cancel="feeFlag = false" :visible="feeFlag" title="费用明细" :footer="null">
<BasicTable @register="registerTableFee"> <BasicTable @register="registerTableFee">
<template v-slot:bodyCell="{ column, record }"> <template v-slot:bodyCell="{ column, record }">
@ -323,7 +323,7 @@ import invoiceFile from './invoiceFile.vue'
import { DownOutlined } from '@ant-design/icons-vue' import { DownOutlined } from '@ant-design/icons-vue'
import { import {
GetInvoiceCodeList, GetUserListAll, DeleteInvoiceDetail, GetInvoiceCodeList, GetUserListAll, DeleteInvoiceDetail,
GeneralInvoiceSave, GeneralInvoiceGet, GeneralInvoiceSave, GeneralInvoiceGet, FreeInvoiceSave,
GeneralInvoiceGetList, GeneralInvoiceInitiate GeneralInvoiceGetList, GeneralInvoiceInitiate
} from '../api' } from '../api'
import { useMessage } from '/@/hooks/web/useMessage' import { useMessage } from '/@/hooks/web/useMessage'
@ -676,6 +676,29 @@ function openFile() {
} }
const router = useRouter() const router = useRouter()
const go = useGo() const go = useGo()
function updateListFreeLeft(val){
const data = {
invoice: {
...form.value,
...getFieldsValue()
},
bizList: val,
}
FreeInvoiceSave(data).then(res => {
if (res.succeeded) {
createMessage.success('保存成功')
if (!route.query.id) {
const { fullPath } = route //
tabStore.closeTabByKey(fullPath, router)
setTimeout(() => {
go(`/invoiceIssueDetail?id=${res.data.id}&type=${route.query.type}`)
}, 50)
} else {
getDetail()
}
}
})
}
function handleUpdate(val) { function handleUpdate(val) {
const data = { const data = {
invoice: { invoice: {
@ -687,7 +710,6 @@ function handleUpdate(val) {
} }
GeneralInvoiceSave(data).then(res => { GeneralInvoiceSave(data).then(res => {
if (res.succeeded) { if (res.succeeded) {
createMessage.success('保存成功') createMessage.success('保存成功')
if (!route.query.id) { if (!route.query.id) {
const { fullPath } = route // const { fullPath } = route //
@ -701,6 +723,36 @@ function handleUpdate(val) {
} }
}) })
} }
function updateListFree(val) {
val.forEach(item => {
item.originalCurrency = item.currency
item.currency = 'RMB'
item.originalAmount = item.applyAmount
item.originalProcessedAmount = item.processedAmount ? item.processedAmount : 0
})
const data = {
invoice: {
...form.value,
...getFieldsValue()
},
details: val,
}
FreeInvoiceSave(data).then(res => {
if (res.succeeded) {
createMessage.success('保存成功')
if (!route.query.id) {
const { fullPath } = route //
tabStore.closeTabByKey(fullPath, router)
setTimeout(() => {
go(`/invoiceIssueDetail?id=${res.data.id}&type=${route.query.type}`)
}, 50)
} else {
getDetail()
}
}
})
}
// //
const deleteRow = async () => { const deleteRow = async () => {
const ids = [] as any const ids = [] as any
@ -739,7 +791,7 @@ const [registerTableFee, { setTableData: setTableDataFee, }] = useTable({
useSearchForm: false, useSearchForm: false,
showIndexColumn: false, showIndexColumn: false,
pagination: false, pagination: false,
showTableSetting: true, showTableSetting: false,
striped: true, striped: true,
rowKey: 'id', rowKey: 'id',
bordered: true, bordered: true,

Loading…
Cancel
Save