增加凭证批量提交功能。

This commit is contained in:
wuyan
2025-06-07 10:15:50 +08:00
parent fdf8ecaf29
commit 5e91f71089
10 changed files with 165 additions and 44 deletions

View File

@ -131,6 +131,17 @@ export function updateVoucherSuccessive(data: any): any {
}) })
} }
/**
* 批量提交凭证
* @param ids 凭证ID串
*/
export function submitBatch(ids: any): any {
return request({
url: '/voucher/submit/' + ids,
method: 'post'
})
}
/** /**
* 审核凭证 * 审核凭证
* @param ids * @param ids

View File

@ -16,7 +16,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {parseTime} from "@/utils/Jinbooks" import {parseTime} from "@/utils/Jinbooks"
import {ref, defineProps} from "vue"; import {ref} from "vue";
const version = ref(__APP_VERSION__) const version = ref(__APP_VERSION__)
const time = ref(parseTime(new Date(), "{y}")) const time = ref(parseTime(new Date(), "{y}"))

View File

@ -5,7 +5,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {computed, defineComponent, defineProps} from "vue" import {computed, defineComponent} from "vue"
import {isExternal} from '@/utils/Validate' import {isExternal} from '@/utils/Validate'
const props = defineProps({ const props = defineProps({

View File

@ -58,7 +58,12 @@
@click="handleAdd" @click="handleAdd"
>{{ t('org.button.add') }} >{{ t('org.button.add') }}
</el-button> </el-button>
<el-button
type="success"
:disabled="ids.length === 0"
@click="handleSubmit"
>提交
</el-button>
<el-button <el-button
type="success" type="success"
:disabled="ids.length === 0" :disabled="ids.length === 0"
@ -95,13 +100,14 @@
<el-table-column type="selection" width="55" align="center"/> <el-table-column type="selection" width="55" align="center"/>
<el-table-column label="凭证字" align="left" header-align="center" prop="word" width="150" fixed="left"/> <el-table-column label="凭证字" align="left" header-align="center" prop="word" width="150" fixed="left"/>
<!-- <el-table-column label="公司名称" align="center" prop="companyName" width="150"/>--> <!-- <el-table-column label="公司名称" align="center" prop="companyName" width="150"/>-->
<el-table-column label="备注" align="left" header-align="center" prop="remark" width="280" :show-overflow-tooltip="true"/> <el-table-column label="备注" align="left" header-align="center" prop="remark" width="280"
<el-table-column label="借方总额" align="right" header-align="center" prop="debitAmount" width="120"> :show-overflow-tooltip="true"/>
<el-table-column label="借方总额" align="right" header-align="center" prop="debitAmount" width="120">
<template #default="scope"> <template #default="scope">
{{ formatAmount(scope.row.debitAmount) }} {{ formatAmount(scope.row.debitAmount) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="贷方总额" align="right" header-align="center" prop="creditAmount" width="120"> <el-table-column label="贷方总额" align="right" header-align="center" prop="creditAmount" width="120">
<template #default="scope"> <template #default="scope">
{{ formatAmount(scope.row.creditAmount) }} {{ formatAmount(scope.row.creditAmount) }}
</template> </template>
@ -114,7 +120,7 @@
<el-table-column label="附单据" align="center" prop="receiptNum"/> <el-table-column label="附单据" align="center" prop="receiptNum"/>
<el-table-column label="结转" align="center" prop="carryForward"> <el-table-column label="结转" align="center" prop="carryForward">
<template #default="scope"> <template #default="scope">
<span v-if="scope.row.carryForward === 'y'"></span> <span v-if="scope.row.carryForward === 'y'"></span>
<span v-if="scope.row.carryForward === 'n'"></span> <span v-if="scope.row.carryForward === 'n'"></span>
</template> </template>
</el-table-column> </el-table-column>
@ -419,6 +425,22 @@ function submitForm(res) {
} }
} }
function handleSubmit(row) {
const _ids = row.id || ids.value.join(",");
const idList = _ids.split(",")
const submitIds = booksVoucherList.value.filter(item => {
return idList.indexOf(item.id) > -1 && 'draft' === item.status
}).map(item => item.id)
if (!submitIds.length) {
proxy.$modal.msgError("没有可以提交的凭证项。");
return
}
voucherApis.submitBatch(submitIds).then(res => {
getList();
proxy.$modal.msgSuccess("操作成功")
})
}
function handleAudit(row) { function handleAudit(row) {
const _ids = row.id || ids.value.join(","); const _ids = row.id || ids.value.join(",");
proxy.$modal.confirm('确认审核"' + _ids + '"等凭证?').then(function () { proxy.$modal.confirm('确认审核"' + _ids + '"等凭证?').then(function () {

View File

@ -21,6 +21,9 @@ package com.jinbooks.entity.dto;
import com.jinbooks.entity.PageQuery; import com.jinbooks.entity.PageQuery;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/** /**
* @description: * @description:
@ -28,10 +31,12 @@ import lombok.Data;
* @time: 2024/11/27 17:37 * @time: 2024/11/27 17:37
*/ */
@EqualsAndHashCode(callSuper = true)
@Data @Data
public class SocialsProviderPageDto extends PageQuery {/** public class SocialsProviderPageDto extends PageQuery {/**
* *
*/ */
@Serial
private static final long serialVersionUID = 6001449362547319688L; private static final long serialVersionUID = 6001449362547319688L;
} }

View File

@ -23,7 +23,10 @@ import com.jinbooks.validate.AddGroup;
import com.jinbooks.validate.EditGroup; import com.jinbooks.validate.EditGroup;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
@ -36,6 +39,9 @@ import java.util.List;
* {@code @date} 2025-01-14 * {@code @date} 2025-01-14
*/ */
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data @Data
public class VoucherChangeDto { public class VoucherChangeDto {
/** /**

View File

@ -23,7 +23,10 @@ import com.jinbooks.validate.AddGroup;
import com.jinbooks.validate.EditGroup; import com.jinbooks.validate.EditGroup;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
@ -38,6 +41,9 @@ import java.util.List;
* {@code @date} 2025-01-14 * {@code @date} 2025-01-14
*/ */
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data @Data
public class VoucherItemChangeDto implements Serializable { public class VoucherItemChangeDto implements Serializable {
@Serial @Serial

View File

@ -49,7 +49,7 @@ public interface VoucherService extends IService<Voucher> {
Message<Integer> getAbleWordNum(String bookId, String head, Integer year, Integer month); Message<Integer> getAbleWordNum(String bookId, String head, Integer year, Integer month);
Message<String> submit(VoucherChangeDto dto); Message<String> submit(VoucherChangeDto dto, boolean update);
Message<Integer> cancelByIds(List<String> ids, String bookId); Message<Integer> cancelByIds(List<String> ids, String bookId);
@ -78,4 +78,6 @@ public interface VoucherService extends IService<Voucher> {
void export(VoucherPageDto dto, HttpServletResponse response) throws IOException; void export(VoucherPageDto dto, HttpServletResponse response) throws IOException;
boolean deleteByBookIds(List<String> bookIds); boolean deleteByBookIds(List<String> bookIds);
Message<String> submitBatch(List<String> ids, String bookId);
} }

View File

@ -1,12 +1,12 @@
/* /*
* Copyright [2025] [JinBooks of copyright http://www.jinbooks.com] * Copyright [2025] [JinBooks of copyright http://www.jinbooks.com]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
* *
*/ */
package com.jinbooks.persistence.service.impl; package com.jinbooks.persistence.service.impl;
@ -309,24 +309,36 @@ public class VoucherServiceImpl extends ServiceImpl<VoucherMapper, Voucher> impl
/** /**
* 保存&提交 * 保存&提交
* *
* @param dto 数据对象 * @param dto 数据对象
* @param update 是否更新数据
* @return 结果 * @return 结果
*/ */
@Override @Override
@Transactional @Transactional
public Message<String> submit(VoucherChangeDto dto) { public Message<String> submit(VoucherChangeDto dto, boolean update) {
// 先执行暂存操作 if (StringUtils.isNotBlank(dto.getId())) {
dto.setStatus(VoucherStatusEnum.DRAFT.getValue()); Voucher voucher = baseMapper.selectById(dto.getId());
Message<String> saveRes; if (voucher == null) {
if (StringUtils.isEmpty(dto.getId())) { return Message.failed("凭证不存在");
saveRes = save(dto); }
} else { if (!VoucherStatusEnum.DRAFT.getValue().equals(voucher.getStatus())) {
saveRes = update(dto); return Message.failed("凭证已提交,不允许修改");
}
} }
if (saveRes.getCode() != Message.SUCCESS) { if (update) {
return saveRes; // 先执行暂存操作
dto.setStatus(VoucherStatusEnum.DRAFT.getValue());
Message<String> saveRes;
if (StringUtils.isEmpty(dto.getId())) {
saveRes = save(dto);
} else {
saveRes = update(dto);
}
if (saveRes.getCode() != Message.SUCCESS) {
return saveRes;
}
dto.setId(saveRes.getData());
} }
dto.setId(saveRes.getData());
// 只有当前期的凭证允许提交,因为会影响到余额数据 // 只有当前期的凭证允许提交,因为会影响到余额数据
String currentTerm = configSysService.getCurrentTerm(dto.getBookId()); String currentTerm = configSysService.getCurrentTerm(dto.getBookId());
@ -356,6 +368,52 @@ public class VoucherServiceImpl extends ServiceImpl<VoucherMapper, Voucher> impl
return updateResult; return updateResult;
} }
/**
* 批量提交
*
* @param ids ids
* @param bookId 账套id
* @return 批量提交结果
*/
@Override
@Transactional
public Message<String> submitBatch(List<String> ids, String bookId) {
if (ids.isEmpty()) {
return Message.failed("请选择要提交的凭证");
}
int count = 0;
// 遍历处理,保证每一个凭证顺序提交
for (String id : ids) {
Message<VoucherVo> infoRes = queryById(id);
if (infoRes.getCode() != Message.SUCCESS) {
return new Message<>(infoRes.getCode(), infoRes.getMessage());
}
VoucherVo voucherVo = infoRes.getData();
VoucherChangeDto dto = VoucherChangeDto.builder().build();
BeanUtils.copyProperties(voucherVo, dto);
List<VoucherItemVo> items = voucherVo.getItems();
if (items.isEmpty()) {
continue;
}
// 转换凭证项
List<VoucherItemChangeDto> voucherItemChangeDtos = items.stream().map(item -> {
VoucherItemChangeDto itemChangeDto = VoucherItemChangeDto.builder().build();
BeanUtils.copyProperties(item, itemChangeDto);
return itemChangeDto;
}).toList();
dto.setItems(voucherItemChangeDtos);
Message<String> submit = submit(dto, false);
if (submit.getCode() != Message.SUCCESS) {
return new Message<>(submit.getCode(), submit.getMessage() + " 成功提交" + count + "条。");
}
count++;
}
return new Message<>(Message.SUCCESS, "成功提交" + count + "条凭证, 忽略" + (ids.size() - count) + "");
}
/** /**
* 插入数据 * 插入数据
* *
@ -489,9 +547,9 @@ public class VoucherServiceImpl extends ServiceImpl<VoucherMapper, Voucher> impl
// 插入新数据 // 插入新数据
if (!insertItems.isEmpty()) { if (!insertItems.isEmpty()) {
// 只有审核完成,才更新余额 // 只有审核完成,才更新余额
if (VoucherStatusEnum.COMPLETED.getValue().equals(dto.getStatus())) { if (VoucherStatusEnum.COMPLETED.getValue().equals(dto.getStatus())) {
//if (VoucherStatusEnum.COMPLETED.getValue().equals(dto.getStatus()) //if (VoucherStatusEnum.COMPLETED.getValue().equals(dto.getStatus())
// && YesNoEnum.n.name().equals(booksVoucher.getCarryForward())) { // && YesNoEnum.n.name().equals(booksVoucher.getCarryForward())) {
updateSubjectBalance(insertItems, insertAuxiliary, false); updateSubjectBalance(insertItems, insertAuxiliary, false);
} }
boolean saveItems = voucherItemMapper.insertBatch(insertItems); boolean saveItems = voucherItemMapper.insertBatch(insertItems);
@ -1025,17 +1083,17 @@ public class VoucherServiceImpl extends ServiceImpl<VoucherMapper, Voucher> impl
/** /**
* 删除凭证及相关条目 * 删除凭证及相关条目
*/ */
@Override @Override
public boolean deleteByBookIds(List<String> bookIds) { public boolean deleteByBookIds(List<String> bookIds) {
//删除凭证 //删除凭证
LambdaQueryWrapper<Voucher> lqw = Wrappers.lambdaQuery(); LambdaQueryWrapper<Voucher> lqw = Wrappers.lambdaQuery();
lqw.in(Voucher::getBookId, bookIds); lqw.in(Voucher::getBookId, bookIds);
baseMapper.delete(lqw); baseMapper.delete(lqw);
//删除凭证条目 //删除凭证条目
LambdaQueryWrapper<VoucherItem> lqwItem = Wrappers.lambdaQuery(); LambdaQueryWrapper<VoucherItem> lqwItem = Wrappers.lambdaQuery();
lqwItem.in(VoucherItem::getBookId, bookIds); lqwItem.in(VoucherItem::getBookId, bookIds);
voucherItemMapper.delete(lqwItem); voucherItemMapper.delete(lqwItem);
return false; return false;
} }
} }

View File

@ -1,12 +1,12 @@
/* /*
* Copyright [2025] [JinBooks of copyright http://www.jinbooks.com] * Copyright [2025] [JinBooks of copyright http://www.jinbooks.com]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
* *
*/ */
package com.jinbooks.web.voucher.controller; package com.jinbooks.web.voucher.controller;
@ -153,7 +153,18 @@ public class VoucherController {
public Message<String> submit(@Validated @RequestBody VoucherChangeDto dto, public Message<String> submit(@Validated @RequestBody VoucherChangeDto dto,
@CurrentUser UserInfo userInfo) { @CurrentUser UserInfo userInfo) {
dto.setBookId(userInfo.getBookId()); dto.setBookId(userInfo.getBookId());
return voucherService.submit(dto); return voucherService.submit(dto, true);
}
/**
* 批量提交
*
* @param ids ids
*/
@PostMapping("/submit/{ids}")
public Message<String> submitBatch(@PathVariable(name = "ids") List<String> ids,
@CurrentUser UserInfo userInfo) {
return voucherService.submitBatch(ids, userInfo.getBookId());
} }
/** /**