snow há 2 anos atrás
pai
commit
926cc1e1ff

+ 4 - 0
src/api/InvoiceSales/invoiceApply/index.ts

@@ -46,3 +46,7 @@ export const httpUpload = (data: object): ResponseType => {
 export const httpCompanyList = (data: object): any => {
   return http.request("post", `${yewuApi}companylist`, { data });
 };
+
+export const httpBack = (data: object): any => {
+  return http.request("post", `${yewuApi}ticketedit`, { data });
+};

+ 30 - 24
src/components/ReconciliationForm/src/cpns/purchase-modal.vue

@@ -4,8 +4,6 @@ import { reactive, ref, unref } from "vue";
 import { useAsync } from "/@/hooks/core/useAsync";
 import { httpCgdList } from "/@/api/purchase/orderRecord";
 import { selectOptions as _selectOptions } from "../_options";
-import { useDebounceFn } from "@vueuse/core";
-
 
 import {
   send_status_list,
@@ -35,6 +33,7 @@ const {
 
 const formData = ref<Record<string, any>>({
   timer: [],
+  qrdCode: "",
   sequenceNo: "",
   cxCode: "",
   goodNo: "",
@@ -85,7 +84,8 @@ function handleReset() {
     sendstatus: "",
     cgdsource: "",
     cgdtype: "",
-    code: ""
+    code: "",
+    qrdCode: ""
   };
   handleSearch();
 }
@@ -155,13 +155,21 @@ defineExpose({
       <ElCol :span="6">
         <ElInput
           size="small"
-          placeholder="商品编号"
-          v-model="formData.goodNo"
+          placeholder="确认单编号"
+          v-model="formData.qrdCode"
         />
       </ElCol>
     </ElRow>
 
     <ElRow :gutter="5" mb-2>
+      <ElCol :span="6">
+        <ElInput
+          size="small"
+          placeholder="商品编号"
+          v-model="formData.goodNo"
+        />
+      </ElCol>
+
       <ElCol :span="6">
         <ElInput
           size="small"
@@ -194,28 +202,26 @@ defineExpose({
           />
         </ElSelect>
       </ElCol>
-
-      <ElCol :span="6">
-        <ElSelect
-          v-model="formData.cgdsource"
-          size="small"
-          placeholder="订单来源"
-          clearable
-          w-full
-        >
-          <ElOption
-            v-for="c in cg_order_source_options"
-            :key="c.value"
-            :label="c.label"
-            :value="c.value"
-          />
-        </ElSelect>
-      </ElCol>
     </ElRow>
 
     <ElRow mb-2>
       <div w-full flex justify-between>
-        <ElCol :span="6">
+        <ElCol :span="12" style="display: flex; gap: 10px">
+          <ElSelect
+            v-model="formData.cgdsource"
+            size="small"
+            placeholder="订单来源"
+            clearable
+            w-full
+          >
+            <ElOption
+              v-for="c in cg_order_source_options"
+              :key="c.value"
+              :label="c.label"
+              :value="c.value"
+            />
+          </ElSelect>
+
           <ElSelect
             v-model="formData.cgdtype"
             size="small"
@@ -252,7 +258,7 @@ defineExpose({
       <ElTableColumn type="selection" width="55" />
       <ElTableColumn label="采购单编号" prop="sequenceNo" width="150" />
       <ElTableColumn label="采购主单编号" prop="cxCode" width="150" />
-      <ElTableColumn label="采购单编号" prop="qrdCode" width="150" />
+      <ElTableColumn label="确认单编号" prop="qrdCode" width="150" />
       <ElTableColumn label="采购单信息">
         <ElTableColumn
           label="供货商"

+ 1 - 2
src/store/modules/user.ts

@@ -6,6 +6,7 @@ import { routerArrays } from "/@/layout/types";
 import { storageSession } from "@pureadmin/utils";
 import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
 import { getRelaComName, getRelaComNo, setRelaComName } from "/@/utils/auth";
+import { removeMenus } from "/@/store/modules/permission";
 
 import {
   getLogin,
@@ -27,8 +28,6 @@ import {
   removeAction
 } from "/@/utils/auth";
 
-import { removeMenus } from "/@/store/modules/permission";
-
 export const useUserStore = defineStore({
   id: "pure-user",
   state: (): userType => ({

+ 303 - 0
src/views/InvoiceSales/invoiceApply/components/back-modal.vue

@@ -0,0 +1,303 @@
+<script setup lang="ts">
+import { ElMessage, dayjs, ElForm } from "element-plus";
+import { computed, reactive, ref, watchEffect } from "vue";
+import { input_type_list } from "../status";
+import { xs_inv_type_list } from "/@/utils/status";
+import { httpBack } from "/@/api/InvoiceSales/invoiceApply";
+import { isnumber } from "/@/utils/validate";
+
+const map = {
+  "10": "electronic", //电子普通发票
+  "20": "special_electronic", //电子专用发票
+  "01": "special", //普通专用发票
+  "04": "normal" //普通发票
+};
+
+const invType = ref("");
+const invNo = ref("");
+const visible = ref(false);
+
+const formRef = ref<InstanceType<typeof ElForm>>(null);
+const emit = defineEmits(["refresh"]);
+
+const rules = reactive({
+  inv_code: [
+    {
+      required: true,
+      message: "发票代码格式不正确",
+      trigger: "blur",
+      validator(_, value) {
+        if (!value) {
+          return new Error("发票代码不能为空");
+        }
+
+        return isnumber(value);
+      }
+    }
+  ],
+  inv_number: [
+    {
+      required: true,
+      message: "发票号码格式不正确",
+      trigger: "blur",
+      validator(_, value) {
+        if (!value) {
+          return new Error("发票号码不能为空");
+        }
+
+        return isnumber(value);
+      }
+    }
+  ],
+  open_date: [
+    {
+      required: true,
+      message: "请选择开票日期",
+      trigger: "change"
+    }
+  ],
+  inv_total: [
+    {
+      required: true,
+      message: "请输入税后金额",
+      trigger: "blur"
+    }
+  ],
+
+  inv_subtotal: [
+    {
+      required: true,
+      message: "请输入税前金额",
+      trigger: "blur"
+    }
+  ],
+  check_code: [
+    {
+      required: false,
+      message: "请输入校验码",
+      trigger: "change"
+    }
+  ]
+});
+
+const scanInvType = ref("");
+const disabled = computed(() => formData.input_type === "1");
+const loading = ref(false);
+const scanInputValue = ref("");
+const formData = reactive({
+  input_type: "1",
+  remark: "",
+  inv_code: "",
+  inv_number: "",
+  open_date: null,
+  inv_subtotal: 0,
+  check_code: ""
+});
+
+function handleSaveStatus() {
+  formRef.value.validate(async isValid => {
+    if (!isValid) return;
+    const {
+      input_type: _,
+      inv_subtotal,
+      check_code,
+      ...otherParams
+    } = formData;
+    let params: Record<string, string> | null = null;
+
+    const type = map[scanInvType.value];
+
+    if (scanInvType.value && String(invType.value) !== String(type)) {
+      return ElMessage.error("扫描识别的发票类型与开票类型不一致");
+    }
+
+    //线下开票
+    params = {
+      invNo: invNo.value,
+      inv_subtotal: inv_subtotal.toFixed(2),
+      ...(check_code ? { check_code } : {}),
+      ...otherParams
+    };
+
+    loading.value = true;
+    const { code, message } = await httpBack(params);
+    loading.value = false;
+
+    switch (code) {
+      case 0:
+        visible.value = false;
+        emit("refresh");
+        break;
+      default:
+        ElMessage.warning(message);
+        break;
+    }
+  });
+}
+
+function handleScanKeydown(evt: KeyboardEvent) {
+  const { keyCode } = evt;
+  if (keyCode !== 13) return;
+
+  //校验扫描枪值是否含有中文逗号
+  if (scanInputValue.value.indexOf(",") >= 0) {
+    ElMessage.error("不能包含中文逗号");
+    return (scanInputValue.value = "");
+  }
+
+  const result = scanInputValue.value.split(",");
+
+  if (result.length !== 9) {
+    ElMessage.error("扫码枪识别数据格式不正确,请重新扫描。");
+    return;
+  }
+
+  const [_1, invoiceType, ...chunks] = result;
+  const [inv_code, inv_number, subtotal_amount, open_time, check_code] = chunks;
+
+  scanInvType.value = invoiceType;
+  const year = open_time.slice(0, 4);
+  const month = open_time.slice(4, 6);
+  const day = open_time.slice(6);
+
+  formData.inv_code = inv_code;
+  formData.check_code = check_code;
+  formData.inv_number = inv_number;
+  formData.inv_subtotal = Number(subtotal_amount);
+  formData.open_date = dayjs(`${year}-${month}-${day}`).format(
+    "YYYY-MM-DD HH:mm:ss"
+  );
+
+  scanInputValue.value = "";
+}
+
+watchEffect(() => {
+  rules.check_code[0].required =
+    invType.value === "normal" || invType.value === "electronic";
+});
+
+watchEffect(() => {
+  const { input_type } = formData;
+
+  if (input_type === "2") {
+    const source = xs_inv_type_list.find(
+      ({ value }) => value === invType.value
+    );
+    if (source) {
+      scanInvType.value = source.scanValue;
+    }
+  }
+});
+
+defineExpose({
+  onDisplay: (_invType, _invNo) => {
+    visible.value = true;
+    invType.value = _invType;
+    invNo.value = _invNo;
+  }
+});
+</script>
+
+<template>
+  <el-dialog v-model="visible">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="rules"
+      label-width="90px"
+      class="demo-ruleForm"
+      size="small"
+      status-icon
+    >
+      <el-row>
+        <el-col :span="12">
+          <el-form-item label="输入类型" prop="input_type">
+            <el-select
+              v-model="formData.input_type"
+              style="width: 100%"
+              placeholder="菜单类型"
+            >
+              <el-option
+                v-for="(si, sii) in input_type_list"
+                :key="'type' + si.value + sii"
+                :label="si.label"
+                :value="si.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+
+        <el-col
+          :span="24"
+          style="padding: 12px 12px 12px 16px"
+          v-if="formData.input_type === '1'"
+        >
+          <el-input
+            clearable
+            v-model="scanInputValue"
+            :rows="3"
+            type="textarea"
+            placeholder="扫码枪输入处"
+            @keydown="handleScanKeydown"
+          />
+        </el-col>
+      </el-row>
+      <el-form-item label="发票类型">
+        <el-select style="width: 100%" v-model="scanInvType" disabled>
+          <el-option
+            v-for="inv in xs_inv_type_list"
+            :key="inv.scanValue"
+            :value="inv.scanValue"
+            :label="inv.label"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="发票号码" prop="inv_number">
+        <el-input
+          v-model="formData.inv_number"
+          placeholder="发票号码"
+          :disabled="disabled"
+        />
+      </el-form-item>
+      <el-form-item label="发票代码" prop="inv_code">
+        <el-input
+          v-model="formData.inv_code"
+          placeholder="发票代码"
+          :disabled="disabled"
+        />
+      </el-form-item>
+      <el-form-item label="开票日期" prop="open_date">
+        <el-date-picker
+          style="width: 100%"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          v-model="formData.open_date"
+          :disabled="disabled"
+        />
+      </el-form-item>
+
+      <el-form-item label="税前金额" prop="inv_subtotal">
+        <el-input-number
+          v-model="formData.inv_subtotal"
+          :precision="2"
+          style="width: 100%"
+          :min="0"
+          :max="999999"
+          :disabled="disabled"
+        />
+      </el-form-item>
+
+      <el-form-item label="校验码" prop="check_code">
+        <el-input
+          placeholde="请输入校验码"
+          v-model="formData.check_code"
+          :disabled="disabled"
+        />
+      </el-form-item>
+      <div class="flex justify-end">
+        <el-button type="primary" :loading="loading" @click="handleSaveStatus"
+          >保存</el-button
+        >
+      </div>
+    </el-form>
+  </el-dialog>
+</template>

+ 0 - 1
src/views/InvoiceSales/invoiceApply/detail.vue

@@ -63,7 +63,6 @@ const { data: companylist, run: companyRun } = useAsync<
     const [company] = companylist.value || [];
     if (!company) return;
     const { input_ticket } = company;
-    console.log(input_ticket);
     isSupport.value = input_ticket === "1";
   }
 });

+ 11 - 5
src/views/InvoiceSales/invoiceApply/index.vue

@@ -14,14 +14,12 @@ import { httpRequsetExport } from "/@/utils/export";
 import { template } from "./config/xls-template";
 import { writeFile, utils } from "xlsx";
 import { usePermission } from "/@/hooks/core/usePermission";
-
+import BackModal from "./components/back-modal.vue";
 const PageName = "invoiceApply";
 
 const { hasPermissionWithCode } = usePermission(PageName);
 const loading = ref(false);
-
 const baseUrl = "/InvoiceSales/invoiceApplyDetail";
-
 const postModalRef = ref<InstanceType<typeof PostModal> | null>(null);
 const execlUploadRef = ref<InstanceType<typeof ExeclUpload> | null>(null);
 const { isSuperUser } = useUserInfo();
@@ -41,6 +39,8 @@ const handleApproval = ({ invNo }) =>
 const { push } = useRouter();
 const selects = ref<any[]>([]);
 
+const backModalRef = ref<InstanceType<typeof BackModal>>(null);
+
 const hooks: PageHooks = {
   pageSearchHook: () => usePageSearch(undefined, undefined, searchConfig)
 };
@@ -116,7 +116,7 @@ function onDownloadTemplate() {
           >批量导入财务开票结果(发票申请)</ElButton
         >
       </template>
-      <template #content_action="{ status, post_code, invNo }">
+      <template #content_action="{ status, post_code, invNo, inv_type }">
         <ElTooltip
           content="填写物流"
           placement="top"
@@ -151,12 +151,17 @@ function onDownloadTemplate() {
           </template>
         </ElPopconfirm>
 
-        <ElTooltip content="修改发票信息" placement="top">
+        <ElTooltip
+          content="修改发票信息"
+          placement="top"
+          v-if="String(status) === '5' && hasPermissionWithCode('005')"
+        >
           <ElButton
             text
             :icon="useRenderIcon('edit')"
             style="margin-left: 0px"
             type="primary"
+            @click="() => backModalRef.onDisplay(inv_type, invNo)"
           />
         </ElTooltip>
       </template>
@@ -164,5 +169,6 @@ function onDownloadTemplate() {
 
     <PostModal ref="postModalRef" @post-save="handleSetPost" />
     <ExeclUpload ref="execlUploadRef" @on-success="() => instance.onSearch()" />
+    <back-modal ref="backModalRef" @refresh="() => instance.onSearch()" />
   </PageAuth>
 </template>