Browse Source

更新商务审核和财务审核页面通用组件

master
wanggang 1 year ago
parent
commit
8da897893b
  1. 2
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/inventory/adjust.js
  2. 2
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/inventory/log.js
  3. 134
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/jis-bbac/settlement/bbac_ba_service.js
  4. 134
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/jis-hbpo/settlement/hbpo_ba_service.js
  5. 27
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/pub_ba_service.js
  6. 9
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/router/business.js
  7. 473
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/_check.js
  8. 13
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/bj/settlement/bj_pub_ba_service.js
  9. 13
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/in/settlement/in_pub_ba_service.js
  10. 486
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/invoice/invoice_map_group.js
  11. 15
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/jis-bbac/settlement/bbac_ba_service.js
  12. 15
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/jis-hbpo/settlement/hbpo_ba_service.js
  13. 15
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/jit/jit-bbac/settlement/bbac_jit_pub_ba_service.js
  14. 13
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/jit/jit-hbpo/settlement/hbpo_jit_pub_ba_service.js
  15. 13
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/md/md-hbpo/settlement/hbpo_md_pub_ba_service.js
  16. 102
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAppService.cs

2
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/inventory/adjust.js

@ -125,7 +125,7 @@ const detailsUrl = `${baseUrl}/get/%s`;
const createUrl = "settleaccount/vmi/edit-balance"; const createUrl = "settleaccount/vmi/edit-balance";
const updateUrl = `${baseUrl}/update/%s`; const updateUrl = `${baseUrl}/update/%s`;
const deleteUrl = `${baseUrl}/delete-list`; const deleteUrl = `${baseUrl}/delete-list`;
const importUrl = `${baseUrl}/code-setting-upload-excel-import`; const importUrl = `${baseUrl}/import`;
const exportUrl = `${baseUrl}/export`; const exportUrl = `${baseUrl}/export`;
const queryMethod = "POST"; const queryMethod = "POST";
const detailsMethod = "POST"; const detailsMethod = "POST";

2
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/inventory/log.js

@ -109,7 +109,7 @@ const detailsUrl = `${baseUrl}/get/%s`;
const createUrl = `${baseUrl}/create`; const createUrl = `${baseUrl}/create`;
const updateUrl = `${baseUrl}/update/%s`; const updateUrl = `${baseUrl}/update/%s`;
const deleteUrl = `${baseUrl}/delete-list`; const deleteUrl = `${baseUrl}/delete-list`;
const importUrl = `${baseUrl}/code-setting-upload-excel-import`; const importUrl = `${baseUrl}/log-import`;
const exportUrl = `${baseUrl}/log-export`; const exportUrl = `${baseUrl}/log-export`;
const queryMethod = "POST"; const queryMethod = "POST";
const detailsMethod = "POST"; const detailsMethod = "POST";

134
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/jis-bbac/settlement/bbac_ba_service.js

@ -1,134 +0,0 @@
import version from "../../version.js";
import { state2 as state, state3 } from "../../state.js";
import businessType from "../../businessType.js";
import invoiceState from "../../invoiceState.js";
const schema = {
title: "商务审批",
type: "object",
properties: {
version,
realnvBillNum: {
title: "金税发票号",
type: "string",
},
invbillNum: {
title: "系统发票号",
type: "string",
},
amt: {
title: "未税金额",
type: "number",
},
taxAmt: {
title: "税后金额",
type: "number",
},
invGroupNum: {
title: "发票分组号",
type: "number",
},
businessType,
state,
invoiceState,
taxDiff: {
title: "发票税后尾差",
type: "number",
},
clientCode: {
title: "客户代码",
type: "string",
},
},
};
const queryUrl = "settleaccount/bbac_ba_service/main-query";
const exportUrl = "settleaccount/bbac_ba_service/export";
const invoiceUrl = "settleaccount/bbac_ba_service/generate-invoice";
const receivedUrl = "settleaccount/bbac_ba_service/received";
const rejectUrl = "settleaccount/bbac_ba_service/reject";
const reissueUrl = "settleaccount/bbac_ba_service/reissue-invoice";
const queryMethod = "POST";
const exportMethod = "POST";
const invoiceMethod = "POST";
const receivedMethod = "POST";
const rejectMethod = "POST";
const reissueMethod = "POST";
export default function () {
return {
query: {
url: queryUrl,
method: queryMethod,
hasFilter: true,
schema: {
title: "商务审批",
type: "object",
properties: {
filters: {
title: "项目",
type: "array",
hidden: true,
items: {
type: "object",
properties: {
logic: {
type: "int",
},
column: {
type: "string",
},
action: {
type: "int",
},
value: {
type: "string",
},
},
},
default: [
{
logic: "and",
column: "version",
action: "equal",
value: null,
readOnly: true,
},
],
},
skipCount: {
hidden: true,
default: 0,
},
maxResultCount: {
hidden: true,
default: 10,
},
sorting: {
hidden: true,
},
businessType: {
hidden: true,
default: 0,
},
},
},
},
table: {
schema: schema,
},
edit: {
exportUrl,
invoiceUrl,
receivedUrl,
rejectUrl,
reissueUrl,
exportMethod,
invoiceMethod,
receivedMethod,
rejectMethod,
reissueMethod,
schema: schema,
},
};
}

134
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/jis-hbpo/settlement/hbpo_ba_service.js

@ -1,134 +0,0 @@
import version from "../../version.js";
import { state2 as state, state3 } from "../../state.js";
import businessType from "../../businessType.js";
import invoiceState from "../../invoiceState.js";
const schema = {
title: "不可结算单",
type: "object",
properties: {
version,
realnvBillNum: {
title: "金税发票号",
type: "string",
},
invbillNum: {
title: "系统发票号",
type: "string",
},
amt: {
title: "未税金额",
type: "number",
},
taxAmt: {
title: "税后金额",
type: "number",
},
invGroupNum: {
title: "发票分组号",
type: "number",
},
businessType,
state,
invoiceState,
taxDiff: {
title: "发票税后尾差",
type: "number",
},
clientCode: {
title: "客户代码",
type: "string",
},
},
};
const queryUrl = "settleaccount/hbpo_ba_service/main-query";
const exportUrl = "settleaccount/hbpo_ba_service/export";
const invoiceUrl = "settleaccount/hbpo_ba_service/generate-invoice";
const receivedUrl = "settleaccount/hbpo_ba_service/received";
const rejectUrl = "settleaccount/hbpo_ba_service/reject";
const reissueUrl = "settleaccount/hbpo_ba_service/reissue-invoice";
const queryMethod = "POST";
const exportMethod = "POST";
const invoiceMethod = "POST";
const receivedMethod = "POST";
const rejectMethod = "POST";
const reissueMethod = "POST";
export default function () {
return {
query: {
url: queryUrl,
method: queryMethod,
hasFilter: true,
schema: {
title: "不可结算单",
type: "object",
properties: {
filters: {
title: "项目",
type: "array",
hidden: true,
items: {
type: "object",
properties: {
logic: {
type: "int",
},
column: {
type: "string",
},
action: {
type: "int",
},
value: {
type: "string",
},
},
},
default: [
{
logic: "and",
column: "version",
action: "equal",
value: null,
readOnly: true,
},
],
},
skipCount: {
hidden: true,
default: 0,
},
maxResultCount: {
hidden: true,
default: 10,
},
sorting: {
hidden: true,
},
businessType: {
hidden: true,
default: 0,
},
},
},
},
table: {
schema: schema,
},
edit: {
exportUrl,
invoiceUrl,
receivedUrl,
rejectUrl,
reissueUrl,
exportMethod,
invoiceMethod,
receivedMethod,
rejectMethod,
reissueMethod,
schema: schema,
},
};
}

27
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/pub_ba_service.js

@ -4,7 +4,7 @@ import businessType from "./businessType.js";
import invoiceState from "./invoiceState.js"; import invoiceState from "./invoiceState.js";
const schema = { const schema = {
title: "不可结算单", title: "商务审批",
type: "object", type: "object",
properties: { properties: {
version, version,
@ -15,6 +15,7 @@ const schema = {
invbillNum: { invbillNum: {
title: "系统发票号", title: "系统发票号",
type: "string", type: "string",
link: true,
}, },
amt: { amt: {
title: "未税金额", title: "未税金额",
@ -27,6 +28,7 @@ const schema = {
invGroupNum: { invGroupNum: {
title: "发票分组号", title: "发票分组号",
type: "number", type: "number",
link: true,
}, },
businessType, businessType,
state, state,
@ -41,16 +43,19 @@ const schema = {
}, },
}, },
}; };
const queryUrl = "settleaccount/pub_ba_service/main-query";
const exportUrl = "settleaccount/pub_ba_service/export"; const queryUrl = "settleaccount/bbac_ba_service/main-query";
const invoiceUrl = "settleaccount/pub_ba_service/generate-invoice"; const exportUrl = "settleaccount/bbac_ba_service/export";
const rejectUrl = "settleaccount/pub_ba_service/reject"; const invoiceUrl = "settleaccount/bbac_ba_service/generate-invoice";
const receivedUrl = "settleaccount/pub_ba_service/received"; const receivedUrl = "settleaccount/bbac_ba_service/received";
const rejectUrl = "settleaccount/bbac_ba_service/reject";
const reissueUrl = "settleaccount/bbac_ba_service/reissue-invoice";
const queryMethod = "POST"; const queryMethod = "POST";
const exportMethod = "POST"; const exportMethod = "POST";
const invoiceMethod = "POST"; const invoiceMethod = "POST";
const rejectMethod = "POST";
const receivedMethod = "POST"; const receivedMethod = "POST";
const rejectMethod = "POST";
const reissueMethod = "POST";
export default function () { export default function () {
return { return {
@ -59,7 +64,7 @@ export default function () {
method: queryMethod, method: queryMethod,
hasFilter: true, hasFilter: true,
schema: { schema: {
title: "结算数据", title: "商务审批",
type: "object", type: "object",
properties: { properties: {
filters: { filters: {
@ -117,12 +122,14 @@ export default function () {
edit: { edit: {
exportUrl, exportUrl,
invoiceUrl, invoiceUrl,
rejectUrl,
receivedUrl, receivedUrl,
rejectUrl,
reissueUrl,
exportMethod, exportMethod,
invoiceMethod, invoiceMethod,
rejectMethod,
receivedMethod, receivedMethod,
rejectMethod,
reissueMethod,
schema: schema, schema: schema,
}, },
}; };

9
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/router/business.js

@ -3857,6 +3857,15 @@ export default [
isTop: true, isTop: true,
}, },
}, },
{
path: "import",
meta: {
type: "button",
title: "导入",
icon: "file",
isTop: true,
},
},
], ],
}, },
], ],

473
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/_check.js

@ -0,0 +1,473 @@
import html from "html";
import { schemaToModel } from "html";
import { ref, defineModel, nextTick, onMounted, watch } from "vue";
import request from "../request/index.js";
import AppForm from "../components/form/index.js";
import AppTable from "../components/table/index.js";
export default {
components: { AppForm, AppTable },
template: html`<el-drawer
v-model="show"
destroy-on-close
size="50%"
class="page-drawer"
:close-on-click-modal="false"
>
<template #header> <span class="el-dialog__title"> 结算明细 </span> </template>
<el-row style="height:calc(100vh - 160px);" v-loading="loading">
<el-col>
<el-tabs>
<el-tab-pane label="发票和结算分组对应关系" v-if="model.invoicE_MAP_GROUP.length">
<el-scrollbar>
<app-table :data="model.invoicE_MAP_GROUP" :columns="columns2" />
</el-scrollbar>
</el-tab-pane>
<el-tab-pane label="发票明细" v-if="model.invoicE_WAIT_DETAIL.length">
<el-scrollbar>
<app-table :data="model.invoicE_WAIT_DETAIL" :columns="columns1" />
</el-scrollbar>
</el-tab-pane>
<el-tab-pane label="已结分组包含不可结算零件" v-if="model.invoicE_NOT_SETTLE.length">
<el-scrollbar>
<app-table :data="model.invoicE_NOT_SETTLE" :columns="columns3" />
</el-scrollbar>
</el-tab-pane>
<el-tab-pane label="发票调整明细" v-if="model.adJ_DETAIL.length">
<el-scrollbar>
<app-table :data="model.adJ_DETAIL" :columns="columns4" />
</el-scrollbar>
</el-tab-pane>
</el-tabs>
</el-col>
</el-row>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="show=false"> 返回 </el-button>
<el-button
type="primary"
@click="showSetupDialog"
v-if="isBusiness&&data.invbillNum&&model.adJ_DETAIL.length===0"
>
重开发票
</el-button>
</span>
</template>
</el-drawer>
<el-dialog
class="re-open"
v-model="setupDialogVisable"
:close-on-click-modal="false"
align-center
destroy-on-close
style="width:50%;height:80%"
>
<template #header>发票重开</template>
<el-steps :active="setupRef" align-center style="height:60px;">
<el-step title="调整明细列表" />
<el-step title="发票明细对比" />
<el-step title="发票预览" />
</el-steps>
<div v-show="setupRef===1" style="height:100%;">
<el-row style="padding:14px 0;height:60px;">
<el-col>
<el-button type="primary" @click="showAddAdjDialog">新建</el-button>
<el-button type="primary" @click="showImportAdjDialog">导入</el-button>
<el-button type="primary" @click="deleteAdj">删除</el-button>
</el-col>
</el-row>
<el-scrollbar ref="scrollRef">
<el-row style="height:100%;">
<el-col style="height:calc(100% - 180px);">
<app-table ref="adjListRef" :data="adjList" :columns="columns5" />
</el-col>
</el-row>
</el-scrollbar>
</div>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="setupRef-=1" v-if="setupRef>1">上一步</el-button>
</span>
<span class="dialog-footer">
<el-button type="primary" @click="setupRef+=1" v-if="setupRef<3">下一步</el-button>
<el-button type="primary" @click="submitReOpen" v-if="setupRef===3">确定</el-button>
</span>
</template>
</el-dialog>
<el-dialog
v-model="addDialogVisible"
align-center
destroy-on-close
:close-on-click-modal="false"
style="width:380px;height:480px;"
>
<template #header>添加调整明细</template>
<el-scrollbar>
<el-row>
<el-col>
<app-form
ref="addAdjFormRef"
v-if="addDialogVisible&&adjModel"
:schema="adjSchema"
v-model="adjModel"
:hideButton="true"
:close-on-click-modal="false"
inline
/>
</el-col>
</el-row>
</el-scrollbar>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="addAdj">确定</el-button>
</span>
</template>
</el-dialog>
<el-dialog
style="width:380px;height:480px;"
align-center
destroy-on-close
:close-on-click-modal="false"
v-model="importDialogVisible"
>
<template #header>导入调整明细</template>
<el-scrollbar>
<el-row v-loading="loading">
<el-col>
<app-form
ref="importAdjFromRef"
v-if="importDialogVisible&&importAdjModel"
:schema="importAdjSchema"
v-model="importAdjModel"
:hideButton="true"
inline
/>
</el-col>
</el-row>
</el-scrollbar>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" :disabled="loading" @click="importAdj">确定</el-button>
</span>
</template>
</el-dialog>`,
styles: html` <style>
.page-drawer .el-tab-pane {
width: 100%;
height: calc(100vh - 160px);
}
.page-drawer .el-tabs__content,
.page-drawer .el-scrollbar {
width: 100%;
height: calc(100vh - 160px - 40px);
}
.re-open .el-dialog__footer {
display: flex;
justify-content: space-between;
}
.el-dialog__body {
height: calc(100% - 120px);
}
.re-open .el-scrollbar,
.re-open .el-scrollbar__view {
height: calc(100% - 120px);
}
</style>`,
props: ["modelValue", "data", "isBusiness"],
emit: ["update:modelValue"],
setup(props, context) {
const show = ref(props.modelValue);
watch(show, (value) => context.emit("update:modelValue", value));
const loading = ref(false);
const model = ref({
invoicE_WAIT_DETAIL: [],
invoicE_MAP_GROUP: [],
invoicE_NOT_SETTLE: [],
adJ_DETAIL: [],
});
//
const columns1 = [
{
dataKey: "version",
title: "期间",
},
{
dataKey: "invbillNum",
title: "发票号",
},
{
dataKey: "invGroupNum",
title: "发票分组号",
},
{
dataKey: "settleGroupNum",
title: "结算分组号",
},
{
dataKey: "amt",
title: "金额",
},
];
const columns2 = [
{
key: "version",
dataKey: "version",
title: "期间",
},
{
dataKey: "invbillNum",
title: "发票号",
},
{
dataKey: "invGroupNum",
title: "发票分组号",
},
{
dataKey: "lu",
title: "零件号",
},
{
dataKey: "price",
title: "单价",
},
{
dataKey: "qty",
title: "数量",
},
{
dataKey: "amt",
title: "金额",
},
{
dataKey: "bussiessType",
title: "业务分类",
},
];
const columns3 = [
{
dataKey: "version",
title: "期间",
},
{
dataKey: "invGroupNum",
title: "发票分组号",
},
{
dataKey: "settleGroupNum",
title: "结算分组号",
},
{
dataKey: "lu",
title: "可结算分组号",
},
{
dataKey: "lu1",
title: "不可结算分组号",
},
];
const columns4 = [
{
dataKey: "oldInvBillNum",
title: "作废发票号",
},
{
dataKey: "invBillNum",
title: "发票号",
},
{
dataKey: "settleDate",
title: "下线日期",
},
{
dataKey: "invGroupNum",
title: "发票分组号",
},
{
dataKey: "lu",
title: "零件号",
},
{
dataKey: "pn",
title: "标识号",
},
{
dataKey: "qty",
title: "数量",
},
{
dataKey: "groupNum",
title: "结算分组",
},
];
const columns5 = columns4.filter((o) => o.dataKey !== "oldInvBillNum" && o.dataKey !== "invGroupNum");
columns5.unshift({
input: "selection",
});
//显示重开发票对话框
const setupDialogVisable = ref(false);
const setupRef = ref(1);
const adjList = ref([]);
const scrollRef = ref(null);
const adjListRef = ref(null);
const addDialogVisible = ref(false);
const importDialogVisible = ref(false);
const showSetupDialog = () => {
adjList.value = [];
setupRef.value = 1;
setupDialogVisable.value = true;
};
const deleteAdj = () => {
const list = adjListRef.value.getSelection();
if (list.length > 0) {
for (let i = 0; i < list.length; i++) {
adjList.value.splice(list[i] - i, 1);
}
nextTick(() => {
adjListRef.value.clearSelection();
scrollRef.value.update();
});
}
};
const adjSchema = {
type: "object",
properties: {
invBillNum: {
type: "string",
title: "发票号",
rules: [{ required: true }],
},
settleDate: {
type: "string",
title: "下线日期",
input: "datetime",
rules: [{ required: true }],
},
lu: {
type: "string",
title: "零件号",
rules: [{ required: true }],
},
pn: {
type: "string",
title: "标识号",
rules: [{ required: true }],
},
qty: {
type: "string",
title: "数量",
input: "number",
rules: [{ required: true }],
},
groupNum: {
type: "string",
title: "结算分组",
rules: [{ required: true }],
},
},
};
const defaultAdjModel = schemaToModel(adjSchema);
const adjModel = ref(Object.assign({}, defaultAdjModel));
const addAdjFormRef = ref(null);
const showAddAdjDialog = () => {
adjModel.value = Object.assign({}, defaultAdjModel);
addDialogVisible.value = true;
};
const addAdj = async () => {
try {
const valid = await addAdjFormRef.value.validate();
if (valid) {
adjList.value.unshift(adjModel.value);
addDialogVisible.value = false;
}
} catch (error) {
console.log(error);
}
};
const importAdjFromRef = ref(null);
const importAdjSchema = {
type: "object",
properties: {
files: {
title: "文件",
type: "array",
multiple: true,
input: "file",
accept: ".xlsx",
default: [],
limit: 1,
size: 100 * 1024 * 1024,
rules: [
{
required: true,
trigger: "change",
},
],
},
},
};
const defaultImportAdjModel = schemaToModel(importAdjSchema);
const importAdjModel = ref(defaultImportAdjModel);
const showImportAdjDialog = async () => {
importAdjModel.value = Object.assign({}, defaultImportAdjModel);
importDialogVisible.value = true;
};
const importAdj = async () => {
try {
const valid = await importAdjFromRef.value.validate();
if (valid) {
loading.value = true;
const url = "settleaccount/vmi/excel-to-json";
const formData = new FormData();
formData.append("files", importAdjModel.value.files[0].raw);
const result = await request(url, formData);
if (!result.errors) {
adjList.value = result.data;
importDialogVisible.value = false;
}
}
} catch (error) {
console.log(error);
} finally {
loading.value = false;
}
};
const submitReOpen = async () => {};
//
onMounted(async () => {
loading.value = true;
const response = await request("settleaccount/invoice_service/detail-query", props.data, { method: "POST" });
model.value = response.data;
loading.value = false;
});
return {
show,
loading,
model,
columns1,
columns2,
columns3,
columns4,
columns4,
columns5,
showSetupDialog,
setupRef,
setupDialogVisable,
adjList,
adjListRef,
deleteAdj,
showAddAdjDialog,
addDialogVisible,
addAdj,
addAdjFormRef,
importAdjFromRef,
adjSchema,
adjModel,
showImportAdjDialog,
importDialogVisible,
importAdjModel,
importAdjSchema,
importAdj,
scrollRef,
};
},
};

13
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/bj/settlement/bj_pub_ba_service.js

@ -1,16 +1,23 @@
import AppList from "../../../components/list/index.js"; import AppList from "../../../components/list/index.js";
import html from "html"; import html from "html";
import { ref } from "vue";
import useConfig from "../../../models/pub_ba_service.js"; import useConfig from "../../../models/pub_ba_service.js";
import AppCheck from "../../_check.js";
export default { export default {
components: { AppList }, components: { AppList, AppCheck },
template: html`<app-list :config="config" @command="onCommand" />`, template: html`<app-list :config="config" @command="onCommand" />
<app-check v-if="visable" v-model="visable" :data="data" :isBusiness="true" />`,
setup() { setup() {
const config = useConfig(); const config = useConfig();
const visable = ref(false);
const data = ref(null);
const onCommand = async (item, rows) => { const onCommand = async (item, rows) => {
data.value = { [item.path]: rows[0][item.path] };
visable.value = true;
console.log(item.path, item, rows); console.log(item.path, item, rows);
}; };
config.query.schema.properties.businessType.default = "BeiJian"; config.query.schema.properties.businessType.default = "BeiJian";
return { config, onCommand }; return { config, onCommand, visable, data };
}, },
}; };

13
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/in/settlement/in_pub_ba_service.js

@ -1,16 +1,23 @@
import AppList from "../../../components/list/index.js"; import AppList from "../../../components/list/index.js";
import html from "html"; import html from "html";
import { ref } from "vue";
import useConfig from "../../../models/pub_ba_service.js"; import useConfig from "../../../models/pub_ba_service.js";
import AppCheck from "../../_check.js";
export default { export default {
components: { AppList }, components: { AppList, AppCheck },
template: html`<app-list :config="config" @command="onCommand" />`, template: html`<app-list :config="config" @command="onCommand" />
<app-check v-if="visable" v-model="visable" :data="data" :isBusiness="true" />`,
setup() { setup() {
const config = useConfig(); const config = useConfig();
const visable = ref(false);
const data = ref(null);
const onCommand = async (item, rows) => { const onCommand = async (item, rows) => {
data.value = { [item.path]: rows[0][item.path] };
visable.value = true;
console.log(item.path, item, rows); console.log(item.path, item, rows);
}; };
config.query.schema.properties.businessType.default = "YinDuJian"; config.query.schema.properties.businessType.default = "YinDuJian";
return { config, onCommand }; return { config, onCommand, visable, data };
}, },
}; };

486
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/invoice/invoice_map_group.js

@ -1,489 +1,23 @@
import AppList from "../../../components/list/index.js"; import AppList from "../../../components/list/index.js";
import AppForm from "../../../components/form/index.js"; import AppForm from "../../../components/form/index.js";
import html from "html"; import html from "html";
import { ref, nextTick } from "vue"; import { ref } from "vue";
import useConfig from "../../../models/invoice/invoice_map_group.js"; import useConfig from "../../../models/invoice/invoice_map_group.js";
import request from "../../../request/index.js"; import AppCheck from "../_check.js";
import AppTable from "../../components/table/index.js";
import { post } from "../../../request/index.js";
import { schemaToModel } from "html";
export default { export default {
components: { AppList, AppForm, AppTable }, components: { AppList, AppForm, AppCheck },
template: html`<app-list :config="config" @command="onCommand" /> template: html`<app-list :config="config" @command="onCommand" />
<el-drawer v-model="drawer" destroy-on-close size="50%" class="page-drawer" :close-on-click-modal="false"> <app-check v-if="visable" v-model="visable" :data="data" />`,
<template #header> <span class="el-dialog__title"> 结算明细 </span> </template>
<el-row style="height:calc(100vh - 160px);" v-loading="loading">
<el-col>
<el-tabs>
<el-tab-pane label="发票和结算分组对应关系" v-if="model.invoicE_MAP_GROUP.length">
<el-scrollbar>
<app-table :data="model.invoicE_MAP_GROUP" :columns="columns2" />
</el-scrollbar>
</el-tab-pane>
<el-tab-pane label="发票明细" v-if="model.invoicE_WAIT_DETAIL.length">
<el-scrollbar>
<app-table :data="model.invoicE_WAIT_DETAIL" :columns="columns1" />
</el-scrollbar>
</el-tab-pane>
<el-tab-pane label="已结分组包含不可结算零件" v-if="model.invoicE_NOT_SETTLE.length">
<el-scrollbar>
<app-table :data="model.invoicE_NOT_SETTLE" :columns="columns3" />
</el-scrollbar>
</el-tab-pane>
<el-tab-pane label="发票调整明细" v-if="model.adJ_DETAIL.length">
<el-scrollbar>
<app-table :data="model.adJ_DETAIL" :columns="columns4" />
</el-scrollbar>
</el-tab-pane>
</el-tabs>
</el-col>
</el-row>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="drawer=false"> 返回 </el-button>
<el-button type="primary" @click="showSetupDialog" v-if="model.adJ_DETAIL.length===0&&prop==='invbillNum'">
重开发票
</el-button>
</span>
</template>
</el-drawer>
<el-dialog
class="re-open"
v-model="dialogVisible"
:close-on-click-modal="false"
align-center
destroy-on-close
style="width:50%;height:80%"
>
<template #header>发票重开</template>
<el-steps :active="setupRef" align-center style="height:60px;">
<el-step title="调整明细列表" />
<el-step title="发票明细对比" />
<el-step title="发票预览" />
</el-steps>
<div v-show="setupRef===1" style="height:100%;">
<el-row style="padding:14px 0;height:60px;">
<el-col>
<el-button type="primary" @click="showAddAdjDialog">新建</el-button>
<el-button type="primary" @click="showImportAdjDialog">导入</el-button>
<el-button type="primary" @click="deleteAdj">删除</el-button>
</el-col>
</el-row>
<el-scrollbar ref="scrollRef">
<el-row style="height:100%;">
<el-col style="height:calc(100% - 180px);">
<app-table ref="adjListRef" :data="adjList" :columns="columns5" />
</el-col>
</el-row>
</el-scrollbar>
</div>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="setupRef-=1" v-if="setupRef>1">上一步</el-button>
</span>
<span class="dialog-footer">
<el-button type="primary" @click="setupRef+=1" v-if="setupRef<3">下一步</el-button>
<el-button type="primary" @click="submitReOpen" v-if="setupRef===3">确定</el-button>
</span>
</template>
</el-dialog>
<el-dialog
v-model="addDialogVisible"
align-center
destroy-on-close
:close-on-click-modal="false"
style="width:380px;height:480px;"
>
<template #header>添加调整明细</template>
<el-scrollbar>
<el-row>
<el-col>
<app-form
ref="addAdjFormRef"
v-if="addDialogVisible&&adjModel"
:schema="adjSchema"
v-model="adjModel"
:hideButton="true"
:close-on-click-modal="false"
inline
/>
</el-col>
</el-row>
</el-scrollbar>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="addAdj">确定</el-button>
</span>
</template>
</el-dialog>
<el-dialog
style="width:380px;height:480px;"
align-center
destroy-on-close
:close-on-click-modal="false"
v-model="importDialogVisible"
>
<template #header>导入调整明细</template>
<el-scrollbar>
<el-row v-loading="loading">
<el-col>
<app-form
ref="importAdjFromRef"
v-if="importDialogVisible&&importAdjModel"
:schema="importAdjSchema"
v-model="importAdjModel"
:hideButton="true"
inline
/>
</el-col>
</el-row>
</el-scrollbar>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" :disabled="loading" @click="importAdj">确定</el-button>
</span>
</template>
</el-dialog>`,
styles: html` <style>
.page-drawer .el-tab-pane {
width: 100%;
height: calc(100vh - 160px);
}
.page-drawer .el-tabs__content,
.page-drawer .el-scrollbar {
width: 100%;
height: calc(100vh - 160px - 40px);
}
.re-open .el-dialog__footer {
display: flex;
justify-content: space-between;
}
.el-dialog__body {
height: calc(100% - 120px);
}
.re-open .el-scrollbar,
.re-open .el-scrollbar__view {
height: calc(100% - 120px);
}
</style>`,
setup() { setup() {
const fileList = ref([]);
const openImportHandler = async () => {
const url = "settleaccount/vmi/excel-to-json";
const method = "POST";
const formData = new FormData();
if (config.query.schema.properties.businessType?.default) {
formData.append("businessType", config.query.schema.properties.businessType.default);
}
for (let i = 0; i < fileList.value.length; i++) {
formData.append(`files`, fileList.value[i].raw);
}
await post(url, formData, method);
};
//create
const invoiceValue = ref([]);
const addDialogVisible = ref(false);
const importDialogVisible = ref(false);
const dialogVisible = ref(false);
const config = useConfig(); const config = useConfig();
const drawer = ref(false); const visable = ref(false);
const loading = ref(false); const data = ref(null);
const model = ref({
invoicE_WAIT_DETAIL: [],
invoicE_MAP_GROUP: [],
invoicE_NOT_SETTLE: [],
adJ_DETAIL: [],
});
const prop = ref("");
const onCommand = async (item, rows) => { const onCommand = async (item, rows) => {
prop.value = item.path; data.value = { [item.path]: rows[0][item.path] };
drawer.value = true; visable.value = true;
loading.value = true; console.log(item.path, item, rows);
const data = { [item.path]: rows[0][item.path] };
const response = await request("settleaccount/invoice_service/detail-query", data, { method: "POST" });
model.value = response.data;
loading.value = false;
};
const columns1 = [
{
dataKey: "version",
title: "期间",
},
{
dataKey: "invbillNum",
title: "发票号",
},
{
dataKey: "invGroupNum",
title: "发票分组号",
},
{
dataKey: "settleGroupNum",
title: "结算分组号",
},
{
dataKey: "amt",
title: "金额",
},
];
const columns2 = [
{
key: "version",
dataKey: "version",
title: "期间",
},
{
dataKey: "invbillNum",
title: "发票号",
},
{
dataKey: "invGroupNum",
title: "发票分组号",
},
{
dataKey: "lu",
title: "零件号",
},
{
dataKey: "price",
title: "单价",
},
{
dataKey: "qty",
title: "数量",
},
{
dataKey: "amt",
title: "金额",
},
{
dataKey: "bussiessType",
title: "业务分类",
},
];
const columns3 = [
{
dataKey: "version",
title: "期间",
},
{
dataKey: "invGroupNum",
title: "发票分组号",
},
{
dataKey: "settleGroupNum",
title: "结算分组号",
},
{
dataKey: "lu",
title: "可结算分组号",
},
{
dataKey: "lu1",
title: "不可结算分组号",
},
];
const columns4 = [
{
dataKey: "oldInvBillNum",
title: "作废发票号",
},
{
dataKey: "invBillNum",
title: "发票号",
},
{
dataKey: "settleDate",
title: "下线日期",
},
{
dataKey: "invGroupNum",
title: "发票分组号",
},
{
dataKey: "lu",
title: "零件号",
},
{
dataKey: "pn",
title: "标识号",
},
{
dataKey: "qty",
title: "数量",
},
{
dataKey: "groupNum",
title: "结算分组",
},
];
const columns5 = columns4.filter((o) => o.dataKey !== "oldInvBillNum" && o.dataKey !== "invGroupNum");
columns5.unshift({
input: "selection",
});
//
const setupRef = ref(1);
const scrollRef = ref(null);
const adjListRef = ref(null);
const adjList = ref([]);
const showSetupDialog = () => {
adjList.value = [];
for (let i = 0; i < 10; i++) {
adjList.value.push({ invBillNum: i });
}
setupRef.value = 1;
dialogVisible.value = true;
};
const deleteAdj = () => {
const list = adjListRef.value.getSelection();
if (list.length > 0) {
for (let i = 0; i < list.length; i++) {
adjList.value.splice(list[i] - i, 1);
}
nextTick(() => {
adjListRef.value.clearSelection();
scrollRef.value.update();
});
}
};
const adjSchema = {
type: "object",
properties: {
invBillNum: {
type: "string",
title: "发票号",
rules: [{ required: true }],
},
settleDate: {
type: "string",
title: "下线日期",
input: "datetime",
rules: [{ required: true }],
},
lu: {
type: "string",
title: "零件号",
rules: [{ required: true }],
},
pn: {
type: "string",
title: "标识号",
rules: [{ required: true }],
},
qty: {
type: "string",
title: "数量",
input: "number",
rules: [{ required: true }],
},
groupNum: {
type: "string",
title: "结算分组",
rules: [{ required: true }],
},
},
};
const defaultAdjModel = schemaToModel(adjSchema);
const adjModel = ref(Object.assign({}, defaultAdjModel));
const addAdjFormRef = ref(null);
const showAddAdjDialog = () => {
adjModel.value = Object.assign({}, defaultAdjModel);
addDialogVisible.value = true;
};
const addAdj = async () => {
try {
const valid = await addAdjFormRef.value.validate();
if (valid) {
adjList.value.unshift(adjModel.value);
addDialogVisible.value = false;
}
} catch (error) {
console.log(error);
}
};
const importAdjFromRef = ref(null);
const importAdjSchema = {
type: "object",
properties: {
files: {
title: "文件",
type: "array",
multiple: true,
input: "file",
accept: ".xlsx",
default: [],
limit: 1,
size: 100 * 1024 * 1024,
rules: [
{
required: true,
trigger: "change",
},
],
},
},
};
const defaultImportAdjModel = schemaToModel(importAdjSchema);
const importAdjModel = ref(defaultImportAdjModel);
const showImportAdjDialog = async () => {
importAdjModel.value = Object.assign({}, defaultImportAdjModel);
importDialogVisible.value = true;
};
const importAdj = async () => {
try {
const valid = await importAdjFromRef.value.validate();
if (valid) {
loading.value = true;
const url = "settleaccount/vmi/excel-to-json";
const formData = new FormData();
formData.append("files", importAdjModel.value.files[0].raw);
const result = await request(url, formData);
if (!result.errors) {
adjList.value = result.data;
importDialogVisible.value = false;
}
}
} catch (error) {
console.log(error);
} finally {
loading.value = false;
}
};
return {
config,
onCommand,
drawer,
loading,
model,
columns1,
columns2,
columns3,
columns4,
columns4,
columns5,
addDialogVisible,
dialogVisible,
prop,
invoiceValue,
importDialogVisible,
openImportHandler,
setupRef,
showSetupDialog,
adjList,
adjListRef,
deleteAdj,
showAddAdjDialog,
addAdj,
addAdjFormRef,
importAdjFromRef,
adjSchema,
adjModel,
showImportAdjDialog,
importAdjModel,
importAdjSchema,
importAdj,
scrollRef,
}; };
return { config, onCommand, visable, data };
}, },
}; };

15
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/jis-bbac/settlement/bbac_ba_service.js

@ -1,16 +1,23 @@
import AppList from "../../../components/list/index.js"; import AppList from "../../../components/list/index.js";
import html from "html"; import html from "html";
import useConfig from "../../../models/jis-bbac/settlement/bbac_ba_service.js"; import { ref } from "vue";
import useConfig from "../../../models/pub_ba_service.js";
import AppCheck from "../../_check.js";
export default { export default {
components: { AppList }, components: { AppList, AppCheck },
template: html`<app-list :config="config" @command="onCommand" />`, template: html`<app-list :config="config" @command="onCommand" />
<app-check v-if="visable" v-model="visable" :data="data" :isBusiness="true" />`,
setup() { setup() {
const config = useConfig(); const config = useConfig();
const visable = ref(false);
const data = ref(null);
const onCommand = async (item, rows) => { const onCommand = async (item, rows) => {
data.value = { [item.path]: rows[0][item.path] };
visable.value = true;
console.log(item.path, item, rows); console.log(item.path, item, rows);
}; };
config.query.schema.properties.businessType.default = "JisBBAC"; config.query.schema.properties.businessType.default = "JisBBAC";
return { config, onCommand }; return { config, onCommand, visable, data };
}, },
}; };

15
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/jis-hbpo/settlement/hbpo_ba_service.js

@ -1,16 +1,23 @@
import AppList from "../../../components/list/index.js"; import AppList from "../../../components/list/index.js";
import html from "html"; import html from "html";
import useConfig from "../../../models/jis-hbpo/settlement/hbpo_ba_service.js"; import { ref } from "vue";
import useConfig from "../../../models/pub_ba_service.js";
import AppCheck from "../../_check.js";
export default { export default {
components: { AppList }, components: { AppList, AppCheck },
template: html`<app-list :config="config" @command="onCommand" />`, template: html`<app-list :config="config" @command="onCommand" />
<app-check v-if="visable" v-model="visable" :data="data" :isBusiness="true" />`,
setup() { setup() {
const config = useConfig(); const config = useConfig();
const visable = ref(false);
const data = ref(null);
const onCommand = async (item, rows) => { const onCommand = async (item, rows) => {
data.value = { [item.path]: rows[0][item.path] };
visable.value = true;
console.log(item.path, item, rows); console.log(item.path, item, rows);
}; };
config.query.schema.properties.businessType.default = "JisHBPO"; config.query.schema.properties.businessType.default = "JisHBPO";
return { config, onCommand }; return { config, onCommand, visable, data };
}, },
}; };

15
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/jit/jit-bbac/settlement/bbac_jit_pub_ba_service.js

@ -1,16 +1,23 @@
import AppList from "../../../../components/list/index.js"; import AppList from "../../../../components/list/index.js";
import html from "html"; import html from "html";
import { ref } from "vue";
import useConfig from "../../../../models/pub_ba_service.js"; import useConfig from "../../../../models/pub_ba_service.js";
import AppCheck from "../../../_check.js";
export default { export default {
components: { AppList }, components: { AppList, AppCheck },
template: html`<app-list :config="config" @command="onCommand" />`, template: html`<app-list :config="config" @command="onCommand" />
<app-check v-if="visable" v-model="visable" :data="data" :isBusiness="true" />`,
setup() { setup() {
const config = useConfig(); const config = useConfig();
const visable = ref(false);
const data = ref(null);
const onCommand = async (item, rows) => { const onCommand = async (item, rows) => {
data.value = { [item.path]: rows[0][item.path] };
visable.value = true;
console.log(item.path, item, rows); console.log(item.path, item, rows);
}; };
config.query.schema.properties.businessType.default = "ZhiGongJianBBAC"; config.query.schema.properties.businessType.default = "ZhiGongJianBBAC";
return { config, onCommand }; return { config, onCommand, visable, data };
}, },
}; };

13
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/jit/jit-hbpo/settlement/hbpo_jit_pub_ba_service.js

@ -1,16 +1,23 @@
import AppList from "../../../../components/list/index.js"; import AppList from "../../../../components/list/index.js";
import html from "html"; import html from "html";
import { ref } from "vue";
import useConfig from "../../../../models/pub_ba_service.js"; import useConfig from "../../../../models/pub_ba_service.js";
import AppCheck from "../../../_check.js";
export default { export default {
components: { AppList }, components: { AppList, AppCheck },
template: html`<app-list :config="config" @command="onCommand" />`, template: html`<app-list :config="config" @command="onCommand" />
<app-check v-if="visable" v-model="visable" :data="data" :isBusiness="true" />`,
setup() { setup() {
const config = useConfig(); const config = useConfig();
const visable = ref(false);
const data = ref(null);
const onCommand = async (item, rows) => { const onCommand = async (item, rows) => {
data.value = { [item.path]: rows[0][item.path] };
visable.value = true;
console.log(item.path, item, rows); console.log(item.path, item, rows);
}; };
config.query.schema.properties.businessType.default = "ZhiGongJianHBPO"; config.query.schema.properties.businessType.default = "ZhiGongJianHBPO";
return { config, onCommand }; return { config, onCommand, visable, data };
}, },
}; };

13
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/md/md-hbpo/settlement/hbpo_md_pub_ba_service.js

@ -1,16 +1,23 @@
import AppList from "../../../../components/list/index.js"; import AppList from "../../../../components/list/index.js";
import html from "html"; import html from "html";
import { ref } from "vue";
import useConfig from "../../../../models/pub_ba_service.js"; import useConfig from "../../../../models/pub_ba_service.js";
import AppCheck from "../../../_check.js";
export default { export default {
components: { AppList }, components: { AppList, AppCheck },
template: html`<app-list :config="config" @command="onCommand" />`, template: html`<app-list :config="config" @command="onCommand" />
<app-check v-if="visable" v-model="visable" :data="data" :isBusiness="true" />`,
setup() { setup() {
const config = useConfig(); const config = useConfig();
const visable = ref(false);
const data = ref(null);
const onCommand = async (item, rows) => { const onCommand = async (item, rows) => {
data.value = { [item.path]: rows[0][item.path] };
visable.value = true;
console.log(item.path, item, rows); console.log(item.path, item, rows);
}; };
config.query.schema.properties.businessType.default = "MaiDanJianHBPO"; config.query.schema.properties.businessType.default = "MaiDanJianHBPO";
return { config, onCommand }; return { config, onCommand, visable, data };
}, },
}; };

102
code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAppService.cs

@ -360,42 +360,6 @@ public class VmiAppService : ApplicationService, IVmiService, IJobService, ITran
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
///// <summary>
///// 库存事务回滚
///// </summary>
//[NonAction]
//[UnitOfWork]
//public async Task UnDo(string groupId)
//{
// var logList = this._logRepository.Where(o => o.GroupId == groupId).AsNoTracking().OrderBy(o => o.ChangedTime);
// foreach (var item in logList)
// {
// var balance = this._balanceRepository.FirstOrDefault(o => o.BillType == item.BillType &&
// o.PartCode == item.PartCode &&
// o.VinCode == item.VinCode &&
// o.ErpToLoc == item.ErpToLoc &&
// o.OrderNum == item.OrderNum);
// if (balance == null)
// {
// balance = new VmiBalance(GuidGenerator.Create());
// balance.InjectFrom(item);
// await _balanceRepository.InsertAsync(balance).ConfigureAwait(false);
// }
// else
// {
// balance.Qty += item.ChangedQty;
// this._balanceRepository.UpdateAsync(balance).Wait();
// }
// var log = new VmiLog();
// log.InjectFrom(item);
// log.LogType = VmiLogType.Type300;
// log.ChangedType = VmiType.In;
// log.ChangedTime = DateTime.Now;
// log.ChangedBy = _currentUser.UserName;
// await _logRepository.InsertAsync(log).ConfigureAwait(false);
// }
//}
/// <summary> /// <summary>
/// 库存余额查询 /// 库存余额查询
/// </summary> /// </summary>
@ -491,6 +455,47 @@ public class VmiAppService : ApplicationService, IVmiService, IJobService, ITran
return new PagedResultDto<VmiLog>(count, entities); return new PagedResultDto<VmiLog>(count, entities);
} }
/// <summary>
/// 人工调整
/// </summary>
/// <param name="log"></param>
/// <returns></returns>
[HttpPost]
public async Task EditBalance(VmiLog log)
{
if (log.Qty >= decimal.Zero)
{
log.LogType = VmiLogType.Type500;
log.ChangedType = VmiType.In;
var data = new VmiBalance();
data.InjectFrom(log);
await In(VmiLogType.Type500, null, data).ConfigureAwait(false);
}
else
{
log.LogType = VmiLogType.Type600;
log.ChangedType = VmiType.Out;
log.Qty = -log.Qty;
await this.Out(VmiLogType.Type600, null, log).ConfigureAwait(false);
}
}
/// <summary>
/// 库存调整导入
/// </summary>
/// <param name="files"></param>
[HttpPost]
public async Task Import(List<IFormFile> files)
{
using var ms = new MemoryStream();
await files.FirstOrDefault().OpenReadStream().CopyToAsync(ms).ConfigureAwait(false);
var list = this.ImportInternal<VmiLog>(ms.ToArray());
foreach (var file in list)
{
await EditBalance(file).ConfigureAwait(false);
}
}
/// <summary> /// <summary>
/// 快照列表 /// 快照列表
/// </summary> /// </summary>
@ -537,31 +542,6 @@ public class VmiAppService : ApplicationService, IVmiService, IJobService, ITran
return fileName; return fileName;
} }
/// <summary>
/// 人工调整
/// </summary>
/// <param name="log"></param>
/// <returns></returns>
[HttpPost]
public async Task EditBalance(VmiLog log)
{
if (log.Qty >= decimal.Zero)
{
log.LogType = VmiLogType.Type500;
log.ChangedType = VmiType.In;
var data = new VmiBalance();
data.InjectFrom(log);
await In(VmiLogType.Type500, null, data).ConfigureAwait(false);
}
else
{
log.LogType = VmiLogType.Type600;
log.ChangedType = VmiType.Out;
log.Qty = -log.Qty;
await this.Out(VmiLogType.Type600, null, log).ConfigureAwait(false);
}
}
private byte[] GetContent<TExport>(List<TExport> entities, string name = "sheet1") private byte[] GetContent<TExport>(List<TExport> entities, string name = "sheet1")
{ {
using var workbook = new XLWorkbook(); using var workbook = new XLWorkbook();

Loading…
Cancel
Save