Files
management/src/views/invoicing/operation_out.vue
2024-10-15 16:20:17 +08:00

540 lines
23 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="app-container">
<div class="head-container">
<el-form ref="queryForm" :model="queryForm" :rules="queryRules" label-position="left" label-width="80px">
<!-- <el-form-item label="出库内容">
<div class="shop_type_box">
<div class="item" v-for="item in inTabs" :key="item.value"
:class="{ active: inTabValue == item.value }" @click="tabChange(item.value, item.type)">
<div class="s_title">{{ item.label }}</div>
<div class="active_dot">
<i class="el-icon-check"></i>
</div>
</div>
</div>
</el-form-item> -->
<!-- <el-form-item label="出库类型" v-if="inTabValue == 'goods'">
<div class="shop_type_box">
<div class="item" v-for="(item, index) in shopTypes" :key="index"
:class="{ active: shopTypesActive == index }" @click="changeTypeEnum(index)">
<div class="s_title">{{ item.label }}</div>
<div class="active_dot">
<i class="el-icon-check"></i>
</div>
</div>
</div>
</el-form-item>
<el-form-item label="出库类型" v-else>
<div class="shop_type_box">
<div class="item" v-for="(item, index) in shopTypes2" :key="index"
:class="{ active: shopTypesActive == index }" @click="changeTypeEnum(index)">
<div class="s_title">{{ item.label }}</div>
<div class="active_dot">
<i class="el-icon-check"></i>
</div>
</div>
</div>
</el-form-item> -->
<el-row>
<el-col :span="8">
<el-form-item label="供应商">
<el-select clearable v-model="queryForm.purveyorId" placeholder="请选择供应商"
style="width: 220px;" @change="changeTypeEnum">
<el-option :label="item.purveyorName" :value="item.id" v-for="item in purveyorList"
:key="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="出库时间" prop="time">
<el-date-picker v-model="queryForm.time" type="date" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" placeholder="选择日期" style="width: 220px;">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="shopTypes[shopTypesActive].value == 'reject'">
<el-col :span="8">
<el-form-item label="应收金额">
<el-input v-model="queryForm.totalAmount" placeholder="请输入应收金额"
style="width: 220px;"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="实收金额">
<el-input v-model="queryForm.paidAmount" placeholder="请输入实收金额"
style="width: 220px;"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="shopTypes[shopTypesActive].value == 'reject'">
<el-col :span="8">
<el-form-item label="付款时间">
<el-date-picker v-model="queryForm.paidAt" type="date" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" placeholder="选择日期" style="width: 220px;">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="批号">
<el-input v-model="queryForm.batchNumber" placeholder="请输入批号"
style="width: 220px;"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<el-form-item label="备注">
<el-input v-model="queryForm.remark" placeholder="请输入备注" style="width: 220px;"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item>
<el-button type="primary" @click="$refs.ConsumableList.show(tableData.list)"
v-if="inTabValue == 'consumable'">选择耗材</el-button>
<el-button type="primary" @click="$refs.shopList.show(tableData.list)" v-else>选择商品</el-button>
</el-form-item>
<el-autocomplete v-model="autocompletename" :fetch-suggestions="querySearchAsync"
:value-key="inTabValue == 'goods' ? 'name' : 'conName'"
:placeholder="inTabValue == 'goods' ? '商品搜索' : '耗材搜索'" @select="handleSelect"
style="width: 500px;"></el-autocomplete>
</el-form>
</div>
<div class="head-container">
<el-button type="primary" plain>
{{ tableData.list.length }}种商品金额合计<span style="color: red;">{{ queryForm.totalAmount }}</span>
</el-button>
</div>
<div class="head-container">
<el-table :data="tableData.list" v-if="inTabValue == 'consumable'">
<el-table-column label="耗材名称" prop="conName">
<template v-slot="scope">
{{ scope.row.conName }}
</template>
</el-table-column>
<el-table-column label="进价">
<template v-slot="scope">
<el-input-number v-model="scope.row.price" :min="0" controls-position="right"
@change="consCountTotal($event, scope.row, 'price')"></el-input-number>
<div class="tips">原价{{ scope.row.costPrice }}/{{ scope.row.conUnit }}</div>
</template>
</el-table-column>
<el-table-column label="数量">
<template v-slot="scope">
<el-input-number v-model="scope.row.stockNumber" :min="0" :step="1" step-strictly
controls-position="right"
@change="consCountTotal($event, scope.row, 'stockNumber')"></el-input-number>
<div class="tips">出库前{{ scope.row.number }}{{ scope.row.conUnit }}</div>
</template>
</el-table-column>
<el-table-column label="小计">
<template v-slot="scope">
<!-- <el-input-number v-model="scope.row.totalAmount" :min="0"
controls-position="right"></el-input-number> -->
<el-input :value="formatDecimal(scope.row.price * scope.row.stockNumber)" readonly
style="width: 100px;" />
</template>
</el-table-column>
<!-- <el-table-column label="变动后剩余库存">
<template v-slot="scope">
{{ scope.row.stockNumber - scope.row.number }}{{ scope.row.conUnit }}
</template>
</el-table-column> -->
<el-table-column label="操作" width="80">
<template v-slot="scope">
<el-button type="text"
@click="tableData.list.splice(scope.$index, 1), spliceclick()">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-table :data="tableData.list" v-else>
<el-table-column type="index" width="50"></el-table-column>
<el-table-column label="商品名称" prop="name">
<template v-slot="scope">
<div class="name_wrap">
<span class="name">{{ scope.row.name }}</span>
<el-tag type="info" v-if="scope.row.specSnap" size="mini">{{ scope.row.specSnap }}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="进价">
<template v-slot="scope">
<el-input-number v-model="scope.row.costPrice" :min="0" controls-position="right"
@change="modifyPrice($event, scope.row, 'costPrice')"></el-input-number>
<div class="tips">成本价{{ scope.row.costPrice }}/{{ scope.row.unitName }}</div>
</template>
</el-table-column>
<el-table-column label="数量">
<template v-slot="scope">
<el-input-number v-model="scope.row.number" :min="0" controls-position="right"
@change="modifyPrice($event, scope.row, 'number', 'totalAmount')"></el-input-number>
<div class="tips">出库前{{ scope.row.stockNumber }}{{ scope.row.unitName }}</div>
</template>
</el-table-column>
<el-table-column label="小计">
<template v-slot="scope">
<!-- <el-input-number v-model="scope.row.totalAmount" :min="0"
controls-position="right"></el-input-number> -->
<el-input :value="scope.row.costPrice * scope.row.number" readonly style="width: 100px;" />
</template>
</el-table-column>
<el-table-column label="变动后剩余库存">
<template v-slot="scope">
{{ scope.row.stockNumber - scope.row.number }}{{ scope.row.unitName }}
</template>
</el-table-column>
<el-table-column label="操作" width="80">
<template v-slot="scope">
<el-button type="text"
@click=" tableData.list.splice(scope.$index, 1), spliceclick()">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div>
<el-button type="primary" @click="submitHandle" :loading="queryFormLoading">确定</el-button>
</div>
<!-- 选择商品 -->
<shopList ref="shopList" @success="selectShop" />
<!-- 选择耗材 -->
<ConsumableList ref="ConsumableList" @success="selectConsumable" />
<el-dialog :visible.sync="showResult" :show-close="false" :close-on-press-escape="false"
:close-on-click-modal="false">
<el-result icon="success" title="出库提交成功" :subTitle="`共操作${tableData.list.length}件商品`">
<template slot="extra">
<el-button type="primary" size="medium" @click="resetHandle">创建新的出库单</el-button>
<router-link to="/invoicing/operating_record">
<el-button size="medium">历史提交</el-button>
</router-link>
</template>
</el-result>
</el-dialog>
</div>
</template>
<script>
import dayjs from 'dayjs'
import shopList from './components/shopList'
import ConsumableList from './components/consumableList'
import { tbShopPurveyorGet, tbProductStockOperateOutAndOn, stockInOut, tbConsInfoGet, tbProductlist } from '@/api/invoicing'
import { formatDecimal } from '@/utils'
export default {
components: {
shopList,
ConsumableList
},
data() {
return {
formatDecimal,
inTabValue: 'consumable',
inTabs: [
{
label: '商品出库',
value: 'goods',
type: 'reject'
},
{
label: '耗材出库',
value: 'consumable',
type: 'out'
}
],
shopTypesActive: 0,
shopTypes: [
{
label: '供应商退货',
value: 'reject'
},
{
label: '其他出库',
value: 'other-out'
}
],
shopTypes2: [
{
label: '供应商退货',
value: 'reject'
}
],
resetForm: '',
queryFormLoading: false,
queryForm: {
batchNumber: '',
list: [],
paidAmount: 0,
paidAt: '',
purveyorId: '',
purveyorName: '',
remark: '',
time: dayjs().format('YYYY-MM-DD'),
totalAmount: 0,
type: 'reject',
shopId: localStorage.getItem('shopId'),
},
queryRules: {
purveyorId: [
{
required: true,
message: ' ',
trigger: 'change'
}
],
time: [
{
required: true,
message: ' ',
trigger: 'change'
}
]
},
purveyorList: [],
tableData: {
list: []
},
showResult: false,
autocompletename: '',
restaurants: [],
timeout: null
}
},
mounted() {
this.resetForm = { ...this.queryForm }
this.tbShopPurveyorGet()
},
methods: {
async querySearchAsync(queryString, cb) {//快捷搜索
let res = null
if (this.inTabValue == 'goods') {
res = await tbProductlist({
page: 0,
size: 20,
name: queryString ? queryString : '',
shopId: localStorage.getItem('shopId'),
sort: 'id',
})
} else {
res = await tbConsInfoGet({
page: 0,
size: 20,
shopId: localStorage.getItem('shopId'),
conName: queryString ? queryString : ''
})
}
this.restaurants = res.content
if (res.content.length == 0) {//给个提示没有搜到
this.$message('无此商品');
return false
}
var uniqueArray = this.restaurants.filter(item1 =>
!this.tableData.list.some(item2 => item2.productId == item1.id)
);
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
cb(uniqueArray);
}, 1000 * Math.random());
},
handleSelect(item) {//选定后清空
this.autocompletename = ''
if (this.inTabValue == 'goods') {
this.selectShop([item])
} else {
this.selectConsumable([item])
}
},
// 切换入库内容
tabChange(value, type) {
this.inTabValue = value
this.shopTypesActive = 1
this.resetHandle()
this.queryForm.type = type
this.$refs.shopList.clearSelection()//清除选项
this.$refs.ConsumableList.clearSelection()//清除选项
},
//删除计算
spliceclick() {
var zong = 0
if (this.inTabValue == 'goods') {
this.tableData.list.forEach(ele => {
zong += ele.costPrice * ele.number
})
} else {
this.tableData.list.forEach(ele => {
zong += ele.price * ele.stockNumber
})
}
this.queryForm.totalAmount = formatDecimal(zong)
},
// 计算耗材总价
consCountTotal(cvalue, row, key1, key2 = undefined) {
if (cvalue == undefined) {
setTimeout(() => {
row[key1] = 0
let zong = 0
this.tableData.list.forEach(ele => {
zong += ele.price * ele.stockNumber
})
this.queryForm.totalAmount = formatDecimal(zong)
}, 10)
} else {
row[key1] = cvalue
let zong = 0
this.tableData.list.forEach(ele => {
zong += ele.price * ele.stockNumber
})
this.queryForm.totalAmount = formatDecimal(zong)
}
},
// 计算商品总价
modifyPrice(cvalue, row, key1, key2 = undefined) {
if (cvalue == undefined) {
setTimeout(() => {
row[key1] = 0
row[key2] = 0
let zong = 0
this.tableData.list.forEach(ele => {
zong += ele.costPrice * ele.number
})
this.queryForm.totalAmount = formatDecimal(zong)
}, 10)
} else {
row[key1] = cvalue
row[key2] = cvalue
let zong = 0
this.tableData.list.forEach(ele => {
zong += ele.costPrice * ele.number
})
this.queryForm.totalAmount = formatDecimal(zong)
}
},
// 提交
submitHandle() {
if (this.tableData.list.length == 0) {
switch (this.inTabValue) {
case 'goods':
this.$message('请先选择商品入!');
break;
case 'consumable':
this.$message('请先选择耗材!');
break;
default:
break;
}
return false
}
this.$refs.queryForm.validate(async valid => {
if (valid) {
try {
this.queryFormLoading = true
switch (this.inTabValue) {
case 'goods':
this.queryForm.list = this.tableData.list
await tbProductStockOperateOutAndOn(this.queryForm)
break;
case 'consumable':
this.queryForm.accountsPayable = this.queryForm.totalAmount
this.queryForm.actualPayment = this.queryForm.paidAmount
this.queryForm.paymentTime = this.queryForm.paidAt
this.queryForm.supplierId = this.queryForm.purveyorId
this.queryForm.list = this.tableData.list
this.queryForm.type = 'out'
await stockInOut(this.queryForm)
break;
default:
break;
}
this.queryFormLoading = false
this.showResult = true
this.$refs.shopList.clearSelection()//清除选项
this.$refs.ConsumableList.clearSelection()//清除选项
} catch (error) {
console.log(error)
this.queryFormLoading = false
}
}
})
},
// 选择耗材
selectConsumable(res) {
let arr = res.map(item => {
item.number = formatDecimal(item.stockNumber - item.stockConsume, 2, true)
item.stockNumber = 0
item.costPrice = item.price
item.conInfoId = item.id
return item
})
this.tableData.list = [...this.tableData.list, ...arr]
},
// 选择商品
selectShop(res) {
let arr = []
res.forEach(item => {
item.skuList.forEach(i => {
arr.push({
name: item.name,
unitName: item.unitName,
productId: item.id,
number: 0,
totalAmount: '',
...i
})
})
})
this.tableData.list = [...this.tableData.list, ...arr]
},
// 初始化
resetHandle() {
this.showResult = false
this.queryForm = { ...this.resetForm }
if (this.inTabValue == 'goods') {
this.queryForm.type = this.shopTypes[this.shopTypesActive].value
} else {
this.queryForm.type = this.inTabs.find(item => item.value == this.inTabValue).type
}
this.tableData.list = []
this.$refs.queryForm.resetFields()
},
// 切换类型
changeTypeEnum(index) {
if (this.queryForm.purveyorId) {
this.shopTypesActive = 0
} else {
this.shopTypesActive = 1
}
this.queryForm.type = this.shopTypes[this.shopTypesActive].value
// this.shopTypesActive = index
// this.queryForm.type = this.shopTypes[index].value
},
// 获取供应商列表
async tbShopPurveyorGet() {
try {
const res = await tbShopPurveyorGet({
shopId: localStorage.getItem('shopId'),
page: 0,
size: 100
})
this.purveyorList = res.content
} catch (error) {
console.log(error)
}
}
}
}
</script>
<style scoped lang="scss">
.name_wrap {
display: flex;
align-items: center;
.name {
margin-right: 10px;
}
}
</style>