financialAccount.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. <template>
  2. <div>
  3. <basic-container>
  4. <avue-crud ref="crud" :data="data" :option="option" :table-loading="loading" @row-update="rowUpdate"
  5. @row-del="rowDel" @saveColumn="saveColumn" @resetColumn="resetColumn">
  6. <template slot="menuLeft" slot-scope="{size}">
  7. <el-button type="primary" icon="el-icon-plus" size="small" :loading="submitButton" @click="entering"
  8. v-if="addBut">录入
  9. </el-button>
  10. </template>
  11. <template slot-scope="{row,index}" slot="menu">
  12. <el-button type="text" size="small" icon="el-icon-edit" @click="rowCell(row, index)">{{ row.$cellEdit ? '保存' :
  13. '修改'
  14. }}
  15. </el-button>
  16. <el-button type="text" icon="el-icon-delete" size="small" @click="rowDel(row, index)">删除</el-button>
  17. </template>
  18. <template slot-scope="{row,index}" slot="corpId">
  19. <span v-if="row.$cellEdit && category != 2" class="required_fields"
  20. style="float: left;line-height: 32px">*</span>
  21. <span v-if="row.$cellEdit && category != 2" style="display: flex">
  22. <el-select v-model="corpId" placeholder="请选择" size="small" style="width:60%" filterable>
  23. <el-option v-for="item in corpOption" :key="item.id" :label="item.cname" :value="item.id" />
  24. </el-select>
  25. <el-button icon="el-icon-search" size="small" @click="openDialog(row, index, 1)"></el-button>
  26. </span>
  27. <span v-else>{{ corpsName }}</span>
  28. </template>
  29. <!-- <template slot-scope="{row,index}" slot="costType">-->
  30. <!-- <breakdown-select-->
  31. <!-- v-if="row.$cellEdit"-->
  32. <!-- v-model="row.costType"-->
  33. <!-- style="width: 90%"-->
  34. <!-- :configuration="configuration"-->
  35. <!-- @selectValue="(value) => {getFeeValue(row, value)}"-->
  36. <!-- >-->
  37. <!-- </breakdown-select>-->
  38. <!-- <span v-else>{{ row.costName }}</span>-->
  39. <!-- </template>-->
  40. <template slot-scope="{row,index}" slot="billNo">
  41. <el-select placeholder="请选择" v-if="row.$cellEdit" v-model="row.billNo" size="small" filterable allow-create
  42. default-first-option clearable>
  43. <el-option v-for="item in row.billNoList" :key="item" :label="item" :value="item"></el-option>
  44. </el-select>
  45. <span v-else>{{ row.billNo }}</span>
  46. </template>
  47. <template slot-scope="{row,index}" slot="taxRate">
  48. <el-input v-model="row.taxRate" v-if="row.$cellEdit" size="small"
  49. oninput='this.value=this.value.replace(/[^(\d.)]/g,"").replace(/^(\d+)\.(\d\d\d\d\d\d).*$/, "$1.$2")'
  50. autocomplete="off">
  51. <i slot="suffix" style="margin-right: 10px;top:6px">%</i>
  52. </el-input>
  53. <span v-else>{{ row.taxRate }}</span>
  54. </template>
  55. <template slot-scope="{row,index}" slot="currency">
  56. <span v-if="row.$cellEdit" class="required_fields">*</span>
  57. <el-select v-if="row.$cellEdit" v-model="row.currency" size="small" placeholder="请选择" style="width: 90%"
  58. @change="currencyChange(row)" clearable filterable>
  59. <el-option v-for="(item, index) in currencyDic" :key="index" :label="item.dictValue"
  60. :value="item.dictValue">
  61. </el-option>
  62. </el-select>
  63. <span v-else>{{ row.currency }}</span>
  64. </template>
  65. <template slot-scope="{row,index}" slot="unit">
  66. <el-select v-if="row.$cellEdit" v-model="row.unit" size="small" style="width: 90%" placeholder="请选择" clearable
  67. filterable>
  68. <el-option v-for="(item, index) in unitDic" :key="index" :label="item.dictValue" :value="item.dictValue">
  69. </el-option>
  70. </el-select>
  71. <span v-else>{{ row.unit }}</span>
  72. </template>
  73. <template slot-scope="{row,index}" slot="price">
  74. <el-input-number v-if="row.$cellEdit" v-model="row.price" size="small" :controls="false" :precision="2"
  75. @input="amountChange(row)" style="width: 100%" />
  76. <span v-else>{{ Number(row.price).toFixed(2) }}</span>
  77. </template>
  78. <template slot-scope="{row,index}" slot="quantity">
  79. <el-input-number v-if="row.$cellEdit" v-model="row.quantity" size="small" :controls="false" :precision="0"
  80. @input="amountChange(row)" style="width: 100%" />
  81. <span v-else>{{ Number(row.quantity).toFixed(2) }}</span>
  82. </template>
  83. <template slot-scope="{row,index}" slot="amount">
  84. <el-input-number v-if="row.$cellEdit" v-model="row.amount" size="small" :controls="false" :precision="2"
  85. style="width: 100%" />
  86. <span v-else>{{ Number(row.amount).toFixed(2) }}</span>
  87. </template>
  88. </avue-crud>
  89. <div class="dialogButton">
  90. <el-button size="small" :loading="submitButton" @click="$emit('choceFun')">取消</el-button>
  91. <el-button type="primary" size="small" :loading="submitButton" @click="submit()">确定</el-button>
  92. </div>
  93. </basic-container>
  94. <containerTitle v-if="billId" title="历史账单"></containerTitle>
  95. <basic-container v-if="billId">
  96. <avue-crud :option="historyOption" :data="historyDataList" ref="historyCrud" v-model="historyForm"
  97. :page.sync="page" :table-loading="historyLoading" @on-load="onLoad">
  98. </avue-crud>
  99. </basic-container>
  100. <el-dialog title="客户、供应商" :visible.sync="corpVisible" width="80%" top="5vh" append-to-body @closed="closeCorp"
  101. class="el-dialogDeep" v-dialog-drag>
  102. <span>
  103. <el-row>
  104. <el-col :span="4">
  105. <el-scrollbar>
  106. <basic-container>
  107. <avue-tree :option="corpTreeOption" :data="treeData" @node-click="corpNodeClick" :style="treeStyle" />
  108. </basic-container>
  109. </el-scrollbar>
  110. </el-col>
  111. <el-col :span="20">
  112. <avue-crud :option="KHOption" :data="corpData" ref="crud" :page.sync="corpPage" :search.sync="corpSearch"
  113. @search-change="corpSearchChange" @search-reset="corpSearchReset" @selection-change="selectionChange"
  114. @current-change="corpCurrentChange" @size-change="corpSizeChange" @on-load="corpOnLoad"
  115. @tree-load="corpTreeLoad" @saveColumn="saveColumn" @resetColumn="resetColumn"
  116. @refresh-change="corpRefreshChange" :table-loading="dialogLoading">
  117. </avue-crud>
  118. </el-col>
  119. </el-row>
  120. </span>
  121. <span slot="footer" class="dialog-footer">
  122. <el-button @click="corpVisible = false">取 消</el-button>
  123. <el-button type="primary" @click="importCorp" :disabled="selectionList.length != 1">确 定</el-button>
  124. </span>
  125. </el-dialog>
  126. </div>
  127. </template>
  128. <script>
  129. import { applyLoan, paymentApply } from "@/api/financialManagement/paymentRequest";
  130. import { getApplyAmount } from "@/api/basicData/purchaseOrder"
  131. import option from "./config/option.json"
  132. import historyOption from "../bill/config/application.json"
  133. import { getUserInfo } from "@/api/system/user";
  134. import { getBillList } from "@/api/financialManagement/paymentRequest";
  135. import { customerList, getDeptLazyTree } from "@/api/basicData/customerInformation";
  136. import { getDeptLazyTree as getFeeLazyTree, customerList as feeList } from "@/api/basicData/basicFeesDesc";
  137. import corpOption from './config/corpOption.json'
  138. export default {
  139. name: "financialAccount",
  140. props: {
  141. addBut: {
  142. type: Boolean,
  143. default: true
  144. },
  145. billId: {
  146. type: String
  147. },
  148. billType: {
  149. type: String
  150. },
  151. srcType: {
  152. type: Number,
  153. default: 1,
  154. },
  155. billData: {
  156. type: Object
  157. },
  158. srcBillId: {
  159. type: Object
  160. },
  161. choceFun: {
  162. type: Function
  163. },
  164. arrList: {
  165. type: Array,
  166. default: []
  167. },
  168. checkData: {
  169. type: Object,
  170. default: {
  171. url: null,
  172. pageStatus: null,
  173. pageLabel: null,
  174. checkType: null
  175. },
  176. },
  177. belongCompany: {
  178. type: String,
  179. },
  180. tradeType: {
  181. type: String,
  182. default: null
  183. }
  184. },
  185. data() {
  186. return {
  187. data: [],
  188. corpId: '',
  189. corpsName: '',
  190. option: option,
  191. loading: false,
  192. submitButton: false,
  193. currencyDic: [],
  194. unitDic: [],
  195. configuration: {
  196. multipleChoices: false,
  197. multiple: false,
  198. disabled: true,
  199. searchShow: true,
  200. collapseTags: false,
  201. placeholder: '请点击右边按钮选择',
  202. dicData: []
  203. },
  204. category: '',
  205. historyLoading: false,
  206. historyOption: historyOption,
  207. historyDataList: [],
  208. historyForm: {},
  209. page: {
  210. pageSize: 10,
  211. pagerCount: 1,
  212. total: 0,
  213. },
  214. corpOption: [], //客户
  215. feeOption: [], // 费用
  216. rowData: null,
  217. corpVisible: false,
  218. feeVisible: false,
  219. treeStyle: 'height:' + (window.innerHeight - 315) + 'px',
  220. corpTreeOption: {
  221. nodeKey: "id",
  222. lazy: true,
  223. addBtn: false,
  224. menu: false,
  225. size: "small",
  226. props: {
  227. labelText: "标题",
  228. label: "title",
  229. value: "value",
  230. children: "children"
  231. }
  232. },
  233. treeCorpId: '',
  234. selectionList: [],
  235. corpPage: {
  236. currentPage: 1,
  237. pageSize: 10,
  238. total: 0
  239. },
  240. corpSearch: {},
  241. dialogLoading: false,
  242. KHOption: corpOption,
  243. corpData: [],
  244. }
  245. },
  246. created() {
  247. this.option.height = window.innerHeight - 240;
  248. this.historyOption.searchShow = false
  249. customerList({
  250. size: 10000,
  251. current: 1
  252. }).then(res => {
  253. // this.corpOption = res.data.data.records? res.data.data.records: [];
  254. if (res.data.data.total > 0) {
  255. this.corpOption = res.data.data.records;
  256. if (Math.ceil(res.data.data.total / 10) > 1) {
  257. for (let i = 2; i <= Math.ceil(res.data.data.total / 10); i++) {
  258. customerList({ current: i, size: 10 }).then(e => {
  259. this.corpOption = this.corpOption.concat(e.data.data.records);
  260. });
  261. }
  262. }
  263. }
  264. })
  265. this.loading = true;
  266. feeList({ size: 10000, current: 1 }).then(res => {
  267. this.feeOption = res.data.data.records ? res.data.data.records : [];
  268. this.init()
  269. }).finally(() => {
  270. this.loading = false;
  271. })
  272. getUserInfo().then(res => {
  273. this.category = res.data.data.billType
  274. if (this.category == 2) {
  275. }
  276. })
  277. //币别
  278. this.getWorkDicts("currency").then(res => {
  279. this.currencyDic = res.data.data
  280. })
  281. this.getWorkDicts("unit").then(res => {
  282. this.unitDic = res.data.data
  283. })
  284. },
  285. mounted() {
  286. // this.init()
  287. },
  288. watch: {
  289. billId(val, oldVal) {
  290. if (val != oldVal) {
  291. this.onLoad(this.page)
  292. }
  293. },
  294. },
  295. methods: {
  296. init() {
  297. if (this.arrList.length === 0) {
  298. this.corpId = this.billData.corpId
  299. this.corpsName = this.billData.corpsName[0].cname
  300. this.feeOption.forEach(item => {
  301. if (this.billData.costType == item.id) {
  302. this.$set(this.billData, 'costName', item.cname)
  303. }
  304. })
  305. this.data.push(this.billData)
  306. } else {
  307. this.billData = this.arrList[0]
  308. this.corpId = this.arrList[0].corpId
  309. this.corpsName = this.arrList[0].corpsName[0].cname
  310. this.arrList.forEach(item => {
  311. this.feeOption.forEach(e => {
  312. if (item.costType == e.id) {
  313. this.$set(item, 'costName', e.cname)
  314. }
  315. })
  316. this.data.push(item)
  317. })
  318. }
  319. this.$nextTick(() => {
  320. this.$refs.crud.doLayout()
  321. })
  322. //删除 提单号
  323. if (this.billData.optionType !== "JK") {
  324. this.option.column.forEach(item => {
  325. if (item.prop === "billNo") {
  326. item.hide = true
  327. } else {
  328. item.hide = false
  329. }
  330. })
  331. }
  332. },
  333. currencyChange(row) {
  334. this.currencyDic.forEach(item => {
  335. if (item.dictValue === row.currency) {
  336. row.exchangeRate = item.remark
  337. }
  338. })
  339. },
  340. rowCell(row, index) {
  341. // this.$refs.crud.rowCell(row, index)
  342. if (row.$cellEdit == true) {
  343. this.$set(row, '$cellEdit', false)
  344. } else {
  345. this.$set(row, '$cellEdit', true)
  346. }
  347. },
  348. rowDel(row, index) {
  349. this.$confirm("确定将选择数据删除?", {
  350. confirmButtonText: "确定",
  351. cancelButtonText: "取消",
  352. type: "warning"
  353. }).then(() => {
  354. this.data.splice(index, 1);
  355. })
  356. },
  357. rowUpdate(row, index, done, loading) {
  358. done(row);
  359. },
  360. entering() {
  361. if (this.data.length !== 0) {
  362. //取第一条数据的 合同号 以及客户
  363. let params = {
  364. ...this.billData,
  365. srcOrderno: this.data[0].srcOrderno,
  366. corpId: this.data[0].corpId
  367. }
  368. this.$refs.crud.rowCellAdd(params);
  369. } else {
  370. this.$refs.crud.rowCellAdd(this.billData);
  371. }
  372. },
  373. onLoad(page, params = {}) {
  374. this.historyLoading = true;
  375. params.srcParentId = this.billId
  376. params.flag = 1
  377. getBillList(page.currentPage, page.pageSize, params).then(res => {
  378. this.historyDataList = res.data.data.records
  379. }).finally(() => {
  380. this.historyLoading = false;
  381. })
  382. },
  383. async forData() {
  384. if (this.addBut) {
  385. let amountSum = 0
  386. for (let item in this.data) {
  387. amountSum += Number(this.data[item].amount)
  388. }
  389. let res = await getApplyAmount({ srcBillId: this.srcBillId, billType: "申请" })
  390. if ((Number(this.form.debitAmount) - Number(res.data.data)) <= amountSum) {
  391. return true
  392. }
  393. } else {
  394. for (let item in this.data) {
  395. let res = await getApplyAmount({ srcBillId: this.data[item].itemId, billType: "申请" })
  396. if ((Number(this.data[item].itemorderAmount) - Number(res.data.data)) <= this.data[item].amount) {
  397. return this.data[item].srcOrderno
  398. }
  399. }
  400. }
  401. },
  402. async submit() {
  403. for (let i = 0; i < this.data.length; i++) {
  404. if (this.corpId === (null || "")) {
  405. return this.$message.error(`请输入第${i + 1}行的客户`);
  406. }
  407. if (this.data[i].costType === (null || "")) {
  408. return this.$message.error(`请输入第${i + 1}行的费用名称`);
  409. }
  410. if (this.data[i].accDate === (null || "")) {
  411. return this.$message.error(`请输入第${i + 1}行的合同日期`);
  412. }
  413. if (this.data[i].amount === (null || "")) {
  414. return this.$message.error(`请输入第${i + 1}行的金额`);
  415. }
  416. if (this.data[i].currency === (null || "")) {
  417. return this.$message.error(`请输入第${i + 1}行的币别`);
  418. }
  419. if (this.data[i].exchangeRate === (null || "")) {
  420. return this.$message.error(`请输入第${i + 1}行的汇率`);
  421. }
  422. if (this.data[i].taxRate === (null || "")) {
  423. return this.$message.error(`请输入第${i + 1}行的税率`);
  424. }
  425. }
  426. let forData = await this.forData()
  427. if (forData) {
  428. if (this.addBut) {
  429. return this.$message.error('已付费金额大于货款')
  430. } else {
  431. return this.$message.error('合同号:' + forData + '已付费金额大于货款')
  432. }
  433. }
  434. // if (forData) {
  435. // return this.$message.error('已付费金额大于货款')
  436. // }else{
  437. // return this.$message.error('合同号:' + forData + '已付费金额大于货款')
  438. // }
  439. this.submitButton = true
  440. const itemsList = this.data.map(item => {
  441. item.corpId = this.corpId;
  442. item.tradeType = this.billData.optionType ? this.billData.optionType : item.tradeType;
  443. item.srcType = item.srcType ? item.srcType : this.srcType;
  444. return item;
  445. })
  446. const params = {
  447. url: this.checkData.url,
  448. pageStatus: this.checkData.pageStatus,
  449. pageLabel: this.checkData.pageLabel,
  450. checkType: this.checkData.checkType,
  451. billType: this.billType,
  452. tradeType: this.tradeType,
  453. DC: this.billData.itemType === "采购" ? "C" : "D", //账单明细会根据D C区分采购 销售搜索
  454. itemsList: itemsList,
  455. belongCompany: this.belongCompany // 所属公司
  456. }
  457. // 采购申请货款 销售申请退款 都会走申请 走审核 => 付款申请
  458. if (this.billType === "申请") {
  459. applyLoan(params).then(res => {
  460. if (res.data.success) {
  461. this.$message.success("操作成功!")
  462. this.$emit("choceFun");
  463. this.$emit("submit")
  464. //跳转付款申请页面
  465. // if(this.$store.getters.pqStatus){
  466. // this.$alert("无法自动跳,因为付费申请页面已存在!", "温馨提示", {
  467. // confirmButtonText: "确定",
  468. // type: 'warning',
  469. // callback: action => {
  470. // }
  471. // });
  472. // }else{
  473. // //关闭一下存在的列表页 跳转
  474. // this.$router.$avueRouter.closeTag('/financialManagement/paymentRequest/index');
  475. // this.$router.push({
  476. // path: "/financialManagement/paymentRequest/index",
  477. // query: {params: res.data.data.id},
  478. // });
  479. // }
  480. }
  481. }).finally(() => {
  482. this.submitButton = false
  483. })
  484. }
  485. //采购退款结算 销售收款结算 不需申请请核 直接结算 => 结算
  486. if (this.billType === "收费") {
  487. paymentApply(params).then(res => {
  488. if (res.data.success) {
  489. this.$message.success("操作成功!")
  490. this.$emit("choceFun");
  491. this.$emit("submit")
  492. }
  493. }).finally(() => {
  494. this.submitButton = false
  495. })
  496. }
  497. },
  498. saveColumn() {
  499. },
  500. resetColumn() {
  501. },
  502. amountChange(row) {
  503. if (!row.quantity) {
  504. row.quantity = 0;
  505. }
  506. if (!row.price) {
  507. row.price = 0;
  508. }
  509. row.amount = Number(row.price) * Number(row.quantity)
  510. },
  511. // 客户、费用弹窗
  512. openDialog(row, index, type) {
  513. this.rowData = {
  514. ...row,
  515. index
  516. }
  517. // 1客户 2费用
  518. if (type == 1) {
  519. this.corpTreeOption.treeLoad = function (node, resolve) {
  520. const parentId = node.level === 0 ? 0 : node.data.id;
  521. getDeptLazyTree({
  522. parentId: parentId,
  523. corpType: "KG"
  524. }).then(res => {
  525. resolve(
  526. res.data.data.map(item => {
  527. return {
  528. ...item,
  529. leaf: !item.hasChildren
  530. };
  531. })
  532. );
  533. });
  534. };
  535. this.corpVisible = !this.corpVisible;
  536. } else if (type == 2) {
  537. this.feeVisible = !this.feeVisible;
  538. }
  539. },
  540. selectionChange(list) {
  541. this.selectionList = list;
  542. },
  543. closeCorp() {
  544. this.selectionList = [];
  545. this.treeCorpId = "";
  546. this.reData = null;
  547. },
  548. corpNodeClick(data) {
  549. this.treeCorpId = data.id;
  550. this.corpPage.currentPage = 1;
  551. this.corpOnLoad(this.corpPage);
  552. },
  553. //列表内展开树节点
  554. corpTreeLoad(tree, treeNode, resolve) {
  555. const parentId = tree.id;
  556. customerList({ parentId: parentId }).then(res => {
  557. resolve(res.data.data.records);
  558. });
  559. },
  560. //点击搜索按钮触发
  561. corpSearchChange(params, done) {
  562. this.corpPage.currentPage = 1;
  563. this.corpOnLoad(this.corpPage, params);
  564. done();
  565. },
  566. corpSearchReset() {
  567. this.treeCorpId = null;
  568. },
  569. corpSizeChange(val) {
  570. this.corpPage.pageSize = val;
  571. this.corpOnLoad();
  572. },
  573. corpCurrentChange(val) {
  574. this.corpPage.currentPage = val;
  575. this.corpOnLoad();
  576. },
  577. corpRefreshChange() {
  578. this.corpOnLoad(this.corpPage, this.corpSearch);
  579. },
  580. corpOnLoad(page, params = { parentId: 0 }) {
  581. let queryParams = Object.assign({}, params, {
  582. size: page.pageSize,
  583. current: page.currentPage,
  584. corpsTypeId: this.treeDeptId,
  585. corpType: 'KG'
  586. });
  587. this.dialogLoading = true;
  588. customerList(queryParams).then(res => {
  589. this.corpData = res.data.data.records;
  590. this.corpPage.total = res.data.data.total;
  591. if (this.corpPage.total) {
  592. this.KHOption.height = window.innerHeight - 350;
  593. }
  594. })
  595. .finally(() => {
  596. this.dialogLoading = false;
  597. });
  598. },
  599. importCorp() {
  600. // item.srcFeesId = item.id
  601. this.corpData.forEach((item, index) => {
  602. if (index == this.rowData.index) {
  603. item.corpId = this.selectionList[0].id;
  604. }
  605. })
  606. this.corpVisible = false;
  607. },
  608. getFeeValue(row, value) {
  609. this.$set(row, 'costName', value.cname)
  610. }
  611. }
  612. }
  613. </script>
  614. <style scoped lang="scss">
  615. .required_fields {
  616. color: #F56C6C;
  617. display: inline-block;
  618. width: 7%
  619. }
  620. </style>