snow 1 year ago
parent
commit
b71c375cf6

+ 7 - 6
.env.development

@@ -16,18 +16,16 @@ VITE_APP_ID = "ww6076e6fd4268ee31"
 # 微信开发环境基础重定向url
 REDIRECT_BASE_URL = "http://cxinv.api.caixiao365.com"
 # 开发环境后端用户地址
-VITE_PROXY_USER_REAL1 = "http://user.api.caixiao365.com"
+VITE_PROXY_USER_REAL1 = "http://user.test241.wanyuhengtong.com"
 # 开发环境后端用户地址
-VITE_PROXY_USER_REAL = "http://cxinv.api.caixiao365.com"
+VITE_PROXY_USER_REAL = "http://stockinv.test241.wanyuhengtong.com"
 # 开发环境后端业务地址
-VITE_PROXY_DOMAIN_REAL = "http://cxinv.api.caixiao365.com"
+VITE_PROXY_DOMAIN_REAL = "http://stockinv.test241.wanyuhengtong.com"
 
 VITE_IS_PROD = true
 
-# 跳转采销地址
+# 跳转结算地址
 VITE_PURCHASE_URL = 'http://pin.caixiao365.com/'
-# 跳转工单地址
-VITE_GD_URL = 'http://bug.caixiao365.com/'
 
 # 报表地址
 VITE_DASHBOARD_URL = 'http://web.report.caixiao365.com/'
@@ -35,3 +33,6 @@ VITE_DASHBOARD_URL = 'http://web.report.caixiao365.com/'
 # token密钥
 VITE_SECRET_KEY = 'key123'
 
+
+# 跳转工单地址
+VITE_GD_URL = 'http://bug.caixiao365.com/'

+ 1 - 1
.gitignore

@@ -1,6 +1,6 @@
 node_modules
 .DS_Store
-# dist
+dist
 
 
 dist-ssr

+ 9 - 0
src/components/execlUpload/src/execl-upload.vue

@@ -87,6 +87,7 @@ defineExpose({
     action="#"
     accept=".xls,.xlsx"
     drag
+    class="upload"
     :auto-upload="false"
     @change="handleChange"
     @remove="handleRemove"
@@ -99,6 +100,12 @@ defineExpose({
 </template>
 
 <style lang="scss" scoped>
+.upload {
+  :deep(.el-upload-list){
+    display: none !important;
+  }
+}
+
 .execl-uploader {
   border: 1px dashed var(--el-border-color);
   border-radius: 6px;
@@ -114,6 +121,8 @@ defineExpose({
     border-color: var(--el-color-primary);
   }
 
+
+
   .el-upload__text {
     line-height: 200px;
     font-size: 22px;

+ 4 - 4
src/utils/btnList.ts

@@ -17,7 +17,7 @@ const btnList = [
   { code: "016", name: "添加销售订单回款标签" },
   { code: "017", name: "导出回票数据" },
   { code: "018", name: "批量导入认证结果" },
-  { code: "019", name: "下载回票批量申请模板" },
+  { code: "019", name: "下载认证模板" },
   { code: "020", name: "买方公司财务审核" },
   { code: "021", name: "买方公司认证" },
   { code: "022", name: "撤销对账申请" },
@@ -29,7 +29,7 @@ const btnList = [
   { code: "028", name: "批量导入财务开票结果(发票申请)" },
   { code: "029", name: "下载资金导入模板" },
   { code: "030", name: "批量导入客户付款资金数据" },
-  { code: "031", name: "下载批量开票模板" },
+  { code: "031", name: "批量下载开票模板" },
   { code: "032", name: "导出对账开票数据" },
   { code: "033", name: "批量创建开票数据" },
   { code: "034", name: "下载订单认款导入模板" },
@@ -39,8 +39,8 @@ const btnList = [
   { code: "038", name: "对账单明细导出" },
   { code: "039", name: "买方公司业务审核" },
   { code: "040", name: "批量审核" },
-  { code: "041", name: "采购下载批量设置类目模板" },
-  { code: "042", name: "采购批量导入设置类目结果" },
+  { code: "041", name: "批量下载采购设置类目模板" },
+  { code: "042", name: "批量采购导入设置类目结果" },
   { code: "043", name: "采购设置税务类目" },
   { code: "044", name: "财务设置税务类目" },
   { code: "045", name: "导出商品税率异常记录" },

+ 1 - 1
src/views/InvoiceSaleSettings/commodityCost/index.vue

@@ -57,7 +57,7 @@ function onDownloadTemplate(isProcure = false) {
   }
 
   const judieTemplate = isProcure ? procureTemplate : template
-  const judieFilename = isProcure ? "采购批量设置类目模板" : "财务批量设置类目模板"
+  const judieFilename = isProcure ? "批量设置采购类目模板" : "批量设置财务类目模板"
 
   const data: any[] = [];
   selects.value.forEach((item) => {

+ 1 - 1
src/views/InvoiceSaleSettings/consultingCost/index.vue

@@ -54,7 +54,7 @@ function onDownloadTemplate(isProcure = false) {
   }
 
   const judieTemplate = isProcure ? procureTemplate : template
-  const judieFilename = isProcure ? "采购批量设置类目模板" : "财务批量设置类目模板"
+  const judieFilename = isProcure ? "批量设置采购类目模板" : "批量设置财务类目模板"
 
   const data: any[] = [];
   selects.value.forEach((item) => {

+ 2 - 2
src/views/purchase/buyInvoiceQuery/index.vue

@@ -22,7 +22,7 @@ const invStatus = ["4", "10"];
 
 // { code: "017", name: "导出回票数据" },
 // { code: "018", name: "批量导入认证结果" },
-// { code: "019", name: "下载回票批量申请模板" },
+//  { code: "019", name: "下载认证模板" }
 const { hasPermissionWithCode } = usePermission(PageName);
 const { isSuperUser } = useUserInfo();
 const pageContentRef = ref<InstanceType<typeof PageContent> | null>(null);
@@ -104,7 +104,7 @@ function onDownloadTemplate() {
           v-if="hasPermissionWithCode('019')"
           :icon="useRenderIcon('arrow-down-line')"
           @click="() => onDownloadTemplate()"
-          >下载回票批量申请模板</ElButton
+          >下载认证模板</ElButton
         >
       </template>
 

+ 10 - 0
src/views/purchase/orderRecord/config/xls-template.ts

@@ -0,0 +1,10 @@
+export const template = {
+  卖方公司编码: "",
+  对账编码: "",
+  发票类型: "",
+  发票代码: "",
+  发票号码: "",
+  发票税前金额: "",
+  开票日期: "",
+  "校验码(电子票必填,全电票不需要)": ""
+};

+ 41 - 0
src/views/purchase/orderRecord/index.vue

@@ -10,6 +10,8 @@ import { httpStatus } from "/@/api/purchase/orderRecord";
 import { httpRequsetExport } from "/@/utils/export";
 import { useAsync } from "/@/hooks/core/useAsync";
 import searchConfig from "./config/search.config";
+import { template } from "./config/xls-template";
+import { utils, writeFile } from "xlsx";
 
 const PageName = "orderRecord";
 const baseUrl = "/purchase/orderRecordDetail";
@@ -67,6 +69,37 @@ async function onDownloadPayInfo() {
     }
   });
 }
+
+//导出模板
+function onDownloadTemplate() {
+  if (selectlist.value.length === 0) {
+    ElMessage.error("至少勾选一条对账单");
+    return;
+  }
+
+  const _data: any = [];
+  for (const { status, payNo, supplierNo } of selectlist.value) {
+    if (String(status) !== "2") {
+      ElMessage.error(`对账单 ${payNo},未通过审核`);
+      return;
+    } else {
+      _data.push({
+        ...template,
+        ["卖方公司编码"]: supplierNo,
+        ["对账编码"]: payNo
+      });
+    }
+  }
+  //创建数据表
+  const workBook = utils.book_new();
+  const workSheet = utils.json_to_sheet(_data);
+  utils.book_append_sheet(workBook, workSheet, "sheet");
+
+  //导出模板
+  writeFile(workBook, "批量开票申请模板.xlsx", {
+    bookType: "xlsx"
+  });
+}
 </script>
 
 <template>
@@ -88,6 +121,14 @@ async function onDownloadPayInfo() {
         >
           对账单明细导出
         </ElButton>
+
+       <ElButton
+          size="small"
+          v-if="hasPermissionWithCode('031')"
+          :icon="useRenderIcon('arrow-down-line')"
+          @click="() => onDownloadTemplate()"
+          >批量下载开票模板</ElButton
+        >
       </template>
 
       <template #content_action="row">

+ 46 - 0
src/views/purchase/ticketReturn/components/execl-files-upload-inv/columns-config.ts

@@ -0,0 +1,46 @@
+const initheaders = [
+  "卖方公司编码",
+  "对账编码",
+  "发票类型",
+  "发票代码",
+  "发票号码",
+  "发票税前金额",
+  "开票日期",
+  "校验码(电子票必填,全电票不需要)"
+];
+
+export const mapProp = {
+  value0: "supplierNo",
+  value1: "payNo",
+  value2: "invoiceType",
+  value3: "invoiceCode",
+  value4: "invoiceNumber",
+  value5: "inv_subtotal_amount",
+  value6: "open_time",
+  value7: "checkNumber"
+};
+
+export const requireHeaders = [];
+
+const columns = () => {
+  const list: any[] = [
+    {
+      type: "index",
+      width: "50",
+      fixed: "left",
+      label: "序号"
+    }
+  ];
+  initheaders.forEach((si, sii) => {
+    list.push({
+      prop: "value" + sii,
+      label: si,
+      minWidth: sii === 0 || sii === 1 ? "120px" : "90px"
+    });
+  });
+
+  console.log(list);
+  return list;
+};
+
+export { initheaders, columns };

+ 390 - 0
src/views/purchase/ticketReturn/components/execl-files-upload-inv/index.vue

@@ -0,0 +1,390 @@
+<script setup lang="ts">
+import { ref } from "vue";
+import { ElMessage } from "element-plus";
+import { execlUpload } from "/@/components/execlUpload";
+import { httpBatchAdd } from "/@/api/purchase/ticketReturn";
+import { useResponseHandle } from "/@/hooks";
+import { useCompany } from "/@/hooks/core/useCompany";
+
+import {
+  initheaders,
+  columns,
+  mapProp,
+  requireHeaders
+} from "./columns-config";
+import { cg_inv_type_list } from "/@/utils/status";
+
+const visible = ref(false);
+const loading = ref(false);
+const tableData = ref([]);
+const columnsConfig = columns();
+const emit = defineEmits(["onSuccess"]);
+
+const allTypes = cg_inv_type_list.map(({ label }) => label);
+
+const row = ref(1);
+
+const createInvErrorMessage = (row: string) =>
+  `导入数据第 ${row} 行 发票类型格式不正确,发票类型必须为${allTypes.join(",")}`;
+
+const { currentCompany } = useCompany();
+
+const responseHandle = useResponseHandle();
+
+const Uploadsuccess = ({ results, header }) => {
+  loading.value = true;
+
+  if (results.length === 0) {
+    ElMessage.error("表格无有效数据!");
+    loading.value = false;
+    return;
+  }
+
+  let headok = true;
+  if (header.length !== initheaders.length) {
+    headok = false;
+  } else {
+    initheaders.forEach((si, sii) => {
+      if (si !== header[sii]) {
+        headok = false;
+      }
+    });
+  }
+
+  if (!headok) {
+    ElMessage.error("表头与导入模板不匹配!");
+    loading.value = false;
+    return;
+  }
+
+  tableData.value = [];
+
+  for (const v1 of results) {
+    const b = Object.values(v1);
+    let model = {};
+    b.forEach((si, sii) => {
+      model["value" + sii] = si + "";
+    });
+    tableData.value.push(model);
+    row.value = row.value + 1;
+  }
+
+    const data = [];
+   tableData.value.forEach((key, index) => {
+      const obj: Record<string, string> = {};
+
+      for (let i in key) {
+        const prop = mapProp[i];
+        const value = key[i];
+        obj[prop] = value;
+     }
+      
+      data.push(obj);
+    });
+
+    const typeErrors: string[] = [];
+    const checkErrors: string[] = [];
+    const codeErrors: string[] = [];
+    const numberErrors: string[] = [];
+    const priceErrors: string[] = [];
+
+    data.forEach((row, index) => {
+      const source = row.invoiceType.trim();
+      const target = cg_inv_type_list.find(({ label }) => label === source);
+
+      if (!target) {
+        typeErrors.push(String(index + 1));
+      } else {
+        row.invoiceType = target.value;
+
+        if (
+          (target.value === "normal" || target.value === "electronic") &&
+          !row.checkNumber
+        ) {
+          checkErrors.push(String(index + 1));
+        }
+      }
+
+      const reg = /^\d+(\.\d+)?$/;
+
+      if (!reg.test(row.invoiceCode)) {
+        codeErrors.push(String(index + 1));
+      }
+
+
+      if (!reg.test(row.invoiceNumber)) {
+        numberErrors.push(String(index + 1));
+      }
+
+      if (!reg.test(row.inv_subtotal_amount) || Number(row.inv_subtotal_amount) < 0) {
+        priceErrors.push(String(index + 1));
+      }
+
+    });
+
+    if (typeErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: createInvErrorMessage(typeErrors.join(","))
+      });
+      loading.value = false;
+      return;
+    }
+
+    if (checkErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${checkErrors.join(",")} 行,校验码不能为空。`
+      });
+      loading.value = false;
+      tableData.value = [];
+      return;
+    }
+
+    if (codeErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${codeErrors.join(",")} 行,发票代码必须为数字。`
+      });
+      loading.value = false;
+      tableData.value = [];
+      return;
+    }
+
+
+    if (numberErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${numberErrors.join(",")} 行,发票号码必须为数字。`
+      });
+      loading.value = false;
+      tableData.value = [];
+      return;
+    }
+
+    if (priceErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${priceErrors.join(",")} 行,发票税前金额必须为数字且不能是负数`
+      });
+      loading.value = false;
+      tableData.value = [];
+      return;
+    }
+
+  loading.value = false;
+};
+
+//提交
+const handleSubmit = async () => {
+  try {
+    if (loading.value) return;
+    loading.value = true;
+
+    const data = [];
+
+    tableData.value.forEach((key, index) => {
+      const obj: Record<string, string> = {};
+
+      for (let i in key) {
+        const prop = mapProp[i];
+        const value = key[i];
+        obj[prop] = value;
+      }
+      data.push(obj);
+    });
+
+    const typeErrors: string[] = [];
+    const checkErrors: string[] = [];
+    const codeErrors: string[] = [];
+    const numberErrors: string[] = [];
+    const priceErrors: string[] = [];
+
+    data.forEach((row, index) => {
+      const source = row.invoiceType.trim();
+      const target = cg_inv_type_list.find(({ label }) => label === source);
+
+      if (!target) {
+        typeErrors.push(String(index + 1));
+      } else {
+        row.invoiceType = target.value;
+
+        if (
+          (target.value === "normal" || target.value === "electronic") &&
+          !row.checkNumber
+        ) {
+          checkErrors.push(String(index + 1));
+        }
+      }
+
+      const reg = /^\d+(\.\d+)?$/;
+
+      if (!reg.test(row.invoiceCode)) {
+        codeErrors.push(String(index + 1));
+      }
+
+
+      if (!reg.test(row.invoiceNumber)) {
+        numberErrors.push(String(index + 1));
+      }
+
+      if (!reg.test(row.inv_subtotal_amount) || Number(row.inv_subtotal_amount) < 0) {
+        priceErrors.push(String(index + 1));
+      }
+
+    });
+
+    if (typeErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: createInvErrorMessage(typeErrors.join(","))
+      });
+      loading.value = false;
+      return;
+    }
+
+    if (checkErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${checkErrors.join(",")} 行,校验码不能为空。`
+      });
+      loading.value = false;
+      return;
+    }
+
+    if (codeErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${codeErrors.join(",")} 行,发票代码必须为数字。`
+      });
+      loading.value = false;
+      return;
+    }
+
+
+    if (numberErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${numberErrors.join(",")} 行,发票号码必须为数字。`
+      });
+      loading.value = false;
+      return;
+    }
+
+    if (priceErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${priceErrors.join(",")} 行,发票税前金额必须为数字且不能是负数`
+      });
+      loading.value = false;
+      return;
+    }
+
+    const buyers = data.map(({ supplierNo }) => supplierNo);
+    const setBuyers = [...new Set(buyers)];
+
+    if (setBuyers.length > 1) {
+      ElMessage.error("卖方公司编码不一致");
+      loading.value = false;
+      return;
+    }
+
+    const supplierNo = data[0].supplierNo;
+
+    data.forEach(item => {
+      delete item["supplierNo"];
+    });
+
+    const { code, message } = await httpBatchAdd({
+      list: data,
+      supplierNo,
+      companyNo:currentCompany.value.companyNo,
+      relaComNo: currentCompany.value.companyNo
+    });
+
+    loading.value = false;
+
+    responseHandle({
+      code,
+      message,
+      noMessage: false,
+      handler: () => {
+        ElMessage.success("数据导入成功!");
+        emit("onSuccess");
+        visible.value = false;
+      }
+    });
+  } catch (err) { 
+    console.log(err)
+  }
+};
+const cancel = () => {
+  tableData.value = [];
+};
+defineExpose({
+  onDisplay: () => ((visible.value = true), (tableData.value = []))
+});
+</script>
+
+<template>
+  <el-dialog
+    :close-on-click-modal="false"
+    v-model="visible"
+    title="批量导入开票数据"
+    width="1040px"
+    top="8vh"
+    center
+  >
+    <execlUpload @on-success="Uploadsuccess" v-if="tableData.length === 0" />
+
+    <el-table
+      :data="tableData"
+      stripe
+      border
+      max-height="500px"
+      size="small"
+      style="width: 100%"
+    >
+      <el-table-column
+        v-for="(si, sii) in columnsConfig"
+        :type="si.type"
+        :minWidth="si.minWidth"
+        :fixed="si.fixed"
+        :key="sii"
+        :prop="si.prop"
+        show-overflow-tooltip
+      >
+        <template #header>
+          <span
+            v-if="
+              !requireHeaders.includes(mapProp[si.prop]) || si.label === '序号'
+            "
+            >{{ si.label }}</span
+          >
+          <p v-else>
+            <span style="color: #f56c6c; font-size: 14px">* </span>
+            {{ si.label }}
+          </p>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div
+      flex
+      justify-end
+      gap-2
+      v-if="tableData.length !== 0"
+      style="padding: 10px 0 0 0"
+    >
+      <el-button size="small" @click="cancel">取消</el-button>
+      <el-button
+        size="small"
+        type="primary"
+        :loading="loading"
+        @click="handleSubmit"
+        >保存</el-button
+      >
+    </div>
+  </el-dialog>
+</template>
+
+<style lang="scss" scoped></style>

+ 2 - 0
src/views/purchase/ticketReturn/components/invoice-form.vue

@@ -300,6 +300,8 @@ electronicsHiddens;
       </template>
 
       <el-form-item>
+        <ElTag type="warning" style="margin-left:30px">暂不支持上传负数发票</ElTag>
+
         <div class="justify-end flex w-full">
           <el-button type="primary" :loading="loading" @click="handlCurrentSave"
             >保存当前发票</el-button

+ 55 - 11
src/views/purchase/ticketReturn/config/_rules.ts

@@ -40,15 +40,32 @@ export const invoceRules: FormRules = {
   invNumber: [
     {
       trigger: "blur",
-      message: "请输入发票号码",
-      required: true
+      required: true,
+      validator(_, value, callback) {
+        const reg = /^\d+(\.\d+)?$/;
+        if (value === "") {
+          callback(new Error("发票号码不能为空!"));
+        } else if (!reg.test(value)) {
+          callback(new Error("发票号码必须为数字"));
+        } else {
+          callback();
+        }
+      }
     }
   ],
   invCode: [
     {
-      trigger: "blur",
-      message: "请选择发票代码",
-      required: true
+      required: true,
+      validator(_, value, callback) {
+        const reg = /^\d+(\.\d+)?$/;
+        if (value === "") {
+          callback(new Error("发票代码不能为空!"));
+        } else if (!reg.test(value)) {
+          callback(new Error("发票代码必须为数字"));
+        } else {
+          callback();
+        }
+      }
     }
   ],
   open_time: [
@@ -61,8 +78,17 @@ export const invoceRules: FormRules = {
   subtotal_amount: [
     {
       trigger: "blur",
-      message: "请输入金额",
-      required: true
+      required: true,
+      validator(_, value, callback) {
+        const reg = /^\d+(\.\d+)?$/;
+        if (value === "") {
+          callback(new Error("税前金额不能为空!"));
+        } else if (!reg.test(value)) {
+          callback(new Error("税前金额必须为数字且不能为负数!"));
+        } else {
+          callback();
+        }
+      }
     }
   ],
   invName: [
@@ -106,15 +132,33 @@ export const invoceRules_Electronics: FormRules = {
   invNumber: [
     {
       trigger: "blur",
-      message: "请输入发票号码",
-      required: true
+      required: true,
+      validator(_, value, callback) {
+        const reg = /^\d+(\.\d+)?$/;
+        if (value === "") {
+          callback(new Error("发票号码不能为空!"));
+        } else if (!reg.test(value)) {
+          callback(new Error("发票号码必须为数字"));
+        } else {
+          callback();
+        }
+      }
     }
   ],
   subtotal_amount: [
     {
       trigger: "blur",
-      message: "请输入金额",
-      required: true
+      required: true,
+      validator(_, value, callback) {
+        const reg = /^\d+(\.\d+)?$/;
+        if (value === "") {
+          callback(new Error("税前金额不能为空!"));
+        } else if (!reg.test(value)) {
+          callback(new Error("税前金额必须为数字且不能为负数!"));
+        } else {
+          callback();
+        }
+      }
     }
   ],
   open_time: [

+ 17 - 3
src/views/purchase/ticketReturn/index.vue

@@ -16,13 +16,16 @@ import ExeclUpoad from "./components/execl-files-upload/index.vue";
 import { usePermission } from "/@/hooks/core/usePermission";
 import { useUserInfo } from "/@/hooks/core/useUser";
 
+import ExcelUploadInv from "./components/execl-files-upload-inv/index.vue";
+
+
 const PageName = "ticketReturn";
 const baseUrl = "/purchase/ticketReturnDetail";
 const invStatus = ["4", "10"];
 
 // { code: "017", name: "导出回票数据" },
 // { code: "018", name: "批量导入认证结果" },
-// { code: "019", name: "下载回票批量申请模板" },
+//  { code: "019", name: "下载认证模板" }
 const { hasPermissionWithCode } = usePermission(PageName);
 const { isSuperUser } = useUserInfo();
 const pageContentRef = ref<InstanceType<typeof PageContent> | null>(null);
@@ -37,6 +40,7 @@ const { currentCompany } = useCompany();
 const loading = ref(false);
 const invoiceModalRef = ref<InstanceType<typeof InvoiceModal>>(null);
 const execelUploadRef = ref<InstanceType<typeof ExeclUpoad>>(null);
+const execelUploadInvRef = ref<InstanceType<typeof ExcelUploadInv>>(null);
 const data = ref({ inv_subtotal_amount: "", total: "" });
 async function handleDownload() {
   await httpRequsetExport({
@@ -78,7 +82,7 @@ function onDownloadTemplate() {
   utils.book_append_sheet(workBook, workSheet, "sheet");
 
   //导出模板
-  writeFile(workBook, "回票批量导入模板.xlsx", {
+  writeFile(workBook, "批量导入回票模板.xlsx", {
     bookType: "xlsx"
   });
 }
@@ -111,6 +115,14 @@ function onDownloadTemplate() {
           >导出回票数据</ElButton
         >
 
+        <ElButton
+          size="small"
+          v-if="hasPermissionWithCode('033') && !isSuperUser"
+          :icon="useRenderIcon('arrow-up-line')"
+          @click="() => execelUploadInvRef.onDisplay()"
+          >批量创建开票数据</ElButton
+        >
+
         <ElButton
           size="small"
           v-if="hasPermissionWithCode('018') && !isSuperUser"
@@ -124,7 +136,7 @@ function onDownloadTemplate() {
           v-if="hasPermissionWithCode('019')"
           :icon="useRenderIcon('arrow-down-line')"
           @click="() => onDownloadTemplate()"
-          >下载回票批量申请模板</ElButton
+          >下载认证模板 </ElButton
         >
       </template>
 
@@ -141,5 +153,7 @@ function onDownloadTemplate() {
 
     <InvoiceModal ref="invoiceModalRef" />
     <ExeclUpoad ref="execelUploadRef" />
+
+    <ExcelUploadInv ref="execelUploadInvRef" />
   </PageAuth>
 </template>

+ 2 - 2
src/views/supply/orderRecord/index.vue

@@ -20,7 +20,7 @@ const { push } = useRouter();
 const selectlist = ref<any[]>([]);
 const loading = ref(false);
 
-// { code: "031", name: "下载批量开票模板" }
+// { code: "031", name: "批量下载开票模板" }
 const { hasPermissionWithCode } = usePermission(PageName);
 
 const hooks: PageHooks = {
@@ -128,7 +128,7 @@ const handleRevoke = payNo => {
           v-if="hasPermissionWithCode('031')"
           :icon="useRenderIcon('arrow-down-line')"
           @click="() => onDownloadTemplate()"
-          >下载批量开票模板</ElButton
+          >批量下载开票模板</ElButton
         >
       </template>
 

+ 3 - 3
src/views/supply/sellInvoiceQuery/index.vue

@@ -21,7 +21,7 @@ const invStatus = ["4", "10"];
 
 // { code: "017", name: "导出回票数据" },
 // { code: "018", name: "批量导入认证结果" },
-// { code: "019", name: "下载回票批量申请模板" },
+//   { code: "019", name: "下载认证模板" }
 const { hasPermissionWithCode } = usePermission(PageName);
 const { isSuperUser } = useUserInfo();
 const pageContentRef = ref<InstanceType<typeof PageContent> | null>(null);
@@ -65,7 +65,7 @@ function onDownloadTemplate() {
   utils.book_append_sheet(workBook, workSheet, "sheet");
 
   //导出模板
-  writeFile(workBook, "回票批量导入模板.xlsx", {
+  writeFile(workBook, "批量导入回票模板.xlsx", {
     bookType: "xlsx"
   });
 }
@@ -103,7 +103,7 @@ function onDownloadTemplate() {
           v-if="hasPermissionWithCode('019')"
           :icon="useRenderIcon('arrow-down-line')"
           @click="() => onDownloadTemplate()"
-          >下载回票批量申请模板</ElButton
+          >下载认证模板</ElButton
         >
       </template>
 

+ 229 - 80
src/views/supply/ticketReturn/components/execl-files-upload/index.vue

@@ -56,6 +56,7 @@ const Uploadsuccess = ({ results, header }) => {
     loading.value = false;
     return;
   }
+
   tableData.value = [];
 
   for (const v1 of results) {
@@ -65,108 +66,256 @@ const Uploadsuccess = ({ results, header }) => {
       model["value" + sii] = si + "";
     });
     tableData.value.push(model);
-
     row.value = row.value + 1;
   }
 
+    const data = [];
+   tableData.value.forEach((key, index) => {
+      const obj: Record<string, string> = {};
+
+      for (let i in key) {
+        const prop = mapProp[i];
+        const value = key[i];
+        obj[prop] = value;
+     }
+      
+      data.push(obj);
+    });
+
+    const typeErrors: string[] = [];
+    const checkErrors: string[] = [];
+    const codeErrors: string[] = [];
+    const numberErrors: string[] = [];
+    const priceErrors: string[] = [];
+
+    data.forEach((row, index) => {
+      const source = row.invoiceType.trim();
+      const target = cg_inv_type_list.find(({ label }) => label === source);
+
+      if (!target) {
+        typeErrors.push(String(index + 1));
+      } else {
+        row.invoiceType = target.value;
+
+        if (
+          (target.value === "normal" || target.value === "electronic") &&
+          !row.checkNumber
+        ) {
+          checkErrors.push(String(index + 1));
+        }
+      }
+
+      const reg = /^\d+(\.\d+)?$/;
+
+      if (!reg.test(row.invoiceCode)) {
+        codeErrors.push(String(index + 1));
+      }
+
+
+      if (!reg.test(row.invoiceNumber)) {
+        numberErrors.push(String(index + 1));
+      }
+
+      if (!reg.test(row.inv_subtotal_amount) || Number(row.inv_subtotal_amount) < 0) {
+        priceErrors.push(String(index + 1));
+      }
+
+    });
+
+    if (typeErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: createInvErrorMessage(typeErrors.join(","))
+      });
+      loading.value = false;
+      return;
+    }
+
+    if (checkErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${checkErrors.join(",")} 行,校验码不能为空。`
+      });
+      loading.value = false;
+      tableData.value = [];
+      return;
+    }
+
+    if (codeErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${codeErrors.join(",")} 行,发票代码必须为数字。`
+      });
+      loading.value = false;
+      tableData.value = [];
+      return;
+    }
+
+
+    if (numberErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${numberErrors.join(",")} 行,发票号码必须为数字。`
+      });
+      loading.value = false;
+      tableData.value = [];
+      return;
+    }
+
+    if (priceErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${priceErrors.join(",")} 行,发票税前金额必须为数字且不能是负数`
+      });
+      loading.value = false;
+      tableData.value = [];
+      return;
+    }
+
   loading.value = false;
 };
+
 //提交
 const handleSubmit = async () => {
-  if (loading.value) return;
-  loading.value = true;
+  try {
+    if (loading.value) return;
+    loading.value = true;
 
-  const data = [];
+    const data = [];
 
-  tableData.value.forEach((key, index) => {
-    const obj: Record<string, string> = {};
+    tableData.value.forEach((key, index) => {
+      const obj: Record<string, string> = {};
 
-    for (let i in key) {
-      const prop = mapProp[i];
-      const value = key[i];
-      obj[prop] = value;
-    }
-    data.push(obj);
-  });
-
-  const typeErrors: string[] = [];
-  const checkErrors: string[] = [];
-
-  data.forEach((row, index) => {
-    const source = row.invoiceType.trim();
-    const target = cg_inv_type_list.find(({ label }) => label === source);
-
-    if (!target) {
-      typeErrors.push(String(index + 1));
-    } else {
-      row.invoiceType = target.value;
-
-      if (
-        (target.value === "normal" || target.value === "electronic") &&
-        !row.checkNumber
-      ) {
-        checkErrors.push(String(index + 1));
+      for (let i in key) {
+        const prop = mapProp[i];
+        const value = key[i];
+        obj[prop] = value;
       }
-    }
+      data.push(obj);
+    });
 
-    console.log(row);
-  });
+    const typeErrors: string[] = [];
+    const checkErrors: string[] = [];
+    const codeErrors: string[] = [];
+    const numberErrors: string[] = [];
+    const priceErrors: string[] = [];
+
+    data.forEach((row, index) => {
+      const source = row.invoiceType.trim();
+      const target = cg_inv_type_list.find(({ label }) => label === source);
+
+      if (!target) {
+        typeErrors.push(String(index + 1));
+      } else {
+        row.invoiceType = target.value;
+
+        if (
+          (target.value === "normal" || target.value === "electronic") &&
+          !row.checkNumber
+        ) {
+          checkErrors.push(String(index + 1));
+        }
+      }
 
-  if (typeErrors.length > 0) {
-    ElMessage({
-      type: "error",
-      message: createInvErrorMessage(typeErrors.join(","))
-    });
-    loading.value = false;
-    return;
-  }
+      const reg = /^\d+(\.\d+)?$/;
+
+      if (!reg.test(row.invoiceCode)) {
+        codeErrors.push(String(index + 1));
+      }
+
+
+      if (!reg.test(row.invoiceNumber)) {
+        numberErrors.push(String(index + 1));
+      }
+
+      if (!reg.test(row.inv_subtotal_amount) || Number(row.inv_subtotal_amount) < 0) {
+        priceErrors.push(String(index + 1));
+      }
 
-  if (checkErrors.length > 0) {
-    ElMessage({
-      type: "error",
-      message: `第 ${checkErrors.join(",")} 行,校验码不能为空。`
     });
-    loading.value = false;
-    return;
-  }
 
-  const buyers = data.map(({ supplierNo }) => supplierNo);
-  const setBuyers = [...new Set(buyers)];
+    if (typeErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: createInvErrorMessage(typeErrors.join(","))
+      });
+      loading.value = false;
+      return;
+    }
 
-  if (setBuyers.length > 1) {
-    ElMessage.error("卖方公司编码不一致");
-    loading.value = false;
-    return;
-  }
+    if (checkErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${checkErrors.join(",")} 行,校验码不能为空。`
+      });
+      loading.value = false;
+      return;
+    }
 
-  // if (setBuyers[0] !== currentCompany.value.companyNo) {
-  //   ElMessage.error("卖方公司编码与当前选择的公司不一致");
-  //   loading.value = false;
-  //   return;
-  // }
+    if (codeErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${codeErrors.join(",")} 行,发票代码必须为数字。`
+      });
+      loading.value = false;
+      return;
+    }
 
-  data.forEach(item => {
-    delete item["supplierNo"];
-  });
 
-  const { code, message } = await httpBatchAdd({
-    list: data,
-    companyNo: currentCompany.value.companyNo,
-    relaComNo: currentCompany.value.companyNo
-  });
+    if (numberErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${numberErrors.join(",")} 行,发票号码必须为数字。`
+      });
+      loading.value = false;
+      return;
+    }
 
-  loading.value = false;
+    if (priceErrors.length > 0) {
+      ElMessage({
+        type: "error",
+        message: `第 ${priceErrors.join(",")} 行,发票税前金额必须为数字且不能是负数`
+      });
+      loading.value = false;
+      return;
+    }
 
-  responseHandle({
-    code,
-    message,
-    noMessage: false,
-    handler: () => {
-      ElMessage.success("数据导入成功!");
-      emit("onSuccess");
-      visible.value = false;
+    const buyers = data.map(({ supplierNo }) => supplierNo);
+    const setBuyers = [...new Set(buyers)];
+
+    if (setBuyers.length > 1) {
+      ElMessage.error("卖方公司编码不一致");
+      loading.value = false;
+      return;
     }
-  });
+
+    const companyNo = data[0].supplierNo;
+
+    data.forEach(item => {
+      delete item["supplierNo"];
+    });
+
+    const { code, message } = await httpBatchAdd({
+      list: data,
+      companyNo
+      // relaComNo: currentCompany.value.companyNo
+    });
+
+    loading.value = false;
+
+    responseHandle({
+      code,
+      message,
+      noMessage: false,
+      handler: () => {
+        ElMessage.success("数据导入成功!");
+        emit("onSuccess");
+        visible.value = false;
+      }
+    });
+  } catch (err) { 
+    console.log(err)
+  }
 };
 const cancel = () => {
   tableData.value = [];
@@ -180,7 +329,7 @@ defineExpose({
   <el-dialog
     :close-on-click-modal="false"
     v-model="visible"
-    title="导入批量开票数据"
+    title="批量导入开票数据"
     width="1040px"
     top="8vh"
     center

+ 2 - 0
src/views/supply/ticketReturn/components/invoice-form.vue

@@ -300,6 +300,8 @@ electronicsHiddens;
       </template>
 
       <el-form-item>
+        <ElTag type="warning" style="margin-left:30px">暂不支持上传负数发票</ElTag>
+
         <div class="justify-end flex w-full">
           <el-button type="primary" :loading="loading" @click="handlCurrentSave"
             >保存当前发票</el-button

+ 55 - 11
src/views/supply/ticketReturn/config/_rules.ts

@@ -40,15 +40,32 @@ export const invoceRules: FormRules = {
   invNumber: [
     {
       trigger: "blur",
-      message: "请输入发票号码",
-      required: true
+      required: true,
+      validator(_, value, callback) {
+        const reg = /^\d+(\.\d+)?$/;
+        if (value === "") {
+          callback(new Error("发票号码不能为空!"));
+        } else if (!reg.test(value)) {
+          callback(new Error("发票号码必须为数字"));
+        } else {
+          callback();
+        }
+      }
     }
   ],
   invCode: [
     {
-      trigger: "blur",
-      message: "请选择发票代码",
-      required: true
+      required: true,
+      validator(_, value, callback) {
+        const reg = /^\d+(\.\d+)?$/;
+        if (value === "") {
+          callback(new Error("发票代码不能为空!"));
+        } else if (!reg.test(value)) {
+          callback(new Error("发票代码必须为数字"));
+        } else {
+          callback();
+        }
+      }
     }
   ],
   open_time: [
@@ -61,8 +78,17 @@ export const invoceRules: FormRules = {
   subtotal_amount: [
     {
       trigger: "blur",
-      message: "请输入金额",
-      required: true
+      required: true,
+      validator(_, value, callback) {
+        const reg = /^\d+(\.\d+)?$/;
+        if (value === "") {
+          callback(new Error("税前金额不能为空!"));
+        } else if (!reg.test(value)) {
+          callback(new Error("税前金额必须为数字且不能为负数!"));
+        } else {
+          callback();
+        }
+      }
     }
   ],
   invName: [
@@ -106,15 +132,33 @@ export const invoceRules_Electronics: FormRules = {
   invNumber: [
     {
       trigger: "blur",
-      message: "请输入发票号码",
-      required: true
+      required: true,
+      validator(_, value, callback) {
+        const reg = /^\d+(\.\d+)?$/;
+        if (value === "") {
+          callback(new Error("发票号码不能为空!"));
+        } else if (!reg.test(value)) {
+          callback(new Error("发票号码必须为数字"));
+        } else {
+          callback();
+        }
+      }
     }
   ],
   subtotal_amount: [
     {
       trigger: "blur",
-      message: "请输入金额",
-      required: true
+      required: true,
+      validator(_, value, callback) {
+        const reg = /^\d+(\.\d+)?$/;
+        if (value === "") {
+          callback(new Error("税前金额不能为空!"));
+        } else if (!reg.test(value)) {
+          callback(new Error("税前金额必须为数字且不能为负数!"));
+        } else {
+          callback();
+        }
+      }
     }
   ],
   open_time: [

+ 1 - 1
src/views/supplyInvoiceSaleSettings/supplyCommodityCost/index.vue

@@ -57,7 +57,7 @@ function onDownloadTemplate(isProcure = false) {
   }
 
   const judieTemplate = isProcure ? procureTemplate : template
-  const judieFilename = isProcure ? "采购批量设置类目模板" : "财务批量设置类目模板"
+  const judieFilename = isProcure ? "批量设置采购类目模板" : "批量设置财务类目模板"
 
   const data: any[] = [];
   selects.value.forEach((item) => {

+ 1 - 1
src/views/supplyInvoiceSaleSettings/supplyConsultingCost/index.vue

@@ -54,7 +54,7 @@ function onDownloadTemplate(isProcure = false) {
   }
 
   const judieTemplate = isProcure ? procureTemplate : template
-  const judieFilename = isProcure ? "采购批量设置类目模板" : "财务批量设置类目模板"
+  const judieFilename = isProcure ? "批量设置采购类目模板" : "批量设置财务类目模板"
 
   const data: any[] = [];
   selects.value.forEach((item) => {